OmniAICreator/Qiita-1.07M huggingface dataset:
Haskellで文字列っぽい型同士を結合する演算子が欲しい。その2(動作するところまでは行った)

[←前回の記事](http://qiita.com/saturday06/items/01d6ee082ca4cbbe0fd7)
# 前回までのあらすじ

Haskellで文字列っぽい型同士を結合する演算子`+++`が欲しい。左辺、右辺、返り値の関係は下表のようになって欲しい。また、 `foo :: String +++ bar :: ByteString` のような型注釈は不要なようにしたい

| 左辺 ＼ 右辺 | 文字列リテラル | String | Lazy.Text | Text | Lazy.ByteString | ByteString |
| --- | --- | --- | --- | --- | --- | --- |
| **文字列リテラル** | String | String | Lazy.Text | Text | Lazy.ByteString | ByteString |
| **String** | | String | Lazy.Text | Text | Lazy.ByteString | ByteString |
| **Lazy.Text** | || Lazy.Text | Text | Lazy.ByteString | ByteString |
| **Text** |||| Text | Lazy.ByteString | ByteString |
| **Lazy.ByteString** ||||| Lazy.ByteString | ByteString |
| **ByteString** |||||| ByteString |

そういう型クラス`FlexibleAppendable`を作ってみるが、Haskell力が足らずにコンパイルが通るものが作れなかった。

# コンパイルが通って動作するところまで到達したバージョン

- コメント欄で @hiratara さんという方に　`{-# OVERRAPPABLE #-}` プラグマをおしえてもらったので使ってみた
- `{-# OverloadedStrings #-}` な文字列リテラルから中身の文字列を取り出すのに、`unsafeCoerce` を使ってみた
 
```hs
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE UndecidableInstances  #-}

import qualified Data.ByteString.Char8 as CB
import           Data.Monoid
import           Data.String
import           Unsafe.Coerce

class FlexibleAppendable l r a where
  (+++) :: l -> r -> a

instance {-# OVERLAPPABLE #-} (IsString l) => FlexibleAppendable l CB.ByteString CB.ByteString where
  (+++) l r = fromString (unsafeCoerce l :: String) <> r

instance {-# OVERLAPPABLE #-} (IsString l, IsString r) => FlexibleAppendable l r String where
  (+++) l r = fromString $ (unsafeCoerce l :: String) <> (unsafeCoerce r :: String)

-- 以下似たようなものがえんえん続く
```

動かしてみる

```hs
main :: IO ()
main = do
  putStrLn $ "Hello, " +++ "World"
  CB.putStrLn $ "Hello, " +++ CB.pack "World"
```

実行結果

```shell-session
Hello, World
Hello, World
```

動いた。すごい！

ただ、この実装の場合こちらが想定している型以外の独自のIsStringインスタンスが渡された際にruntime corruptionが発生することがあります。こちらが把握していないデータ構造に対して強制キャストをするためです。Unsafe.Coerceの解説に書いてありました。やばそうなので改善したい機運が凄いです。

進展があったら「その3」を投稿します。進展ありました→  http://qiita.com/saturday06/items/72c98df4e3d1481962b1
【スパースコーディング】スパースなデータ表現の利点

<!--
# はじめに
今回はスパースなデータ表現について解説します。
しくみはそれほど難しいものではありませんが、最近流行っているDeepLearningと関連があったり、あなたの脳の中でも使われている、利点の多いデータ表現技術です。
-->

スパースなデータ表現とは、データを表現するための辞書を用意し、その要素のできるだけ少ない組み合わせでデータを表現することをいいます。
文章で説明されてもいまいちピンとこないと思うので図で表すとこんな感じです。

![visionaudio-20.png](https://qiita-image-store.s3.amazonaws.com/0/46932/b8b2a2a2-492b-e7e4-037e-518545f34f6d.png)
引用元: [Andrew Ng, Unsupervised Feature Learning and Deep Learning, 2015](http://www.csee.umbc.edu/courses/graduate/678/spring15/visionaudio.pdf)

右側のLearned basesと書いてある部分が辞書を表しています。
スパースコーディングは入力画像の一部または全体を、辞書に含まれる要素の組み合わせで表現しようというものです。
例えば下の例では表現したい画像$x$を$\phi_{36}$、$\phi_{42}$、$\phi_{63}$という3つの要素を

```math
0.8\phi_{36} + 0.3\phi_{42} + 0.5\phi_{63}
```

というふうに組み合わせて$x$を近似しています。  
もっとたくさんの要素を使って

```math
0.8\phi_{36} + 0.002\phi_{40} + 0.3\phi_{42} + 0.02\phi_{58} + 0.5\phi_{63}
```

などとすれば近似精度は上がるかもしれませんが、スパースコーディングにおいてはあえてこれを行いません。
少数の要素を用いることで、__意味のある表現を取り出すことができる__からです。
スパースな表現を用いると、データを表現するにはどの要素がどの程度有用なのかをはっきりさせることができます。
例えば上の例では、$x$を表現するには$\phi_{36}$が最も有用で、次に$\phi_{63}$、$\phi_{42}$と並ぶ、といった具合です。
Git でグローバルな .gitignore を作成する

OS X で環境構築するときに忘れないように Git のグローバルな .gitignore の作成についてメモっとく。[Git で Email と Username をグローバル設定する](http://qiita.com/takuya0301/items/894d16f05c8b8475365b)の続き。

.DS_Store はグローバルな .gitignore に追加するといいかと。

# ~/.config/git/ignore に設定する #

```shell-session
$ mkdir -p ~/.config/git
$ cat <<EOF > ~/.config/git/ignore
> .DS_Store
> EOF
```

# 指定ファイル (~/.gitignore_global) に設定する #

```shell-session
$ cat <<EOF > ~/.gitignore_global
> .DS_Store
> EOF
$ git config --global core.excludesFile ~/.gitignore_global
```

# 参考文献 #

https://help.github.com/articles/ignoring-files/
Git で Email と Username をグローバル設定する

OS X で環境構築するときに忘れないように Git のグローバル設定についてメモっとく。

# Email と Username をグローバル設定に追加する #

```shell-session
$ git config --global user.email "takuya0301+git@example.com"
$ git config --global user.name "Takuya Tsuchida"
```

# Email と Username のグローバル設定を確認する #

```shell-session
$ git config --global user.email
takuya0301+git@example.com
$ git config --global user.name
Takuya Tsuchida
$ git config --global --list
user.email=takuya0301+git@example.com
user.name=Takuya Tsuchida
$ cat ~/.gitconfig
[user]
  email = takuya0301+git@example.com
  name = Takuya Tsuchida
```

# 参考文献 #

https://help.github.com/articles/setting-your-email-in-git/
https://help.github.com/articles/setting-your-username-in-git/
Swift1系脳で出来ないと思い込んでいたことができるようになっていた件

もう Xcode 8 がリリースされ Swift 3 の時代ですが、Swift1, Swift2 のおはなしです。

# 再帰的構造を持つ enum

Swift 1 系では、再帰的構造を持つ enum を定義することはできませんでした。たとえば、

```swift
// swift 1, 2 ともに動かないコード
enum List<T> {
    case Nil
    case Cons(x: T, xs: List<T>)
}
```

というコードを書くと、Swiftの処理系は受け付けてくれません。しかしながら、Swift2はとても素晴らしい `indirect` という修飾子を導入することにより、再帰的構造を持つ enum を定義できるようになりました。

```swift 
// swift 2 系では動く
indirect enum List<T> {
    case Nil
    case Cons(x: T, xs: List<T>)
}
```

また、挙動的に面白いのが、再帰的構造を持つが即座に評価されないようになっている場合、たとえば以下のような遅延ストリームについては、`indirect` 修飾子がなくても動くのです。これは Swift 1 系のときに挙動を試してないので、どうだったかわかりませんが、Xcode ダウンロードするのめちゃめちゃ時間掛かるし重いのでだれか試して欲しい。

```swift
// indirect 修飾子はいらない
enum Stream<T> {
    case Nil
    case Cons(x: T, xs: () -> Stream<T>)
}
```

List/Stream ともに Swift3 でも動作します。

# 関数内に定義した関数の再帰呼び出し

まあコードみればわかると思うけど、以下のようなコードが Swift 1 系では動かなかった（記憶がある...）。間違っていたらごめんなさい。でも関数内に定義した関数なんて、再帰呼び出しにくらいしか使わなくないですか？と半ギレした記憶があるので多分ほんとに動かなかったと思う。Swift2でやっと動くようになりました。

```swift
func fact(n: Int) -> Int {
    func loop(i: Int, acc: Int) -> Int {
        return i < 1 ? acc : loop(i - 1, acc: i * acc)
    }
    return loop(n, acc: 1)
}
```

ちなみに Swift 3 では以下のように書かないとダメです

```swift
func fact(n: Int) -> Int {
    func loop(i: Int, acc: Int) -> Int {
        return i < 1 ? acc : loop(i: i - 1, acc: i * acc)
    }
    return loop(i: n, acc: 1)
}
```

Swift 最高！！！！！！（大嘘）
戻り値のあるブループリント関数を CreateEvent ノードで指定できるようにする際の注意点

[この記事](http://qiita.com/go_astrayer/items/28f3726e03d2d22087e2)の補足記事です。

**「戻り値のあるブループリント関数が Create Event ノードで列挙されなかった」**

と言った現象が発生したので、調べてみました。

# 現象について
例えば、C++ で**「戻り値のある動的デリゲータを引数として受け取る関数」**を以下のように定義します。
（ここでは**「MyFunc」**という名前にします。）

```cpp
// bool を返すデリゲータ
DECLARE_DYNAMIC_DELEGATE_RetVal(bool, FExecuteDelegate);

/**
 * 
 */
UCLASS()
class MYPROJECT_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()
 
    // bool を返すデリゲータを引数として受け取る
    UFUNCTION(BlueprintCallable, Category = "MyProject")
    static void MyFunc(FExecuteDelegate Event) {}
 	
};

```

そして、定義した**「MyFunc」**を使って、ブループリントで以下のようなノードを組みます。
![DelegateFunc2.png](https://qiita-image-store.s3.amazonaws.com/0/43814/cf393ae1-5487-9e6a-b8be-cf485bfc3ef0.png)

次に、**「Create Event ノード」**で指定するための**「bool を返す関数」**をブループリントで定義します。
（ここでは、**「DelegateFunc」**という名前にします。）
![DelegateFunc.png](https://qiita-image-store.s3.amazonaws.com/0/43814/8852e051-52ec-2c5b-3f0d-02857b3450bc.png)

これで**「Create Event ノード」**で**「DelegateFunc」**を指定することが出来ると思ったのですが……。
![DelegateFunc3.png](https://qiita-image-store.s3.amazonaws.com/0/43814/22d18459-8c0c-1d5f-073a-513b5cc364a6.png)

見ての通り、**「DelegateFunc」**が列挙されませんした。

# 対処法について
そこで調べてみたところ、デリゲータの定義を以下の様に変更すれば出来ると書かれていたので、試してみました。

```cpp
// bool を返すデリゲータ
//DECLARE_DYNAMIC_DELEGATE_RetVal(bool, FExecuteDelegate);
DECLARE_DYNAMIC_DELEGATE_OneParam(FExecuteDelegate, bool&, Output); //<-- これ

/**
 * 
 */
UCLASS()
class MYPROJECT_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
    GENERATED_BODY()
 
    // bool を返すデリゲータを引数として受け取る
    UFUNCTION(BlueprintCallable, Category = "MyProject")
    static void MyFunc(FExecuteDelegate Event) {}

};
```

結果はどうなったかというと……
![DelegateFunc4.png](https://qiita-image-store.s3.amazonaws.com/0/43814/54a1f3fe-1413-5bbc-d994-84ee6a807609.png)

無事に**「DelegateFunc」**を指定できるようになりました。

# 参考サイト
* [Blueprintable delegates with return values](https://answers.unrealengine.com/questions/201763/blueprintable-delegates-with-return-values.html)
staging環境、production環境へのデプロイの際にローカル上でasset_syncを事項する際の注意点

## 実行環境
* capistranoを使用してawsなどのサーバーにrailsアプリをデプロイ

* デプロイする際にassets:precompileはローカル上で行う
> サーバーが複数ある時などを考慮してローカルで行う

* asset_syncを使用して、precompileで出力されるファイルを Amazon S3 などでホスティング

* production環境はデプロイサーバーからデプロイ
> デプロイサーバーからのデプロイはIAMロールからの認証

* staging環境では、ローカル上からcapコマンドを叩いてデプロイ

* EC2からS3へのアクセスはIAMロールでの認証


## ローカル環境でassets:precompile
どのように設定をするかなどはもともと素晴らしい資料があったのでそちらを参照していただい方がいいだろう

* [参考資料1](http://qiita.com/dentyu/items/011af7f7ce62aa88f95c)
* [参考資料2](http://qiita.com/rmacchoj7/items/f92568fd8970860f189e)
* [参考資料3](http://cluex-developers.hateblo.jp/entry/2016/08/10/183055)

以上を参考に設定を行った。


実行環境のような環境ではおそらくうまくいかないことがある。

## 失敗例
### 1.ローカル以外でもassets:precomile?
capfileに

```
require 'capistrano/rails/assets'
```

を設定している場合。。。

おそらく、初歩的なミスをする人は少ないと思うが、少なからず自分はこれで結構な時間を消費した。

そもそも、一度ローカルでassets:precompileするのだから、この設定はいらない。
そこに気づけず、ずっとdeployを失敗していた。

staging環境へのdeployの際にまず、最初にローカル上でassets:precompileが実行され、
asset_syncは

```
 config.fog_provider = 'AWS'
 config.fog_directory = ENV['FOG_DIRECTORY']
 config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
 config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
```
以上の設定をすることで、s3にファイルをアップしてくれる

ここまではいいのだが、staging環境（awsのEC2）でもassets:precompileが実行されてしまう。

そうすると、IAMロールユーザーからの認証になるので、

```
 config.fog_provider = 'AWS'
 config.fog_directory = ENV['FOG_DIRECTORY']
 config.aws_iam_roles = true
```
以上の設定が必要になる。

これが原因でエラーが起きていた。

対処方法としては、
capfileの

```
require 'capistrano/rails/assets'
```
をコメントにすればいいだけである。
すでにローカル上でassets:precompileするのだから、これは必要なくなる


### 2.stagingとproductionとでデプロイ方法が違う
上記の実行環境を見ていただくとわかるが、production環境の方はデプロイサーバーを介してデプロイをするが、staging環境ではローカル上から直接コマンドを叩いてデプロイする場合

何が問題かというと、asset_syncの設定が異なること！！

一般的には、config/initializers/asset_sync.rbに設定を記述する。
これが問題となる！！

production環境はデプロイサーバーからのデプロイであるからIAMロールが認証する

だから

```
 config.fog_provider = 'AWS'
 config.fog_directory = ENV['FOG_DIRECTORY']
 config.aws_iam_roles = true
```
以上の設定が必要になる。

しかし、

stagingはローカル上からなので、

```
 config.fog_provider = 'AWS'
 config.fog_directory = ENV['FOG_DIRECTORY']
 config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
 config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
```
以上の設定が必要になる。

stagingとproductionで設定が異なるという問題起きる。。。

対処方法は
config/environmets/rails_env.rb（rails_env=各環境） に設定を記述すればいい。

注意点としてstagingでのデプロイで必要となるasset_syncの設定はdevelopment.rbに記述する必要がある。理由はローカル上でassets:precompileをしているから！！！


## 最後に
以上のようにローカル上でのassets:precompileをする際の注意点を挙げたが、実際にこのようなことを防ぐために、複数台あるwebサーバーのうち一台のwebサーバー上でassets:precompileする方法もある。

これは実際の自分の環境などと比べてどうするかを決めればいいと思う。

最後まで読んでいただきありがとうございます。

何かありましたら、指摘お願いいたします。
cocos2d-x-3.13.1 で cpp プロジェクトを作成

# 環境

1. Mac OS X 10.11.6 (英語)
2. Xcode 7.3.1
3. Android Studio 2.1.3
4. Cocos2d-x 3.13.1

# 方針

1. Android の API Level は ```android-17```

# 環境変数を設定

cocos2d-x の `README.md` に従って `setup.py` を実行すると `~/.profile` が修正されてしまうのが嫌なので `~/.profile` に追加される内容を手動で設定。

1. cocos2d-x の親ディレクトリから

		export COCOS_CONSOLE_ROOT=`pwd`/cocos2d-x/tools/cocos2d-console/bin
		export PATH=$COCOS_CONSOLE_ROOT:$PATH

		export COCOS_TEMPLATES_ROOT=`pwd`/cocos2d-x/templates
		export PATH=$COCOS_TEMPLATES_ROOT:$PATH

		export NDK_ROOT=~/Library/Android/sdk/ndk-bundle
		export PATH=$NDK_ROOT:$PATH

		export ANDROID_SDK_ROOT=~/Library/Android/sdk
		export PATH=$ANDROID_SDK_ROOT:$PATH
		export PATH=$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:$PATH

		export ANT_ROOT=/usr/local/Cellar/ant/1.9.7/bin
		export PATH=$ANT_ROOT:$PATH

  1. `~/.profile` には以下に相当する内容も追加されるが、使われているところが不明なので省略

			export COCOS_X_ROOT=`pwd`
			export PATH=$COCOS_X_ROOT:$PATH

  2. ant は brew でインストールした
      1. Android ビルドで使われる

# プロジェクトを作成

		$ cocos new HelloCpp -p org.cocos2dx.hellocpp -l cpp
		> Copy template into .../HelloCpp
		> Copying Cocos2d-x files...
		$ cd HelloCpp

1. 上の例では cocos2d-x のテンプレートと同じ名前を使ってる

# iPhone で実行

		$ cocos run -p ios

 1. `cocos run` だと実機が繋がっていてもシミュレーターで動く

# Xcode で実行

1. proj.ios_mac ディレクトリ内の xcodeproj を Xcode で開けば 実機でも Run できた
  1. コンパイル警告が大量に出る

# Android で実行

		$ cocos run -p android --ap android-17 -j 4

1. 実機を外して `cocos run -p android --ap android-17 --app-abi x86 -j 4` とすると、シミュレーターでも動いた

# Android Studio で実行

1. proj.android-studio ディレクトリをプロジェクトとして開ける
  1. 以下の警告が出るので ```Update```

			It is strongly recommended that you update Gradle to version 2.14.1 or later
			As part of the update, the Android plugin will be updated to version 2.1.3

2. 以下を実行してからでないと実機の Run で ```java.lang.UnsatisfiedLinkError ... couldn't find "libMyGame.so"``` エラー

		$ cocos compile -p android --ap android-17 --android-studio -j 4

3. そのままエミューレーターで Run すると ```INSTALL_FAILED_NO_MATCHING_ABIS``` エラー。以下のコマンドを実行して Android Studio を再起動したらエミューレーターで動いた。

		$ cocos compile -p android --ap android-17 --app-abi x86 --android-studio -j 4

4. ただし、実機で Run しようとすると ```INSTALL_FAILED_NO_MATCHING_ABIS``` エラーが出るようになった。以下のコマンドを実行すると再度実機で動くようになるが、エミュレーターではまた動かなくなる。

		$ cocos compile -p android --ap android-17 --app-abi armeabi --android-studio -j 4
[macOS]AU Lab

<p>テキスト文書を読み上げ機能で再生した音声に、CoreAudioのAudio Unitを使ってエフェクトをかける方法を探っていきたいと思う。</p>

<p>まずは、Audio Unitについて調べてみる。</p>

<p>CoreAudioのAudio Unitで出来る事を調べるには、AU Labを使ってみるのが一番だ。</p>

<p>AU Labは、以下から入手できる。</p>

<a href="http://www.apple.com/jp/itunes/mastered-for-itunes/">Mastered for iTunes</a><br />

<p>読み上げるテキストを用意する。</p>

<p>自由に利用出来るテキストとして、小説『白鯨』がよく使われているが、日本語のテキストだと、青空文庫から入手するのがよいと思う。ただし、文字コードはUTF-8に、開業文字はLFにすること。</p>

<p>入手してテキストをsayコマンドで読み上げる。</p>

<pre><code>$ say -n : -f ./風琴と魚の町.txt
</code></pre>

<p>AU Labを起動する。</p>

<img width="336" alt="起動画面.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/12540/5be34e49-b95c-db69-cce0-ca331d728690.jpeg">


<p>"Create Document"を押下し、Editメニューで"Add Audio Unit Generator..."を選択し、AUNetReceiveを追加する。</p>

<img width="123" alt="AUNetReceive.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/12540/ac5b0564-a660-a558-92d0-b8365778ccff.jpeg">


<p>AUNetReceiveの接続を押下する。</p>

<img width="85" alt="接続.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/12540/534776a2-812a-f486-fd50-65366ab80e1c.jpeg">


<p>追加したGeneratorのEffectsを押下し、メニューでAUDistortionを選択する。</p>

![AUDistortion.jpg](https://qiita-image-store.s3.amazonaws.com/0/12540/5e2b0717-8e64-2886-68e4-364b6c187506.jpeg)


<p>すると、ディストーションのパラメータが変更できるようになる。</p>

![変更.jpg](https://qiita-image-store.s3.amazonaws.com/0/12540/a3796718-334e-8496-f0f5-b59bd86b5273.jpeg)


<p>次は、これをプログラムで行えるようにしてみる。</p>

関連情報
<a href="http://www.apple.com/jp/itunes/mastered-for-itunes/">Mastered for iTunes</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />
<a href="https://t.co/6P3h2jtbRk</a>note<br />
[Java]GoogleAPIをバッチ処理で使う

Linuxサーバ上のファイルをGoogleDriveにバックアップしたく、以下のサンプルコードを元に実装してみた。
https://github.com/google/google-api-java-client-samples/tree/master/drive-cmdline-sample

しかし、GoogleAPIの認証時にブラウザが必要になるため、サーバ上では実行できない。
色々調べてみると、一度リフレッシュトークンを取得すればそれを使ってアクセストークンを生成できる、とのことだが、サンプルコードで使われているクラスにリフレッシュトークンをセットするようなメソッドが見つからなかった。

代わりに、一度GUI環境で認証情報を作成し、それをサーバに転送して使われるようにすれば問題なく動作することがわかった。
上記のサンプルコードだと、認証情報を保存するパスは以下のフィールドで定義されている。
````
  /** Directory to store user credentials. */
  private static final java.io.File DATA_STORE_DIR =
      new java.io.File(System.getProperty("user.home"), ".store/drive_sample");
````
一度認証すると、上記ディレクトリ内にStoredCredentialというファイルが生成される。
これをGoogleDriveAPIを実行したいマシンに持って行き、`/home/hoge/.store/drive_sample/StoredCredential` においてやればGoogleAPIを実行できる。
Python globで得るファイル名を数字順にする

環境によっては何もしなくても`glob.glob`で得られるファイルは数字順であったが、他の環境ではそうでもなくarbitraryであった。

出典：http://stackoverflow.com/questions/12093940/reading-files-in-a-particular-order-in-python
を参考にsortすることで解決する。

```
import glob 
import re
def numericalSort(value):
    numbers = re.compile(r'(\d+)')
    parts = numbers.split(value)
    parts[1::2] = map(int, parts[1::2])
    return parts
fitsf=sorted(glob.glob('*.fits'), key=numericalSort)
```
9/14　今日の学習内容〜画像にリンクを貼り付ける〜

###今日の学習内容
***
昨日はテキストをクリックするとリンク先に移動するリンクを作りましたが、今日は画像をクリックしてリンク先に移動できるようにしたいと思います( ´ ▽ ` )ﾉ

下準備として、画像ファイルを``app/asset/images``フォルダに保存しておきます。↓
お好きな画像でOKです。
画像ファイルをドラッグすることで、アップロードできます。

![スクリーンショット 2016-09-14 22.02.14.png](https://qiita-image-store.s3.amazonaws.com/0/137880/b36cafbc-e048-bd2d-749a-153dfb3ee923.png)



では、実際に画像をクリックしてリンク先に移動できるようにする練習をしていきましょう(・ω・)ノ

``lesson_controller``にからのアクションを作成します。
今回は``practice10``を作成しました。↓

![スクリーンショット 2016-09-14 21.11.28.png](https://qiita-image-store.s3.amazonaws.com/0/137880/1f5faded-8a2b-a224-4946-6d1ba62e683c.png)


次に、作成したアクションに対応するテンプレートファイル(.erbで終わるファイル)を``app/view/lesson``の中に作成してください。

昨日と同じように、リンクを作成するために、``link_to``メソッドを使用していきます。
今日は、画像を扱うので、``image_tag``メソッドを使用します。
内容は以下の画像を参考にしてください(￣▽￣)↓

![スクリーンショット 2016-09-14 22.21.35.png](https://qiita-image-store.s3.amazonaws.com/0/137880/6abb3082-7d8e-240b-7450-b0d0867c8f01.png)

``rails s -b $IP -p $PORT``コマンドをターミナルに打ち込み、実行してください。
出てきたリンクをクリックして開くと、トップページが表示されるので、URL欄に``/lesson/practice10``と入力し、リロードします。
``practice10``アクションがルーティングに従って選択され、内容が実行されます。
レンダリングに使用されるのは、同じ名前をつけた``practice10.html.erb``が自動的に選択されるわけですね。

以下、実行画面です。↓

![スクリーンショット 2016-09-14 22.25.50.png](https://qiita-image-store.s3.amazonaws.com/0/137880/4d48e662-33d3-4eeb-8c48-e70918d347c2.png)

画像をクリックすると、設定していたリンク先に移動します↓

![スクリーンショット 2016-09-14 22.31.50.png](https://qiita-image-store.s3.amazonaws.com/0/137880/61ed1df4-a8d4-3827-ea68-45eb11dec627.png)

今回は、グーグル検索のページをリンク先に設定しておきました( ´ ▽ ` )ﾉ

``practice10.html.erb``に書いてあった``align``属性は、画像の位置を指定するものです。
上の画像では、``left``にしていましたが、こちらを``top``に変えてみましょう！↓

![スクリーンショット 2016-09-14 22.27.30.png](https://qiita-image-store.s3.amazonaws.com/0/137880/7a004da3-53c3-0bd0-bf85-e38df334e2f5.png)

画像が表示される位置が変更されたことが確認できるかと思います(￣▽￣)

また、HTMLの基本として、画像の表示をオフにしている方やテキストブラウザを利用されている方のために**画像の代わりになるテキスト**を用意しておく必要があります。

それに使うものが``alt``属性です。

上記の画像では、``search``と表示されるように設定してあります(・ω・)ノ
省略した場合はファイル名から自動的にセットされるようです。

実際に、画像を読み込まないように設定してリロードしてみました。↓

![スクリーンショット 2016-09-14 22.44.48.png](https://qiita-image-store.s3.amazonaws.com/0/137880/9d808cec-19ae-0854-85e8-7dfbb4eab7d8.png)

Chromeを使われている方は、Chromeの詳細設定のプライバシー→コンテンツ設定より、画像を表示しないように設定できるので、実際に試してみてはいかがでしょうか(￣▽￣)








###あとがき
***
今日は、昨日に引き続き、リンクの作成について学習を進めていきました。
Webページを見ていると、よく画像をクリックしてリンク先に移動しますが、こんなに簡単に作れるものだったのですね( ´ ▽ ` )ﾉ

ここまで読み進めていただき、ありがとうございましたm(__)m
　
###参考にさせていただいたサイト・文献
***
- [改定3版基礎RubyOnRails](https://www.amazon.co.jp/dp/4844338153)
- [cloud9](https://ide.c9.io/)
- [Railsドキュメント image_tag](http://railsdoc.com/references/image_tag)
[Rails][Routing] Rails4.x で 少数点（. ドット）を含めたURLを使いたい場合

# やりたいこと
```rb
GET http://domain.jp/api/2.1.1/users
```

とか

```rb
GET http://domain.jp/meats/score/21293.02
```

とか、少数点、というかドットが入った形のURLを使う方法についてです。

（そもそもドットの入った値はURLに入れないほうが良いのかもしれませんが...）

# 失敗例
```rb:config/routes.rb
get 'meats/score/:score' => 'meats#score'
```

```rb:spec/routing/meats_routing_spec.rb
it "routes to #score" do
  expect(:get => "/meats/score/5.4").to route_to("meats#score", score: "5.4", format: "json")
end
```

```rb:Result
No route matches "/meats/score/5.4"
```

この様に No route matches 扱いになります。

# # Railsはデフォルトではparameterにdotを受け付けない

[こちら](http://guides.rubyonrails.org/routing.html#specifying-constraints)に記載されている通り、ドットをparameterに含めることは許容されていないようです。

> By default the :id parameter doesn't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within an :id add a constraint which overrides this - for example id: /[^\/]+/ allows anything except a slash.

# 対応 - Constraintsで、paremeterを正規表現で指定する

## Constraintsの意味（抜粋）

> something that limits your freedom to do what you want [= restriction]

日本語にすると制約とか制限とか

なので、この場合には、 **Parameterに対する制約** ということになります。

## constraintsの使用例

```rb:例
resources :photos, constraints: { id: /[A-Z][A-Z][0-9]+/ }
```

↑だと ```/photos/AB1``` とかになります

## 手っ取り早くパラメータにドット（小数点）を許容する方法

```rb
get 'meats/score/:score' => 'meats#score', score: /[^\/]
```

スラッシュ ```/``` 以外を許容します

## 形式を限定して小数点（ドット）許容する
### `数字+ドット+数字` の場合

```rb
get 'meats/score/5.1' => 'meats#score', constraints: { score: /\d+\.\d+/ }
```

### `2.2.2.2.2.2.2.2` の様な感じの場合

```rb
get 'meats/score/5.1' => 'meats#score', constraints: { score: /\d+(\.\d+)*/ }
```

### `api/v2.1.1/foo` とかの場合
（そもそもURLを使ったapiのバージョニングがいいかどうかは置いておいて...）

↓の様なconstrainsを使うといいかと思います。

```rb
, constraints: { api_version:  /v\d+(\.\d+)*/ }
```


# References
- http://guides.rubyonrails.org/routing.html#specifying-constraints
- https://blog.hello-world.jp.net/ruby/754/
良いプログラマーになるための備忘録

## 備忘録

<a href="http://qiita.com/zaru/items/3da2b90b066ec69ab9e9" target="_blank">良いプログラマとは、僕が今思っていることをまとめてみた - Qiita</a>

<a href="http://qiita.com/jabba/items/efcc1d7a15075e631b36" target="_blank">世界の凄腕エンジニア達からのプログラミングに関するお言葉集は不思議にココロを打つのでした - Qiita</a>

<a href="http://qiita.com/jacksuzuki/items/b2fa6b44962e73a53d08" target="_blank">ロシアの天才ハッカーによる【新人エンジニアサバイバルガイド】 - Qiita</a>

<a href="http://qiita.com/kenichi_cc/items/c3ecca7b7d5fc5c6bf2e" target="_blank">コードを書く際の指針として見返すサイトまとめ - Qiita</a>

<a href="http://www.acroquest.co.jp/webworkshop/programing_course/note.html" target="_blank">目から鱗が落ちるように分かるプログラミング講座 詳細解説 Acroquest Technology 株式会社</a>

### Guidelines

<a href="http://postd.cc/7-strategies-to-quickly-become-productive-in-an-unfamiliar-codebase/" target="_blank">不慣れなコードベースで短期間に生産性を高めるための7つの方法 | プログラミング | POSTD</a>

<a href="http://qiita.com/sh-ogawa/items/efb4907f6b5fd6a6ae03" target="_blank">保守開発に開発者として入って困ることのまとめ（実体験） - Qiita</a>

<a href="http://qiita.com/kkyouhei/items/38ba41fb6b877f160e99" target="_blank">技術系の名言まとめ++ - Qiita</a>

<a href="http://qiita.com/n_slender/items/3be36b3dc7451e230e95" target="_blank">真似をする前にバッドプラクティスかどうかを調べてみよう - Qiita</a>


### Coding Style

<a href="http://cortyuming.hateblo.jp/entry/20131208/p1" target="_blank">関数名や変数名に使えそうな動詞・名詞・形容詞のメモ - 牌語備忘録 -pygo</a>

<a href="http://qiita.com/Koki_jp/items/d5f1b5f277b581888a1f" target="_blank">DRY原則をもう一度 -コンカレント・エンジニアリング- - Qiita</a>

<a href="http://www.songmu.jp/riji/entry/2014-08-20-code-review.html" target="_blank">クソコードに対する怒りとコードレビューにおける人格攻撃について | おそらくはそれさえも平凡な日々</a>

### ビジネスをする上で気をつけること

<a href="http://qiita.com/kazukichi/items/aeba286c2a750081e5c0?utm_content=buffer9cb02&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer" target="_blank">WEBサービスで起業したい人に読んで欲しい１９のコト - Qiita</a>

<a href="http://qiita.com/kazukichi/items/7379b75fba2f90d3cf45" target="_blank">エンジニアで稼ぐために大切な１３のコト - Qiita</a>
Google検索でかゆいところに手が届く設定・ショートカット


## Google検索結果時のショートカット

Googleの検索結果→歯車アイコン→検索設定→「インスタンスの結果を常に表示」後に以下が使用可能。

| j |Googleの検索結果の次に移動 |
|:------------:|:------------:|
| k |Googleの検索結果の前に移動 |
|/ |検索ボックスに移動 |
SQLServerのSELECT結果をファイルに出力する

SQLCMDを使用することでコマンドプロンプトからSQL文を発行できます。
今回はスクリプトファイルに記述したSQL文をバッチファイルから実行し
その結果をテキストファイルに出力します。

##インストール
SQLCMDはSQLServerをインストールすれば使用できます。
単体で使用する場合はMicrosoftのサイトからFeature Packをダウンロードします。 
この場合、環境変数にPATHが通っていないので設定します。

##スクリプトファイル
Query.sql

```sql
SELECT * FROM TestTable
```
※SELECT文の前に 

```sql
SET NOCOUNT ON 
```
と書くと件数が出力されません。

##バッチファイル
テキストファイルに

```bat
@ECHO OFF 
CD %~dp0
SQLCMD -S localhost -U sa -P pass -d TestDb -i Query.sql -s, -W -h -1 -o Qutput.csv
```
と記述してTest.batとして保存します。
バッチを実行するとスクリプトファイルに記述したSELECT文の結果がQutput.csvに
カンマ区切りで出力されます。

##コマンドラインオプション
| オプション | 説明 |
|:-:|:-:|
| -S | サーバ名 |
| -U | ログイン |
| -P | パスワード |
| -d | データベース |
| -i  | スクリプトファイル |
| -s  | 区切り文字 |
| -W  | 余計な空白を省く |
| -h  | -1でヘッダ非表示 |
| -o  | 出力ファイル |

SQLCMDユーティリティ
https://msdn.microsoft.com/ja-jp/library/ms162773.aspx
Rails + Unicorn + Nginx + EC2 +ELBの構成でWebサイトにアクセスできないときの原因

よくあるアプリの構成でサービスがダウンしているとき（Webブラウザを介してサービスを利用できないこと）、の原因をまとめてみました。


今回は特にWebアプリのインフラで遭遇しがちなものを想定しています。
自分が遭遇してきたケースです

# Webアプリ構成

||使用するもの|
|:---:|:---:|
|フレームワーク|Rails|
|Webサーバー|Nginx|
|その他サーバー|Unicorn|
|ロードバランサー|ELB|
|インフラ|EC2|


という構成でサービス運営しているとします。

この構成はRails + クラウドの構成でサービス作るときにありがちな構成かと思います。


# 原因その1: Unicornの停止

## この状況かどうかの確認方法

web
sshログインしてunicornが動いているか確かめてみよう

EC2にログイン後

```
$ ps aux | grep unicorn
```

で確認してみましょう。

## 解決方法

unicornを起動しなおす。

参考)http://qiita.com/moonsubaru/items/09df180736f09c995954


# 原因その2: Nginxの停止

## この状況かどうかの確認方法

また、sshログインしてnginxが動いているか確かめてみましょう。

EC2にsshログイン後

```
$ ps aux | grep nginx
```

を打ってみましょう。

## 解決方法

Nginxを再起動する

EC2にsshログイン後

```
$ nginx
```

としましょう。場合によっては sudo をつける必要があります。。


# 原因その3: EC2がELBから切り離されている

## 状況

WebサーバーがELBのヘルスチェックに応答できておらず、OutOfServiceになってしまった可能性が高いです。

## この状況かどうかの確認方法

IPアドレスにWebブラウザからアクセスしてみて、画面が正常に表示される場合はこの状況です。

## 解決方法

ELBの応答に対して正しく応答するようにしましょう。

今回は応答できないということなので、

「サーバ側で重い処理が走っててレスポンスが遅い」

という場合なので2通りの対応をします。

### 重いプロセスをkillする

その処理が大事な場合どうするんだ、というのは置いておいて

```
$ kill <プロセスid>
```

で処理を停止できます。


### ヘルスチェックの設定を変更する

AWSのマネジメントコンソールでEC2を選択した後、
サイドバーからロードバランサーを選びます。

![sidebar.png](https://qiita-image-store.s3.amazonaws.com/0/88357/5381e1b9-d707-9ce0-ce5e-ae8c0f9d31ac.png)


その後、「ヘルスチェック」のタブを選択し、「ヘルスチェックの編集」を押しましょう。
高度な詳細という項目を変更します。

「応答タイムアウト」を長くすれば、レスポンスの遅さに寛容になります。
「非正常のしきい値」、「正常のしきい値」も変えて調整するのもいいでしょう。

この編集はELBに紐付いたサーバーをInServiceにするための緊急対応なので、
正常稼働できる状態にサービスを戻したら、数値も元に戻しましょう。

# 最後に

Webブラウザでアクセスするとなんとなくわかったりします。
今更だけどiOSのウィジェットを実装してバッテリー残量を表示してみた


## はじめに

書くネタがちょっと尽きた感でてきたので前々からやろうかな？って思っていたウィジェットについて触ってみました。

## 実装

1. まずは適当にプロジェクトを作成
2. __File > New > Target...__ を選択
3. __Application Extension__ から __Today Extention__を選択

![スクリーンショット 2016-09-14 午後10.12.00.png](https://qiita-image-store.s3.amazonaws.com/0/97280/4e19f426-802c-2b62-c385-f00cdf8ea1fc.png "スクリーンショット 2016-09-14 午後10.12.00.png")
4. 大体的適当にターゲットの名前をつける
5. とりあえず実行してみる（今回はBatteryStatusとしてターゲットを追加した。このスキーマで実行する。なお、バッテリーは実機でないと確認できない！）

![スクリーンショット 2016-09-14 午後10.13.33.png](https://qiita-image-store.s3.amazonaws.com/0/97280/a7e025df-0c50-45c1-721a-76c152f1f3c5.png "スクリーンショット 2016-09-14 午後10.13.33.png")
![スクリーンショット 2016-09-14 午後10.13.15.png](https://qiita-image-store.s3.amazonaws.com/0/97280/56ffacff-a4c5-e737-d223-d900d6128b5e.png "スクリーンショット 2016-09-14 午後10.13.15.png")
シミュレータではあるがこんな感じに例のアレが追加された。
6. ちょっと実装


## ちょっと実装

![スクリーンショット 2016-09-14 午後10.15.07.png](https://qiita-image-store.s3.amazonaws.com/0/97280/824e974f-6c2f-be80-eeca-0ce6b2b9e02c.png "スクリーンショット 2016-09-14 午後10.15.07.png")

とりあえずこんな感じの構成になっているので、作ったターゲット名の中にあるstoryboardを編集した。

続いて、 __TodayViewController.swift__ を弄る

```swift:TodayViewController.swift
import UIKit
import NotificationCenter

class TodayViewController: UIViewController, NCWidgetProviding {
        
    @IBOutlet weak var batteryLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setBatteryStatus()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
        setBatteryStatus()
        
        completionHandler(NCUpdateResult.NewData)
    }
    
    private func setBatteryStatus() {
        UIDevice.currentDevice().batteryMonitoringEnabled = true
        let floatBatteryLevel = UIDevice.currentDevice().batteryLevel
        batteryLabel.text = NSString(format: "%.1f％", floatBatteryLevel * 100) as String
    }
}
```

![IMG_0133.PNG](https://qiita-image-store.s3.amazonaws.com/0/97280/9a1a20c8-1d50-0a41-f568-883d29b2c44c.png "IMG_0133.PNG")

私の起床時間がバレてしまうが、真ん中に __BatteryStatus__ としてウィジェットが追加されたことが確認できた。
素人の言語処理100本ノック:05


[言語処理100本ノック 2015](http://www.cl.ecei.tohoku.ac.jp/nlp100/)の挑戦記録です。環境はUbuntu 16.04 LTS ＋ Python 3.5.2 \:\: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧は[こちら](http://qiita.com/segavvy/items/fb50ba8097d59475f760)からどうぞ。

## 第1章: 準備運動

###05.n-gram
>与えられたシーケンス（文字列やリストなど）からn-gramを作る関数を作成せよ．この関数を用い，"I am an NLPer"という文から単語bi-gram，文字bi-gramを得よ．

出来上がったコード：

```python:main.py
# coding: utf-8


def n_gram(target, n):
	'''指定されたリストからn-gramを作成

	引数:
	target -- 対象リスト
	n -- n-gramのn値（1ならuni-gram、2ならbi-gram...）
	戻り値:
	gramのリスト
	'''
	result = []
	for i in range(0, len(target) - n + 1):
		result.append(target[i:i + n])

	return result


target = 'I am an NLPer'
words_target = target.split(' ')

# 単語bi-gram
result = n_gram(words_target, 2)
print(result)

# 文字bi-gram
result = n_gram(target, 2)
print(result)
```

実行結果：

```python:端末
[['I', 'am'], ['am', 'an'], ['an', 'NLPer']]
['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']
```

###ついでにuni-gramとtri-gramも
関数のテストを兼ねて、uni-gramとtri-gramも確認しました。

```python:main.pyの続き
# 単語uni-gram
result = n_gram(words_target, 1)
print(result)

# 文字uni-gram
result = n_gram(target, 1)
print(result)

# 単語tri-gram
result = n_gram(words_target, 3)
print(result)

# 文字tri-gram
result = n_gram(target, 3)
print(result)
```

実行結果：

```python:端末
[['I'], ['am'], ['an'], ['NLPer']]
['I', ' ', 'a', 'm', ' ', 'a', 'n', ' ', 'N', 'L', 'P', 'e', 'r']
[['I', 'am', 'an'], ['am', 'an', 'NLPer']]
['I a', ' am', 'am ', 'm a', ' an', 'an ', 'n N', ' NL', 'NLP', 'LPe', 'Per']

```

大丈夫そうですね。

　
6本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。
CentOS7でsudoなしでdockerを利用するちょっとした工夫

# CentOS7でsudoなしでdockerを利用するちょっとした工夫 #

## 概要
トゥ～ン…(プロフェッショナル風)
家のサーバをCentOS6.8からCentOS7にした。
Dockerを入れた。
Rootでは使えた。
CentOS6.8でやったように一般ユーザで使えるように設定した。
一般ユーザでは使えなかった。詰まった。

あと一歩だけ前に進もう…（プロフェッショナル）

そこで、sudoなしで使うためのCentOS7特有の設定について記したい。


## 同じ点
### dockerインストールと起動

CentOS6系ではレポジトリの追加が必要でしたが、CentOS7では標準で対応しています。

```bash:yum
$ sudo yum install docker
```

もともと7系で標準搭載する機能としてfedoraとかで開発が進んでたものなのでね。（たしか）

```bash:systemd
$ sudo systemctl start docker.service
```

dockerサービスを起動させます。ここまではCentOS6.8でも同様でした。

## 異なる点

### その１ dockerのグループが違う
dockerはLinuxのコンテナ技術を使った仮想化の仕組みですので、
考え方はインスタンス（仮想サーバ）というよりも1プロセスとして考える方が自然です。
そのためか、dockerは基本rootでしか動きません。というよりdockerサービスが使用する
ファイルは権限はrootのものがほとんどですので当たり前といえば当たり前なのですが。

ですが、DockerではDocker所属グループにユーザをぶち込むことで
rootでないユーザでもsudoなしで利用できるようになります。

CentOS6系ではDocker(docker-io)の所属グループは「docker」でしたが、
CentOS7ではDockerの所属グループは「Dockerroot」になっております。

groupファイルを確認するとdockerユーザになっております。

```bash:/etc/group
<中略>
pulse-access:x:992:
pulse:x:171:
gdm:x:42:
sssd:x:991:
gnome-initial-setup:x:990:
stapusr:x:156:
stapsys:x:157:
stapdev:x:158:
tcpdump:x:72:
slocate:x:21:
vboxusers:x:989:
clamupdate:x:988:
apache:x:48:
tomcat:x:91:
mysql:x:27:
radiusd:x:95:
dockerroot:x:987:jenkins,tubone
hadoop:x:1001:
input:x:986:
systemd-bus-proxy:x:985:
systemd-network:x:984:
geoclue:x:983:
setroubleshoot:x:982:

```

そのためCentOS6系の手順である、一般ユーザをdockerグループにぶち込む設定はこうなります。

```bash:gpasswd
$ sudo gpasswd -a USER dockerroot
```

### その2 Dockerが使用するsockファイルをきちんとする
上記の手順で普通なら完了するのだが、私の環境ではどうにもうまくいかない。
なぜなんだ…　ということで、sock ファイル を確認してみると

```bash:/var/run/docker.sock
srw-rw---- 1 root root 0  8月 27 19:06 /var/run/docker.sock
```
と、所属グループがrootですね…　たまげたなぁ。

所属グループをdockerrootに直してあげます。

```bash:chown
$ sudo chown root:dockerroot /var/run/docker.sock
```

## 確認

```bash:確認
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

エラーが表示されず一般ユーザで動かせたよ。
やったぜ。
さくらのクラウド(VPS)CentOS7でcertbotを使って無料でSSLサイト運用


たまにはキャッチーなタイトルを。「さくらの」とは言っていますが、epelの有効化以外は、CentOS7一般の手順と一緒です。epel-relesaseはプリインストールされているんですが、無効化されているため、certbot公式の手順がうまくいきません。apacheとmod_sslはインストール済みの状態を想定しています。

まずは、epelの有効化をします。

``` /etc/yum.repos.d/epel.repo
[epel]
(略)
enabled=1
(略)
```

続いてcertbotをインストールします。

```
yum install python-certbot-apache
```

ssl.confの最後尾(/VirtualHostの直前)に以下の設定を追加します。ホスト名やディレクトリは適宜読み変えてください。

``` /etc/httpd/conf.d/ssl.conf
ServerName foobar.net
<Directory /opt/foobar.net/pub>
  AllowOverride All
  Require all granted
</Directory>
```

certbotを起動します。ssl.confの設定が正しければ、ウィザードの指示に従って簡単に完了できると思います。

```
certbot
```

これでServerNameで指定したFQDN(foobar.net)のSSL証明書の作成と導入が完了です！ブラウザからアクセスして有効な証明書がインストールされていることを確認してください。

SSLだけで運用したい（暗号化無しでは使わないで欲しい）場合、以下のようにリダイレクトを設定します。

``` /etc/httpd/cond.d/foobar.conf
<VirtualHost *:80>
  ServerName foobar.net
  ServerAlias www.foobar.net
  Redirect "/" "https://foobar.net/"
</VirtualHost>
```

証明書の更新も自動化しておきます。certbotで生成した証明書は3ヶ月で期限が切れるため、その前に必ず更新が走るように設定しておく必要があります。下記例では毎月2回更新していますが、renewコマンドは”必要に応じて"しか更新処理を行わないため、毎日起動するようにしておいても構いません。

```
0 0 1,15 * * certbot renew
```


## 参考リンク
- https://certbot.eff.org/
- http://httpd.apache.org/docs/current/rewrite/avoid.html#redirect
git amend(修正)なやつ

gitを使っていてちょっとした修正を前のcommitに含ませたいときに使えるようです。  

```
git add 変更したファイル
```  
そして、  

```
git commit --amend
```  
多分ここで-mをつけたらメッセージも変更できるぽい  
commitがすっきりするようです。
【AWS】EC2 SQL Server

＊SQL Server on EC2構築しました

- AWSではすでにSQLServerのインストールされたEC2サーバーを作成することができる

##1. 作成
- EC2インスタンス作成時にAMIを選択できる
    - AMIはMicrosoft Windows Server 2012 R2 with SQL Server Expressを選択
- SecurityGroup
    - Type:MS SQL→SQLServerは1433ポートで接続するため
    - Type:RDP→作成したEC2にはRDP(Remote DeskTop)接続しかできない

##2. 接続
- 以下のサイトを参考にした
    - http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/connecting_to_windows_instance.html
        - Public IP：--.--.--.--
        - User name:Administrator
        - Password:----------(EC2インスタンス上で右クリックするとConnectionするための情報を取得できる


##3. 2.の手順で接続できないとき
- proxyが1433ポートの接続を許可していない可能性がある
- そのときは、ポケットwi-fiなどで外部のネットワーク上からRDP接続するしかない


### おまけ
- RD Gateway経由の方法を使えば、proxy内からRDP接続が可能になるらしい
    - http://scissors.cps2g.info/bCvuzQ
Symfony2でDIするサービスクラスにコンストラクタインジェクションでRequestオブジェクトを渡すやり方

メソッドインジェクションで渡す場合、
コントローラからそのままRequestオブジェクトを渡せばよいと思います。

```HogeController.php
public function editAction(Request $request)
{
    $service = $this->get('hoge.hoge_service');
    $service->tryHoge($request);

    return;
}
```

とても単純ですね。

そうではなく、コンストラクタインジェクションで渡す場合、
services.ymlを以下のように定義すれば渡すことができました。

```services.yml
hoge.hoge_service:
    class: Hoge\HogeBundle\Service\Hoge\HogeManager
    arguments:
        - @doctrine.orm.default_entity_manager
        - @validator
        - @request_stack    # ★リクエスト
        - @logger
```

```HogeManager.php
use Symfony\Component\HttpFoundation\RequestStack;

public function __construct(
    EntityManagerInterface $em,
    ValidatorInterface $validator,
    RequestStack $requestStack,
    LoggerInterface $logger
)
{
    $this->em = $em;
    $this->validator = $validator;
    $this->logger = $logger;
    $this->request = $requestStack->getCurrentRequest();        // ★リクエスト取得

    $this->rootUrl = $this->request->getSchemeAndHttpHost();    // ★取得したリクエストでいろいろできる
}
```

こうすることで、DIコンテナがRequestを自動で設定してくれるので
サービスクラスを利用するクラスはサービスクラスのRequestについて気にしなくてもよくなります。
PowerShell で、多項目中、複数項目の数の集計


20160701

または、`PowerShell` で `(sort |) uniq -c`

多分もっといい計算方法があるはず。

## やりたいこと

|名前|教科|点数|コメント|
|:--|:--|:--|:--|
|A|国語|100|-|
|B|国語|90|-|
|C|国語|90|-|
|A|理科|50|-|
|B|理科|70|-|
|C|理科|70|-|

`csv` でこんなのが山ほどあるとして、各教科で各点数が何名いるか集計したい場合。


つまり、`perl` でなら

```
$  perl -MTest::More -F, -lane '$a->{$F[1]}->{$F[2]} ++ }{ note explain $a' test.csv
# {
#   '国語' => {
#     '100' => 1,
#     '90' => 2
#   },
#   '理科' => {
#     '50' => 1,
#     '70' => 2
#   }
# }
```

なんてお茶を濁す作業。

**追記**

ヘッダ無しの場合のコード。ヘッダありの場合は、yumura_sさんのご指摘通り、一発ですね。


## `PowerShell` にて

Dos窓で、

```
> powershell
PS > cd bar
```

`PowerShell` を起動して、目的のファイルがあるところまで `cd`

### ワンライナー

日本語交じりなら、Shift-jis で。

**A**

```
PS > cat test.csv | %{ $a = $_.split(",") ; $a[1], $a[2] -join "," } | group $_ | select name, count
Name     Count
----     -----
国語,100     1
国語,90      2
理科,50      1
理科,70      2
```

**B**

```
PS > cat test.csv | %{ $a = $_.split(",") ; $a[1], $a[2] -join "," } | group -NoElement
Count Name
----- ----
1 国語,100
2 国語,90
1 理科,50
2 理科,70
```

- `sort` を付けたければ、各ワンライナーのあとに工夫して。
- A, B に違いが無いように見えるが、 B は、"Name" 文字列が長くなると後半が切れてしまって悲惨なことになる。
	- `Format-Table -Autosize` で、切れなくは出来る。

#### 試行錯誤中だった時のスクリプト

まあ、配列の作り方やらを備忘しとくのに。


```
$list= (Get-Content test.csv  | %{ $a = $_.split(",") ;  $a[1], $a[2] -join "," } )
foreach ( $item in ( $list  | sort -Unique ) ){
    $d = ( $list | Select-String -SimpleMatch $item  | Measure-Object ).Count
    Write-Output ( $item, $d -join "," )
}
```

## ごくごく初歩のメモ

どうせ、しばらく使わないので、メモっとく

### PowerShell の設定

ドス窓ひらいて、

```
> powershell
```

て打って、文句言われたら、`Set-ExecutionPolicy -Scope CurrentUser` あたりを打ち込む

### Powershell のコマンド

正式名称は長いけど、エイリアスが貼ってあるので、 `cd`, `ls`, `cat`, `more` あたりは、似たような感じで使える。

### pbcopy

`clip`

日本語を扱う場合は、 `$outputencoding=[console]::outputencoding` 貼り付けてから実行するが吉

`Set-Clipboard` は、面倒そう

### pbpaste

`Get-Clipboard`

### *shrc

```
PS >New-item –type file –force $profile
```

しといて、できたファイルに

```
$outputencoding=[console]::outputencoding
New-Alias pbpaste Get-Clipboard
New-Alias pbcopy clip
```

なんぞ書く。
GMTインストール その2.


[その1.](http://qiita.com/bunzaemon/items/4e089bd60522e750fe2c) の続き

20160801

1. WSL の有効化
2. Anaconda のインストール
3. GMT4.5
4. GMT5

### 20190208 メモ

メモ作成時点では気にしていなかったのですが、東海大学のFTPは繋がらない事が、ままある様です。

ミラーじゃなく本家からダウンロードしてください。

ftp://ftp.soest.hawaii.edu/gmt/


## 3. GMT4.5


1. 環境をアクティブに
2. 必要ライブラリなどのイントール
3. 本体のインストール
4. 確認

### 3.1. 環境をアクティブに

```
$ source activate gmt4
```

### 3.2. 必要ライブラリなどのイントール

その1.の作業で gshhg を除きインストール済み。

http://gmt.soest.hawaii.edu/projects/gmt/wiki/Download

より `gshhg-gmt` をダウンロード

```
$ cd ${HOME}/anaconda3/envs/gmt4
$ mkdir -p src
$ mkdir -p share/gmt
$ cd src
# ダウンロードしたものをここに移動
$ tar zxf gshhg-gmt-2.3.6.tar.gz
$ mv gshhg-gmt-2.3.6 ../share/gmt/gshhg
```

- 古いバージョンで良いなら、`ftp://ftp.scc.u-tokai.ac.jp/pub/gmt/gshhg-gmt-2.3.4.tar.gz`

### 3.3. 本体のインストール


```
$ cd ${HOME}/anaconda3/envs/gmt4/src
$ wget -q ftp://ftp.scc.u-tokai.ac.jp/pub/gmt/gmt-4.5.13-src.tar.bz2
$ tar xjf gmt-4.5.13-src.tar.bz2
$ cd gmt-4.5.13
$ ./configure \
    --prefix=${HOME}/anaconda3/envs/gmt4 \
    --with-gshhg-dir=${HOME}/anaconda3/envs/gmt4/share/gmt/gshhg \
    --enable-triangle \
    --disable-flock \
    --enable-eps
$ make
$ make install-gmt
$ make install-data
$ make install-man
$ make install-doc
```

### 3.4. 確認

```
$ gmtdefaults -D | head
#
#	GMT-SYSTEM 4.5.13 [64-bit] Defaults file
#
#-------- Plot Media Parameters -------------
PAGE_COLOR		= white
PAGE_ORIENTATION	= landscape
PAPER_MEDIA		= a4+
#-------- Basemap Annotation Parameters ------
ANNOT_MIN_ANGLE		= 20
ANNOT_MIN_SPACING	= 0
```

## 4. GMT5

1. 環境をアクティブに
2. 必要ライブラリなどのイントール
3. 本体のインストール
4. 確認

### 4.1. 環境をアクティブに

```
$ source activate gmt5
```


### 4.2. 必要ライブラリなどのイントール

その1.の作業で `gshhg`, `dcw` を除きインストール済み。

http://gmt.soest.hawaii.edu/projects/gmt/wiki/Download

より `gshhg`, `dcw` をダウンロード

```
$ cd ${HOME}/anaconda3/envs/gmt5
$ mkdir -p src
$ mkdir -p share/gmt
$ cd src
# ダウンロードしたものをここに移動
$ tar zxf dcw-gmt-1.1.2.tar.gz
$ tar zxf gshhg-gmt-2.3.5.tar.gz
$ mv src/dcw-gmt-1.1.2 share/gmt/dcw
$ mv src/gshhg-gmt-2.3.5 share/gmt/gshhg
```

- 古いバージョンで良いなら、
    - `ftp://ftp.scc.u-tokai.ac.jp/pub/gmt/gshhg-gmt-2.3.4.tar.gz`
    - `ftp://ftp.scc.u-tokai.ac.jp/pub/gmt/dcw-gmt-1.1.1.tar.gz`


### 4.3. 本体のインストール

http://gmt.soest.hawaii.edu/projects/gmt/wiki/Download

より本体ダウンロード


```
$ cd ${HOME}/anaconda3/envs/gmt5/src
# ダウンロードしたものをここに移動
$ tar xzf gmt-5.2.1-src.tar.gz
$ cd gmt-5.2.1/
$ cp cmake/ConfigUserTemplate.cmake cmake/ConfigUser.cmake
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=${HOME}/anaconda3/envs/gmt5 ..
$ make all
$ make install
```


### 4.4. 確認

```
$ gmtdefaults -D | head
#
# GMT 5.2.1 Defaults file
# vim:sw=8:ts=8:sts=8
# $Revision: 15178 $
# $LastChangedDate: 2015-11-06 11:45:03 +0100 (Fri, 06 Nov 2015) $
#
# COLOR Parameters
#
COLOR_BACKGROUND                = black
COLOR_FOREGROUND                = white
```
【JavaScript】PC,スマートフォン両方に対応したツイートボタン

せっかくQiitaに登録したので適当に情報をまとめていきたいと思います。

最近Webサイトをちょこちょこいじる機会が多かったので今回は比較的自由で簡単にできるツイートボタンの設置についてです。

#ソース
```qiita.html
<!DOCTYPE html>
<html>
	<head>
		<title>ButtonTest</title>

		<meta charset="utf-8">

		<style type="text/css">
			*{
				text-align: center;
				font-family: meiryo;
			}

			input{
				background: rgba(0,132,180,.8);
				border: 1px solid transparent;
				border-radius: 4px;
				color: #FFFFFF;
				display: block;	
				font-size: 16px;
				margin: 0 auto 100px auto;
				padding: 15px 0 15px;
				text-decoration:none;
				text-align: center;
				transition: all  0.3s ease;
				width: 300px;
				-webkit-appearance: none;
			}
		</style>

		<script type="text/javascript">
				function tweetpost(){
					var EUC = encodeURIComponent;
					var twitter_url = "http://twitter.com/?status=";
					var URL = window.location.href;
					var message;

					//あらかじめ設定されたツイート内容と現在いるページのURLを取得してツイートします。
					message = "ここにツイート内容を入れる\n" + URL;

					if (navigator.userAgent.indexOf('iPhone') > 0 || navigator.userAgent.indexOf('iPad') > 0 || navigator.userAgent.indexOf('iPod') > 0 || navigator.userAgent.indexOf('Android') > 0) {
						location.href = 'https://twitter.com/intent/tweet?text=' + EUC(message);
					}else{
						window.open(twitter_url + EUC(message), "_blank","top=50,left=50,width=500,height=500,scrollbars=1,location=0,menubar=0,toolbar=0,status=1,directories=0,resizable=1");
					}
				}
		</script>
	</head>

	<body>
		<p>このボタンをクリックするとツイートすることができます。</p>
		<input type="button" value="Tweet" onclick="tweetpost()"/>
	</body>
</html>
```

#解説
CSS部分は見た目を整えたかったから書いただけ
実際にはhtmlとJavaScript部分だけで十分です。

コピペしてブラウザで開いてみるとこんな感じになってると思います。
(それすら面倒くさい方は[こちらのデモページ](http://sometrouble.net/tekitou/qiita_js001)をどうぞ)
***
![f8220f47265a08ba1db8d6fd9fe0d46c.png](https://qiita-image-store.s3.amazonaws.com/0/139165/78fab4ae-36cf-41d5-7ed7-268916800dfb.png)
***
青いTweetボタンをクリックするとtweetpost関数が呼ばれてユーザーエージェントを取得、
iPhone,iPad,iPod,Androidのいずれかだとlocation.hrefでツイート画面に飛びます。
それ以外（PCなど）はwindow.openで小ウィンドウが生成されてツイートができます。

WindowsPhoneとかBlackBerryはどうなるか知りません。

リンクをツイートするだけならTwitterが提供してる[こっち](https://about.twitter.com/ja/resources/buttons)で十分なんですけど、
もうちょっと凝ったことをしたいときなんかにお役立て頂ければ幸いです。


***
2016/09/20 追記

iPhoneの場合cssの

```
-webkit-appearance: none;
```
は指定しないとボタンのデザインが変えられない(ダサい)のでちゃんと指定してあげてください。
***
比較：指定前
<img width="375" alt="2e15e079c1b16a0ba2592cc812d3587e.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/139165/1f898631-357e-8013-aa3f-c245be51ff63.jpeg">

比較：指定後
<img width="375" alt="16d1ea3f12289b26391b1bfd54745c7c.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/139165/b3dc4fe4-423b-b4c1-f1d3-9eeb98801d22.jpeg">
***


また、スマートフォンレイアウトに対応させる場合、**\<head>~\</head>**間に

```
<meta name="viewport" content="width=320, minimum-scale=1.0, maximum-scale=2.0">
```

と記述してあげるといい感じになります。
[デモページ2](http://sometrouble.net/tekitou/qiita_js002)
GMTインストール その1.


20160801

Windows10 上。
つっても、WSL の上の `Anaconda` 上にだけど。

`GMT` とは、地図描画コマンドで、グラフも描けたりするソフト。

1. WSL の有効化
2. Anaconda のインストール
3. GMT4.5
4. GMT5


## 1. WSL の有効化

Windows Subsystem for Linux

windows 10 のみ

1. 設定アプリ => 更新とセキュリティ => 開発者向け => 開発者モード選択
2. 再起動後、プログラムと機能（スタートボタン右クリック）からWindowsの機能の有効化または無効化 => Windows Subsystem for Linux を有効に
3. 必要に応じて再起動後 `cmd.exe` 上で `bash` と打ち、ユーザー名とパスワードを設定

### 最初にごにょごにょ

```
$ sudo vi /etc/hosts
```

二行目に

```
127.0.1.1 YOURHOSTNAME
```

を追加

```
$ sudo apt-get install build-essential gfortran
$ sudo apt-get install ghostscript
```

でコンパイラなどをインストール。
`ghostscript` に関しては、`gmt` で要求されることから

## 2. Anaconda のインストール


https://www.continuum.io/downloads

から、Linux 用の `Anaconda3-4.X.X-Linux-x86_64.sh` をダウンロード

```
$ bash ./Anaconda3-4.1.1-Linux-x86_64.sh
```

を実行すると、通常 `${HOME}/anaconda3` にインストールされる。

- 質問には yes でよい
    - PATH はインストーラーの指示に従ってもいいし、自身で登録してもいい。

### 新規環境構築


```
$ conda create -n gmt4 anaconda      # 環境作成
$ conda create -n gmt5 anaconda      # 環境作成
$ source activate gmt5               # 環境呼び出し
```


### libcom_err.so.3

**GMT5のインストール時のみ**

- `gmt5` の `make all` 実行時に以下のエラーが起こるため

```
/usr/bin/ld: warning: libcom_err.so.3, needed by ${HOME}/anaconda3/env/gmt5/lib/libgdal.so, not found (try using -rpath or -rpath-link)
```


`libcom_err.so*` を探して、シンボリックリンクを貼れば動きます。

```
$ cd ${HOME}/anaconda3/env/gmt5/lib
$ ln -s /lib/x86_64-linux-gnu/libcom_err.so.2.1 libcom_err.so.3
```

環境ごとに違うので、`/lib`, `/usr/lib`,  `/lib64`, `/usr/lib64` などに当たりをつけて探す必要あり。


### GMT 用最低限のライブラリ・コマンドインストール

`netcdf4` などは、デフォルトで入っています[^1]。

[^1]: 【2019/05/24 追記】バージョンが違うAnacondaでは入ってない場合もあるみたいなので、その時は、conda install netcdf4 する。

```
$ conda install -c menpo fftw         # GMT 用のライブラリ等のインストール
$ conda install gdal libgdal=2.0.0=0  # 〃
$ conda install cmake                 # GMT5 を入れるつもりなら。
```

- `libgdal` のバージョンが `2.0.0-1` からは、コマンドによってはコンフリクトを生じさせるため、あらかじめダウングレード。
rex0220 計算項目更新プラグイン

計算項目の追加や計算式の変更を行った場合、計算項目更新プラグインで既存レコードの計算項目を更新出来ます。

・対象アプリの全レコードの更新を行い、計算項目の値を再設定します。
・プラグイン設定画面に計算項目を表示
・レコード取得・更新をパラレル処理することで、高速化
・３ヶ国語対応

※フォーム設定で計算項目を変更した場合、本番環境へ反映後にプラグインで既存レコードを更新してください。

[rex0220 stores](https://rex0220.stores.jp) で、販売中です。

Ver.5 変更点
・一括更新時、「パラレル更新」のチェックボックスでパラレル処理の有無を指定
　※更新がエラーになる場合は、チェックを外して実行

# プラグインの追加

![calc11.png](https://qiita-image-store.s3.amazonaws.com/0/100572/3a4b6073-6c30-22b4-3523-9a7c55f5d97c.png)

# プラグインの設定画面
指定レコードを更新しますので、事前にデータのバックアップを取ってから実行してください。

・「既存レコードを変更」をクリック
![2022-05-06_10h47_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/93fecf9f-1092-1145-f595-f64c3acf6bee.png)


# 既存レコードの更新

- パラレル更新
チェック時、最大５のパラレル更新を行います。

![2023-02-02_13h59_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/502caaf2-6575-007e-9af1-a5113473873c.png)
![2023-02-02_14h00_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/11dda2d8-d823-0b85-ed65-51bfbbaf8f5a.png)
![2023-02-02_14h02_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/8b70be6e-8314-2910-ba0e-0a09c21f5c34.png)


# 更新エラーについて

必須項目や文字数制限などの制約を付与後、既存レコードの項目の値を変えていない場合、
既存レコードの更新を行うと、エラーになります。
既存レコードの項目値の変更を行ってください。

![2022-05-06_10h56_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/fcac532e-2745-2239-979f-f6efd1269850.png)

# REST API の実行回数制限について

1日に実行できるAPIリクエスト数は、1つのアプリにつき10,000件です。
[kintone ヘルプ 制限値一覧](https://jp.cybozu.help/k/ja/admin/limitation/limit.html)

計算項目更新プラグインで、50万件のレコードを更新する場合、約6千件の REST API を発行します。
50万件のレコード処理の REST API 発行回数の内訳
・対象レコード件数取得　1
・レコード取得 500,000 / 500 = 1,000
・レコード更新 500,000 / 100 = 5,000

レコード件数が多い場合は、csv 読み込みによる計算項目の更新をご検討ください。

# 注意事項
フォーム設定で計算項目を変更した場合、本番環境へ反映後にプラグインで既存レコードを更新してください。
Web VRとは？

# よくある誤解

-----

## よくある誤解

* スマホで画面分割表示するやつでしょ？
* ポジトラできないんでしょ？
* 描画が微妙じゃない？


-----

## 違うのです＞＜

-----


# Web VR #とは？


-----

## ブラウザVR ↔ WebVR API

__本書での定義__

<dl>
 <dt>ブラウザVR</dt>
  <dd>Webブラウザを通じたVR体験およびコンテンツ</dd>
 <dt>WebVR API</dt>
  <dd>VRデバイスの情報取得API<br />W3Cにて仕様策定中(Editor's Draft)
  </dd>
</dl>


----- 

# WebVR APIで出来ること

* HMD情報の取得
    * VRデバイスID, IPD
* HMDイベントの取得
    * HMD接続・接続解除/表示中/装着中* HMDの向き情報（速度/加速度）の取得
* HMD位置の取得
    * ViveやOculusポジトラありの場合
    * 座位→立位の変換マトリクス
* ＋HMDでの描画補助
    * HMDの垂直同期対応, 描画対象canvas指定
* ＋Viveコントローラ情報(Gamepad API)

------

# ブラウザVR

ブラウザに実装された各種APIを用いて，
ブラウザを通じて，VR体験を提供する．

例えば，
* スマホのブラウザで360°動画
* A-Frameでちょっと作ったCardboard系体験

※ WebVR APIを使っていない場合もありまーす！

-----

# ブラウザVRを支える技術

* WebVR API
  * HMD情報の取得
    * PCVRの場合は位置情報も
* Gamepad API
  * VRコントローラ情報の取得
  * フィードバック
* WebGL
  * 3D空間の描画/画面分割
* WebAudio
  * 音の操作

-----

## よくある誤解の解消

* ~~スマホで画面分割表示するやつでしょ？~~
    * WebVR APIはPCVRデバイス情報も取得可能
    * 画面分割はWebVR APIの仕事じゃないもん！
        * 分割描画に必要な情報の生成につかいます
* ~~ポジトラできないんでしょ？~~
    * できる！（VRデバイスによる）
* ~~描画が微妙じゃない？~~
    * 主にjavascriptとWebGLによるものです．
    * 2画面分の計算は大変なんだよ！

--------

## WebVRコンテンツを作るには？

* フルスクラッチ
* WebVR boilerplate with Three.js
* フレームワーク
    * [A-Frame](https://aframe.io/)：HTML記述のみで実現
    * [Solufa](http://solufa.io/) : Virtual DOM
* CMSの利用
* Unity WebVR Exporter (gtk2kさん策)
    * [紹介記事](https://dev.mozilla.jp/2016/06/exporting-an-indie-unity-game-to-webvr/)

-----

# 最近のWebVR API事情

トピック
* FirefoxでOculus DK1に表示 (2014)
* WebVR API Spec v1.0 (2016/03/01) 
* WebVR API 仕様策定をW3Cへ移管 (2016/06/02) 
* WebVR API Spec v1.1 (2016/09/09)
* MS Edge のWebVR API対応表明 (2016/09/09)

----- 

# Web VRを取り巻く課題(山積み)

* [A] PC向けVRには特殊なブラウザが必要
    * Chromium(WebVRビルド) / Firefox Nigthly
    * Samsung Internet for GearVR
* [C] js/webglのボトルネック
* [C] マルチデバイス対応向け
    * モバイルとPCで同一の体験を提供できない？
* [A] https…
* ......

-----

# まとめ

* ブラウザVR ≠ WebVR API
  * WebVR APIはPC用VR HMDも扱える仕様
* 実用性は未知数
  * 動作環境に制限あり
  * 仕様もUnstable...

手を出すのはまだ早い（かも）
PCVR用にはChrome/Firefoxの正式対応待ち◎

-------

# 参考

* [W3C WebVR Spec](https://w3c.github.io/webvr/)
* [WebVR.info](https://webvr.info/)
* [Is WebVR Ready?](https://iswebvrready.org/)
* [MDN WebVR API](https://developer.mozilla.org/ja/docs/Web/API/WebVR_API)
    * 翻訳中...(Help me!)

---------

# 自分用メモ
* 簡単に作れてしまう
* → VR酔いへの対処などを無視した悪質コンテンツ増
* → VRの価値低減