OmniAICreator/Qiita-1.07M huggingface dataset:
Ruby on Rails チュートリアル学習記録

Ruby on Railsチュートリアル学習記録です。

一度で理解できないポイントがいくつかあるので、咀嚼する意味を含めてアウトプットしております。

## 6.2.5 一意性を検証する

今日は、6.2.5の実験をしていますが、一意性の検証用のコードは、rails consoleのアウトプットと合わせて読むと理解しやすいと思っています。

### minitestからの一意性検証部分を抜粋

upcaseしているため一意性は確保されています。

@user.saveで一度データベースへ登録（INSERT）後に、duplicate_user.valid?でデータベース内のデータの重複チェックを実施。

これは、falseが返るので、assert_notで成功するので重複チェックテストが通るという理由ですね。

うん、アウトプットは理解を深めますね。

```ruby:user_test.rb
  test "email addresses should be unique" do
    duplicate_user = @user.dup
    duplicate_user.email = @user.email.upcase
    ### データベース内の存在性確認のため、一度INSERTしている
    @user.save
    assert_not duplicate_user.valid?
  end
```
### Userモデルコード

```ruby:app/models/user.rb
class User < ApplicationRecord
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
end
```

### rails consoleアウトプット

user_test.rbと同等の状態を再現しています。

最後にfalseになることを確認するのがポイントです。

```ruby
$ rails console --sandbox
Running via Spring preloader in process 459
Loading development environment in sandbox (Rails 5.1.4)
Any modifications you make will be rolled back on exit
>> user = User.create(name: "Example User", email: "user@example.com")
   (0.1ms)  SAVEPOINT active_record_1
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "user@example.com"], ["LIMIT", 1]]
  SQL (2.2ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Example User"], ["email", "user@example.com"], ["created_at", "2017-12-19 02:51:04.441985"], ["updated_at", "2017-12-19 02:51:04.441985"]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> #<User id: 1, name: "Example User", email: "user@example.com", created_at: "2017-12-19 02:51:04", updated_at: "2017-12-19 02:51:04">
>> duplicate_user = user.dup
=> #<User id: nil, name: "Example User", email: "user@example.com", created_at: nil, updated_at: nil>
>> duplicate_user.email = user.email.upcase
=> "USER@EXAMPLE.COM"
>> duplicate_user.valid?
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "USER@EXAMPLE.COM"], ["LIMIT", 1]]
=> false
>>
```
freespotでmacアドレスを偽装してwifiの接続時間を伸ばす

freespotで登録なしで使えるのは10分間です。登録したくない、でもたくさん使いたいって時にどうぞ。
#スクリプトをつくる

```
vim wifi.sh
```

正規表現でmacアドレスをランダムで作っています
\#!/bin/shの部分はシバンといいshがこの構文を理解します。
構文は以下の通り


```
#!/bin/sh
 
sudo ifconfig en0 ether $(perl -e 'for ($i=0;$i<5;$i++){@m[$i]=int(rand(256));} printf "02:%X:%X:%X:%X:%X\n",@m;')
 
sudo ifconfig en0 down
 
sudo ifconfig en0 up
 
ifconfig en0
```


#実行する

```
sh wifi.sh
```
　
freespotだと接続時間に制限がある場合があります。その場合macアドレスを変更することで別のデバイスが接続されたと認識させます。

たとえば10分の接続時間の制限がある場合
yesコマンドで実行させるコマンドの文字列を生成してパイプで渡して9分おきにwifi.shを実行します。

```
yes 'sh wifi.sh;sleep 540' | sh
```
vueかnuxtか（今のところのnuxtについて）

> ### 2018.11.27 update2
> [ダイナミックレンダリング](https://developers.google.com/search/docs/guides/dynamic-rendering)を利用できればSEOのためのSSRは必要ない。TypeScriptを使う場合、vueの方が資料も多い。
> vue-cliの発展でプロジェクトsetupやビルドはnuxtと変わらないレベルで簡単。
> パフォーマンスのためのSSRが必要ならNuxt.jsだが、そうでなければ今はvueを選ぶ。

---

> ### 2018.8.8 update
nuxt正式リリースしてしばらく経った。試す機会があったので改めて比べてみたが、現在はvueで始めるよりはnuxtを利用する方がメリットが大きいと思った。（vue v2.5.17 / nuxt.js v1.4.2）

> * ビルドスピードは十分早くなった
* SSRを利用しなくても `nuxt generate --spa` でvueプロジェクトと大体同じデプロイフローを取れる。※routingのpropsをpagesコンポーネントに渡せるかは調べてないので不明（ここはネックになり得る）
* SSRはやっぱり必要になる可能性が高い（googlebotは問題なくてもtwitter,facebookのクローラーはjs不能）

> vueをnuxtにしたとして、SSRをやらない限りは、開発コスト・学習コストは殆ど変わらないと思う。今新規でspa開発をするなら自分はnuxtを使うと思う。

---
以下元の本文

---

対象バージョン

* vue 2.5.x
* nuxt.js 1.0.0-rc11


## SSR(Server side rendering)の必要性

SSRの目的はたいていSEOのためではないだろうか。しかしgooglebotはjavascriptを理解するし、非同期通信も行うので、正当に作っていればvueのみのSPAでも正しくインデックスされる。(Google Search ConsoleのFetch as googleで確認できる）

## 運用ハードルが高い

nuxtの場合は基本nodeサーバで動くので、それに沿った運用計画が必要。サーバスケーリングやデプロイをどうするか。この辺は公式で勧められているPaasなどを使うのが順当そう。AWSの場合はEC2でシンプルに運用するのは難しくてECSでコンテナベースでインフラ作る形になるのかな。

nodeやexpressを使ったサーバ運用やコンテナ運用の知見が乏しい場合、ハードルが上がる。


## ~~nuxt generateについて~~
 * **コメントで指摘を受け削除。nuxtコマンド時にspaオプションを付けることで対応可能な模様**

~~これはvueのbuildみたいに静的サイトとして生成してくれるものと思っていたが、それは間違っていないのだが、動的ルーティングができない。
vue-routerで`/users/:id`のようなパスを切ってる場合は、[設定で全ての存在するパスをリストしなければならない。](https://ja.nuxtjs.org/api/configuration-generate#routes)
もちろんgenerateの場合のみでnuxt startでの利用時はそんなことないのだが、「いざとなったら静的サイト出力すればいいや」が出来ない場合がある。~~


## vue-routerのprops:trueが使えない

`/users/:id`のid値を、pagesコンポーネントのpropsに渡せない。[vue-routerの機能](https://router.vuejs.org/ja/essentials/passing-props.html)。
[無理やりnuxtのテンプレートをいじって解決](https://github.com/nuxt/nuxt.js/issues/1502#issuecomment-347491774)できるが、あまりやりたくないハック。

## webpack build設定の上書きが面倒

[既に設定されたオブジェクトについて差し替え](https://ja.nuxtjs.org/api/configuration-build#extend)る形で面倒。loader系はloader名がキーになってるわけではないので探す必要がある。。

```js
    // vue settings
    const vueLoaderIdx = config.module.rules.findIndex(r => r.loader === 'vue-loader')
    // html内の画像URLなどを対象にする（元の設定だとimgがない）
    config.module.rules[vueLoaderIdx].options.transformToRequire = {
      embed: 'src',
      img: 'src',
      video: 'src',
      source: 'src',
      audio: 'src',
      image: 'xlink:href',
    }
```

## nuxt devのビルドが遅い

server/clientのコードを両方ビルドしてるから？なんかvueのbuildより体感２倍くらい遅い。これは正式版になったら解決するのかも。masterブランチで試してみた際はもっと早かった。


---

いろいろ書いたけどvueでSSRしようとしたらnuxt.js一択ではある。vue-server-rendererはかなり低レイヤーなので実装が大変だ。

nuxtは現在rc11（９月リリース）で間もなく正式版がリリース予定。前のリリースから時間があいているため、結構大きな変更になることが予想される。
プロジェクトが上手くいかなくなる前に知っておくこと その3

この記事はサムザップ Advent Calendar 2017の19日目の記事です。
昨日は[satotin](https://qiita.com/satotin)さんの[UnityからIL２CPPビルドしたXcodeプロジェクトにブレイクポイントを貼ってデバッグしたい](https://qiita.com/satotin/items/db72698253a1725fed21)でした。

昨日のsatotinさんありがとうございます。
*戦いとは、常に二手三手先を読んで行うものだ*fujisyunです。

別の事書くつもりだったけれど
｢変更管理知らなかったです!｣って言う人がいたので、
変更管理についておさらい。

# アジェンダ

+ これだけは覚えていってね
+ やること
+ おわりに

# これだけは覚えていってね

*要求の変更やインシデントに対し、
変更管理することでプロジェクトへの影響を最小限にして対応する。*



プロジェクトマネジメントの領域では、
プロジェクトの進行において、変更は起こりうるものと認識されています。
変更管理という行動はプロジェクト開始したときから行われます。
ニュアンスとしては、準備と考えてもらうとよき。

# 統合マネジメント [PMBOKより](https://www.pmi-japan.org/topics/pmi1/pmbok_5_10.php)
+ プロジェクト憲章作成
+ プロジェクトマネジメント計画書作成
+ プロジェクト作業の指揮・マネジメント
+ プロジェクト作業の監視・コントロール
+ **統合変更管理**
+ プロジェクトやフェーズの終結

ちゃんとPMBOKにも載っているかんね。
※PMBOK=プロジェクトマネジメントの知識体系

# 参考:不確実性コーン

![chart.png](https://qiita-image-store.s3.amazonaws.com/0/217305/2ecd7f5e-a957-9956-b697-dddcc21836e8.png)

プロジェクトの進行は立ち上がりの時ほど、
コスト(見積もり)と結果の乖離が大きくなる可能性がある。


# 変更管理を実施する前に注意すること
計画、リスク洗い出し、振り返りがあっての変更管理。

そのようにしてプロジェクトのチームを強化していかなければ、
何度となく変更管理が発生しプロジェクトの失敗に繋がることになる。

## 計画

WBSや見積もり、変更を管理するには変更を監視するための計画が必要。
**作業者が迷いなく進められるくらいに詳細であること。**
**抜けがちな作業としては、異常系や非機能系。**
**見通しが立たない範囲は別途計画を立てるようにするほうがオススメです。**

## リスク洗い出し

インシデントにたいして予め対策を立てておく。
Bプラン。

## 振り返り

次、同様の変更管理が発生しないように、
原因の追求と対策をしっかり行う必要があります。

# 変更管理

主に、変更を要求する者がプロジェクトマネージャーに対して変更を要求する。

+ プロダクトの仕様変更
+ 人員、機材などの変更
+ スケジュールの変更
などなど、計画からの変更があった場合に起票する。

# 起票内容

主に3点くらいは押さえておくとよきかと。

+ 対応者と作業内容
+ 影響する作業
+ 影響する条件(見積もりや予算、制約など)

プロジェクトを成功させるために詳らかにする。
これらの情報をもとに変更の決裁を行う。

# おわりに

変更管理"だけ"の話なので
｢何かあれば変更すればいいや!｣｢変更してよかったんや!｣とみえてしまっていたらすみません。
それは文章の書き方がまずいか認識の間違いです。

**プロジェクトの管理者は、変更管理が発生しないように
計画、リスク洗い出し、振り返りなどを実施する必要があります。
そして、もし変更管理が必要になった場合は、詳らかに情報を共有しながら、
プロジェクトの成功へ向けて最小限の影響でおさまるよう努力しましょう。
それがプロジェクト管理者の義務です。**

変更管理が発生しなければしないほどプロジェクトの成功の可能性が高くなってくると思います。
プロジェクトは変更が発生するものですが、その変更に柔軟に対応出来るよう常に準備して進めましょう。

ということで明日はyou1933さんで
『Unity　ちょっとシェーダーで遊んでみた』のお話です。
you1933さんのシェーダーテク楽しみっす!
では、よろしくおねがいします!
GameViewをフルスクリーンにする

![FullScreen.png](https://qiita-image-store.s3.amazonaws.com/0/141731/a7282453-e87d-79de-bd05-c0c4b08d4c5d.png)

UnityはPC上(UnityEditor)と各デバイス上でほぼ同じ画面が再現できるのと、Editorのほうがいろいろデバッグ機能を入れたりできるので、PCで動画収録したいなーということがあるかと思います。

となるとフルスクリーンにしたいところなんですが、GameViewにはそのものズバリな設定はなく、"Maximize On Play"もあくまで「Editorウィンドウ内で最大化」するもので、なんか違う…ということなります。

ということで、GameViewをフルスクリーンにするスクリプトを書いてみました。(Unity2017.1.1f1で確認)

```FullScreenGameView.cs
using UnityEngine;
using UnityEditor;

// GameViewをフルスクリーンで表示するスクリプト(WindowsはF11、macOSはCommand+Shift+Fでトグル動作)
public class FullScreenGameView
{
    const string menuPath = "Window/Game (Full Screen)";

#if UNITY_EDITOR_WIN
    [MenuItem(menuPath + " _F11", false, 2001)]
#elif UNITY_EDITOR_OSX
    [MenuItem(menuPath + " %#f", false, 2001)]
#endif
    public static void Execute()
    {
        EditorWindow gameView = GetGameView();

        if (Menu.GetChecked(menuPath) == false)
        {
            gameView.Close();       // ドッキング中にサイズを変えるとEditorのサイズも変わってしまうため一旦閉じる

            float width = Screen.currentResolution.width;
            float height = Screen.currentResolution.height;
            float offset = 17.0f;   // GameViewのコントロールバーの高さ(Unity2017.1の場合) ※タブや枠は計算に入れない

            gameView = GetGameView();
            gameView.minSize = new Vector2(width, height + offset);
            gameView.position = new Rect(0, -offset, width, height + offset);

            Menu.SetChecked(menuPath, true);
        }
        else
        {
            // 位置パラメータをデフォルトに戻してからClose
            gameView.minSize = minSize;
            gameView.position = position;
            gameView.Close();

            Menu.SetChecked(menuPath, false);
        }
    }

    private static EditorWindow GetGameView()
    {
        // ウィンドウが存在しない場合は生成される
        return EditorWindow.GetWindow(System.Type.GetType("UnityEditor.GameView,UnityEditor"));
    }

    // デフォルト位置パラメータ(元の位置には戻せないので、扱いやすい位置＆サイズにしておく)
    private static Vector2 minSize = new Vector2(100.0f, 100.0f);
    private static Rect position = new Rect(0.0f, 0.0f, 640.0f, 480.0f);
}
```

UnityEditorのメニューから"Window/Game (Full Screen)"を選択するか、ショートカット(WindowsはF11、MacはCommand+Shift+F)でトグル動作するようになっています。

なお、Macの場合は事前にUnityEditorの左上の緑ボタンを押して全画面モードにしておくか、システム環境設定でメニューバーとDockを消しておく必要があります。本来のお作法としてはフルスクリーン化のショートカットはCommand+Control+Fなんですが、MenuItemではMacのControl(Ctrlではない)は指定できないようです。

やっていることとしては、GameViewを取得して最小サイズをフルスクリーンと同じサイズにして、コントロールバーの高さ分だけ上にずらして位置を設定しています。これは、最小サイズをフルスクリーンにしないと、Unityが気を利かせて画面内に収まるように小さく調整してしまい、タブやウィンドウ枠が見えてしまうためです。

キモとしましては、EditorWindow.GetWindow()にUnityEditor.GameViewクラスを指定するんですが、privateなのでそのままでは使えません。そこで、C#のSystem.Type.GetTypeを使ってUnityEditorのアセンブリから型を取得しています。

C#って何でもありなのね…。
GAE の開発サーバーで監視対象ファイルが多すぎてオートリロードが無効になる場合の対応方法

# はじめに

* GAE の開発サーバー dev_appserver.py を実行した際に監視対象ファイルが多すぎるとオートリロードが無効になる

```
/PATH/TO/SDK/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/mtime_file_watcher.py:184: UserWarning: There are too many files in your application for changes in all of them to be monitored. You may have to restart the development server to see some changes to your files.
  'There are too many files in your application for '
```

# 対応方法

* GAE の設定で監視対象外ファイルを正規表現で指定する
* GAE/Go だと $GOPATH 以下を全て監視しようとするので vendor や node_modules やファイルの多いプロジェクトを無視すると良さそう

```yaml:app.yaml
skip_files:
- .*node_modules
- .*vendor
- .*project-name-having-too-many-files
```
mastodonを1.3くらいから2.1.0まで一気にあげた

多分誰も求めてないけど、備忘録

# アップデート前

バージョン忘れたけどWebpack導入直前

## 環境

- 非Docker, Ubuntu 16.04
- 1台のLinux上でDB兼用、redisは独立で複数インスタンスが共存

# 結局なにがはまったの？

- 通知の設定が増えてたので.env.productionに2行追加
- bundle installしようとしたらrubyが2.4.1つかってたのに2.4.2になってた
  - rbenvのアプデが必要
  - あと、bundlerのgemもいれないとだめ
- bundle installしようとしたらbuildでこける
  - 必要パッケージが増えてたので最新のproduction-guideのapt installを流し直した
  - https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Production-guide.md
  - 実際はletsencryptはいらないので抜いた
  - apt -y install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file git-core g++ libprotobuf-dev protobuf-compiler pkg-config nodejs gcc autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev nginx redis-server redis-tools postgresql postgresql-contrib  yarn libidn11-dev libicu-dev
- db:migrateでコケる
  - https://github.com/tootsuite/mastodon/issues/3938
  - RAILS_ENV=production bundle exec rails mastodon:maintenance:prepare_for_foreign_keys
- assets:precompileでこける
  - nodejsのバージョンが古かった。アプデしたら解決
  - 4系しかリポジトリが入ってなかったので以下でいれた
  - curl -sL https://deb.nodesource.com/setup_6.x | bash -
- cronの設定が変わったので変更
  - 既存のものはすべてsidekiqに取り込まれたので不要に
  - 画像とかのリモートリソースの削除がdailyに
    - これ、あるインスタンスだと70GBくらいになってたのが20GBまで減ったので大変幸せになった

# 進め方

基本Updating-Mastodon-Guideの通りに。差分は前述。

https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Updating-Mastodon-Guide.md

# 感想

- 思ったよりも簡単にアプデできた。こんなに楽にできるならもっと前にしておけばよかった！
- ActivityHubが神がかってて、幸せになった
- 利用者から感謝の声が！！
- TwitterBANされたので自分としてもはっぴー

---
追記(同日)

1.3くらいにアップグレードしたときもそうなんですが、.env.productionに項目が増えてることが割とあるのですが、updatingのガイドにその話がないので、アプデするときはそこ注意したほうがいいです。
【論文シリーズ】多語彙音声認識に応用される深層テンソルNN

## 原文
[The Deep Tensor Neural Network With Applications to Large Vocabulary Speech Recognition
Dong Yu, Senior Member, IEEE, LiDeng, Fellow, IEEE, and Frank Seide, Member, IEEE (2013)](https://goo.gl/b8vwST)




## 1. 要約／背景
* 論文(Context-dependent pre-trained deep neural networks for large-vocabulary speech recognition)で提唱したモデルを発展させたもの。
* DNNのモデルで、テンソル空間を導入した。入力ベクトルを、2つのサブ空間に投射する。空間の間で相互作用を起こし、次の層へより抽出された特徴を送り出す。



## 2. 骨子の理論

![151207224233_1.JPG](https://qiita-image-store.s3.amazonaws.com/0/127228/c7181026-b868-087c-904d-abcd98f9c86d.jpeg)

これは隠れ層の2空間化(DP = Double Projection)の概略図である。DPは、各層で実行可能である。
(b)のパターンは、2投射空間それぞれから出力層へ引き渡され、出力層uは、テンソルになる。
(c)のパターンでは、2投射空間からの出力がクロネッカー積で統合され、次の入力層に引き渡される。(c)のパターンのほうが、BPの計算が容易である。

音声認識の場合、1つの空間に「音声検知」、もうひとつに「音波スペクトルのパターン」といった使い分けができる。

下層の空間の性質により、出力と次の入力の計算形式が決まる (下表)。

![151207224233_2.JPG](https://qiita-image-store.s3.amazonaws.com/0/127228/c68905b5-465c-3ed9-ad96-805e886958a4.jpeg)


クラス分類の場合、例に違わず交差エントロピー誤差関数の極値を求めるアルゴリズムで評価される。

```math
\bar{D} = \frac{1}{N}\sum_{x}D(x) = \frac{1}{N}\sum_{x}\sum_{y}\bar{p}(y|x)\log p(y|x)
```

差異は、パラメータの極値を求めるステップにある。
例として、l+1層からl層へのBPの式を挙げる。
第二空間に、第一空間固有の行列 $I(k1)$ を掛け合わせる(逆も同様)。

```math
\frac{\partial (v^{l+1})^T}{\partial h_1^{l}} = \frac{ \partial {\large(}{\large(}h_2^{l}\otimes I_{K_1^l}{\large)}h_1^{l}{\large)}^T} {\partial h_1^{l}} = (h_2^{l})^T \otimes I_{K_1^{l}} \\
\frac{\partial (v^{l+1})^T}{\partial h_2^{l}} = \frac{ \partial {\large(}{\large(}I_{K_2^l}\otimes h_1^{l}{\large)}h_2^{l}{\large)}^{T}} 
{\partial h_2^{l}} = I_{K_2^{l}} \otimes (h_1^{l})^T

```


## 3. モデル適用例
SWB-30hrタスクと呼ばれる音声データのテストセットで音声認識テストを行った。(下表は結果)
前モデルのCD-DNN-HMMの誤差率が28.3％だったのに対し、2重投射のケースでは、27％まで改善した。
(最も複雑なモデルは、2000ユニットの隠れ層が4層、96X96の投射層が1層のモデルである。)

![151207224233_6.JPG](https://qiita-image-store.s3.amazonaws.com/0/127228/ef345715-6c1b-bf2c-4cb7-42732a781ab9.jpeg)
ゲーム開発をWebViewからUnityに乗り換えて、苦労したこと、良かったこと

こんにちは。[CYBIRDエンジニア Advent Calendar 2017](https://qiita.com/advent-calendar/2017/cybird) 22日目の@gucchonです。新卒入社5年目のエンジニアです。
21日目は[@kenchang100kg](https://qiita.com/kenchang100kg)さんの「[2017年の振り返り(インフラ)](https://qiita.com/kenchang100kg/items/a798aad8ceec27f5afb2)」でした。振り返ってみれば、本当に大きな変化があった1年だったなぁ…としみじみしますね。


# 本日の内容

弊社の恋愛ゲームアプリのクライアントサイドは、1年前までWebViewアプリとしての開発が主でした。しかし、社内外の諸々の事情を鑑みて、今年からは、Unityでのゲーム開発にチャレンジしています。私にとっても、開発チームにとっても、慣れないUnityでの開発は大きなチャレンジでしたが、なんとか無事に1タイトルリリースすることができ、今後より良いプロダクトへと発展させていくための土台作りができたのではと手応えを感じています。

ということで今回は、これまでWebView開発をしていた我々が、Unity開発に乗り換えてみて、苦労したことや、良かったことなどをまとめてみようと思います。

# 苦労したこと

大きくは3つあります。どれも新規タイトルの開発中に直面した問題でした。

## 1. 実装の自由度が高い

WebView時代が低かったのかというとそんなことはないのですが、Unityでの開発ノウハウのない状態で実装が始まったので、人によって各機能の実装方法がバラバラになってしまっていました。

例えば、Scene内のHieraruchyのGameObjectの構成とか。コンポーネントの掴み方なんかも、PrefabをInstantiateしたあとGetComponentをしたり、SerializeFieldを指定した変数にアサインしたり、Find系でHieraruchy内を探したり(これは検索範囲が広い場合はNG)と、色々な方法が取られていました。初期の頃は特に、そういった細々した実装方法の方針を決めていなかったので、開発チーム内に混乱を生んでしまっていました。

なので、Unityでチーム開発するときは、実装方針についてチーム内で議論して、しっかり決めておいた方が良いと思いました。我々の場合は、1つの機能を作りきって、全員でレビューをして、認識を合わせる...ということを実施しました。要はお手本となるようなScene、Prefab、Script一式を用意した感じです。

## 2. レビューに手間がかかる

弊社では、WebView時代からGithubを使ったバージョン管理をしていて、実装時のコードレビューもGithubのPull Requestで行うのが通例となっています。Unityの開発チームでもPull Requestでのレビューを行っていますが、.unityとか.prefabといったUnity独自のファイルは、コードの差分を見たところで、「何が変更されているのか」、「正しく仕様を満たせているのか」といったことを判断できません。WebView時代ならコードレビューで十分判断できましたし、差分を見ただけで、実装者が変更した内容の意図を汲み取ることもできます。

そのため、少し手間はかかりますが、.unityとか.prefabの変更があれば、実際にUnityで変更したSceneを開いたり、実行したりして、レビューするようにしています。

## 3. コンフリクトを解消できない

これもGitに絡んだ話ですが、.unityとか.prefabファイルはコンフリクトしたらほぼ解消できないので、細心の注意を払う必要があります。特にチーム規模が大人数になればなるほど、危険性が高まりますね。新規開発プロジェクトの後半になると、色んな人が色んな部分のバグ修正をあっちでもこっちでもやり出すので、より危ないです。

我々の場合はもう「運用でカバー」といった感じで、Scene単位で管理表を作って、作業着手するときに「このScene触ってます」というのを記載してもらっていました。あとは、メンバーの役割も別けていたので、コンフリクトが発生しない運用ができていました。

一応、UnityYAMLMergeというツールがあるようですが、今のところ「運用でカバー」で安定していて、困ってはいないので試したことはないです。まぁ、WebViewだろうがUnityだろうがコンフリクト起こさないに越したことはないですね。

# 良かったこと

こちらも大きく3つです。

## 1. 開発環境の構築が楽

WebView時代はPCでの開発環境の構築にそれなりに手間がかかりました。基本的にはコマンドを手順通りに実行していけばOKなのですが、ハマってしまう頻度もそこそこ高かったように思います。特に非エンジニアに簡単に提供できるようなものではなく、それなりに知識がないと扱いづらい環境になってしまっていたと思います。

その点Unityは、インストールしてプロジェクトを開けばすぐにゲームを実行できるので、開発や確認までの敷居が圧倒的に下がったと感じます。

## 2. 非エンジニアでも実装作業に参加できる

最も大きな利点がこれだと思っています。前述したように、環境構築や実行が楽になったことにも起因していますが、流石ゲームエンジンだけあって、非エンジニアでもある程度容易に扱えるようになっているので、開発フローの改善には素晴らしい効果があったように思います。デザイナーがそのままゲーム画面のレイアウトやアニメーションを実装できるようになったことは、かなりの生産性UPにつながっています。

おかげで、エンジニアは機能実装に、デザイナーはデザイン作業にそれぞれ集中できるようになりました。

## 3. 表現の幅が広がった

WebGLを活用すれば、WebViewでもリッチな表現を実現できますが、端末環境、開発環境の現状から、使いこなすのはまだ少しハードルが高いのかなと感じていました。Unityの場合は、アニメーションやパーティクルエフェクトなどを手軽に実装でき、Scriptからの制御も容易にできます。

また、前述の通り、デザイナーがUnity上で実装を行うことで、クオリティUPに集中できることも、表現力を上げれられるようになった一因だと感じます。

# 最後に

今回は、WebView開発からUnity開発に乗り換えてみて、苦労したことと良かったことをざっくりとまとめてみました。

結果としては、メリットの方が大きく、開発チームにとっても、ユーザにとっても良い選択だったのではないかと思っています。特に生産性UPという部分に関しては、想像以上の成果があったように思います。

とはいえ、まだ熟練しているとは言い難いので、今後も精進していきたいところです。

さて、[CYBIRDエンジニア Advent Calendar 2017](http://qiita.com/advent-calendar/2017/cybird)。明日、23日目は[@ntrv](https://qiita.com/ntrv)さんの「GoでZabbixを爆速にしたかった」です。どうぞお楽しみに！
[WordPressテーマ] HTMLからテキスト、テキストからHTMLに変換する

WordPressの関数で取得したHTMLからテキストだけ取り出したいことや、その逆をしたい時があったので関数をメモしておく。

### テキスト -> HTML

`wpautop()`という関数を使う。

[関数リファレンス/wpautop - WordPress Codex 日本語版](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wpautop)

以下は使った時のコード

```php
echo wpautop(get_option('original_theme_options'));
```

テーマのフッターでテーマカスタマイザによって設定した値を表示する時に使用した。

### HTML -> テキスト

`wp_strip_all_tags()`という関数を使う。

[関数リファレンス/wp strip all tags - WordPress Codex 日本語版](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_strip_all_tags)

以下は使った時のコード

```php
function get_child_list(){

  // クエリの組み立て
  $my_wp_query = new WP_Query();
  $all_wp_pages = $my_wp_query->query(array(
    'post_type' => 'page',
    'nopaging'  => 'false'
  ));

  //　現在ページの子ページを取得
  $child_pages = get_page_children( get_the_ID(), $all_wp_pages );

  // 子ページが存在しないとき
  if(count($child_pages)<1){
    return;
  }

  foreach($child_pages as $child_page){

    // 子ページの情報を取得
    $child_page_id = $child_page->ID;
    $child_page_data = get_post($child_page_id);
    $child_page_raw_content = $child_page_data->post_content;
    $child_page_url = $child_page_data->guid;

    // HTMLを整形(　HTMLタグを削除して、110文字を切り出す
    $child_page_content = mb_substr(wp_strip_all_tags($child_page_raw_content, true), 0, 55);
  }
}
```

子ページのページのリストを取得するコード。`foreach`で出力をすれば各情報を出力することが出来る。


---
Copyright (c) 2017 Tomoyuki KOYAMA
Released under the MIT license
http://opensource.org/licenses/mit-license.php
PSoC 6 のデュアルコアでＬチカ (1)

これは、[PSoC Advent Calendar 2017]の1日目に突っ込まれた記事です。

##CPUが二つ入った[PSoC 6]
さきごろ発表された[PSoC 6]には、**Cortex-M4**と**Cortec-M0+**の二つのCPUが搭載されています。この記事では、二つのCPUを駆使したプログラムを使い、Ｌチカを行います。

##CPUサブシステムの構成
[PSoC 6]には、CPUとCPUに近いモジュールから構成されるCPUサブシステムと呼ばれるブロックがあります。

![GS003375.png](https://qiita-image-store.s3.amazonaws.com/0/224737/d96dfbab-f970-d436-70a7-ad3523f18be1.png)

二つのCPUコアは、FlashやRAMと共に単一のバスに接続されています。このため、メモリとすべての周辺モジュールは、どちらのCPUからも平等にアクセス可能です。なんと公平なんでしょう。
反面、すべてのリソースをユーザ側のソフトウェアで割り振る必要があるので、それなりのソフトウェア技量が必要になってしまいます。

##ハードウェアは[CY8CKIT-062-BLE]
ここで使用されるハードウェアは、[PSoC&reg; 6 BLE Pioneer Kit CY8CKIT-062-BLE][CY8CKIT-062-BLE]です。

![GS003376.png](https://qiita-image-store.s3.amazonaws.com/0/224737/f3e50834-a836-99c3-eb7a-7a56c75f3578.png)

この評価ボード上のLEDを点滅（Ｌチカ）させます。

##プロジェクトを作ります。
すでに、ソフトウェアでＬチカするプロジェクトの作り方とプログラムの方法は、[PSoC 6 Pioneer Kit で、Lチカしてみる (1)](http://yamagoya.hatenablog.jp/entry/2017/12/18/010000)で紹介されています。そこで、この記事では、ソフトウェアのみについて言及します。

最初は、**Cortex-M0+**で実行されるプログラムです。

```c:main_cm0p.c
#include "project.h"

int main(void)
{
    __enable_irq(); /* 全体の割り込みを許可する */
    /* Cortex-M4 を叩き起こして CY_CORTEX_M4_APPL_ADDR から実行させる。 */
    Cy_SysEnableCM4(CY_CORTEX_M4_APPL_ADDR); 

    for(;;)
    {
        /* GPIO 出力をクリア (Low) する。 */
        Cy_GPIO_Clr(Pin_LEDR_PORT, Pin_LEDR_NUM);
        /* 1000m秒待つ */
        CyDelay(1000);
    }
}
```

[PSoC 6]では、最初に**Cortex-M0+**が立ち上がります。そして`Cy_SysEnableCM4(CY_CORTEX_M4_APPL_ADDR);`を実行することで**Cortex-M4**での実行を開始します。

その後、LEDが接続されているGPIO出力を1000m秒ごとにLowに設定します。普通のＬチカでしたら、LowとHighを交互に出力するのですが、このプログラムでは、Lowのみ出力します。では、Highを出力するのは誰かというと、**Cortex-M0+**に叩き起こされた**Cortex-M4**が実行する以下のプログラムです。

```c:main_cm4.c
#include "project.h"

int main(void)
{
    __enable_irq(); /* 全体の割り込みを許可する */

    /* 500m秒待つ */
    CyDelay(500);

    for(;;)
    {
        /* GPIO 出力をセット (High) する。 */
        Cy_GPIO_Set(Pin_LEDR_PORT, Pin_LEDR_NUM);
        /* 1000m秒待つ */
        CyDelay(1000);
    }
}
```

このプログラムの無限ループ部分では、1000m秒ごとにGPIO出力をHighに設定しています。Highにするタイミングは、無限ループ直前の`CyDelay(500);`で作り出しています。これにより**Cortex-M0+**がGPIOをLowにしてから**おおむね**500m秒後に**Cortex-M4**がHighにするため、50%デューティーのＬチカが実現できます。まさに、二つのCPUによる共同作業というわけです。

##問題点
このシステムでは、**Cortex-M0+**と**Cortex-M4**が、自分勝手なタイミングでGPIOをHigh/Lowしています。タイミングを作っているのはソフトウェアによる遅延なので、もしかしたら次第にずれていってしまうかもしれません。
これらのタイミングがずれないようにするには、CPUの間で通信を行い同期をとる必要があります。

##関連文献
[AN215656 – PSoC 6 MCU Dual-Core CPU System Design][AN215656]

[PSoC Advent Calendar 2017]:https://qiita.com/advent-calendar/2017/psoc
[PSoC 6]:http://www.cypress.com/psoc6
[CY8CKIT-062-BLE]:http://www.cypress.com/cy8ckit-062-ble
[AN215656]:https://www.cypress.com/an215656
Excel 2016 > グラフが縮退状態になる | 拡大しても横棒と縦棒数本だけになる > 対処:しばらく待つ

```txt:動作環境
Windows 8.1 Pro (64bit)
Excel 2016
```

### 症状

Excel 2016をインストール直後、.xlsxファイルを開くと下記のような状況になった。

- グラフのシート内でグラフが縮退状態
    - 拡大率10%
    - グラフの上下左右の白丸マーカーが一点に縮退した状態
        - degenerated
    - すべてのグラフシートで発生
- 縮小したグラフを拡大した場合
    - 横線と縦線だけのグラフになる

### 対策

10分程度待つ。

同じ症状の例がないか検索していたが、見つからなかった(この間は10分程度)。
もう一度症状を確認しようとしたところ、上記の状況は発生しなくなっていた。

- グラフのシート内でグラフが通常の大きさで表示
    - 拡大率 90%
    - すべてのグラフシートで正常
- 拡大縮小処理でも正常にグラフを拡大縮小できる

インストール直後で何かの処理が動いたままになっていたのだろうか？
Project Euler Q50 【連続する素数の和】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
素数$41$は$6$つの連続する素数の和として表せる:
$41 = 2 + 3 + 5 + 7 + 11 + 13.$

$100$未満の素数を連続する素数の和で表したときにこれが最長になる.

同様に, 連続する素数の和で$1000$未満の素数を表したときに最長になるのは$953$で$21$項を持つ.

$100$万未満の素数を連続する素数の和で表したときに最長になるのはどの素数か?

## 解答

```bash
seq 1000000 |
factor |
awk 'NF==2{printf $2" "}' |
awk '{for(i=1;i<=NF-1;i++){s=0;c=0;for(j=i+1;j<=NF;j++){if(1000000<=s+$j){break}else{s+=$j;c+=1}};print s,c}}' |
awk '21<$2' |
sort -k2,2nr |
awk '$0=$1' |
factor |
awk 'NF==2{print $2}' |
head -1
997651
```

まだ無駄な処理をしてる感は否めない。。

## 答え合わせ
こちらのサイト様と一致していればOKとした。
http://kingyojima.net/pje/050.html
サーバー {9BA05972-F6A8-11CF-A442-00A0C90A8F39} は、必要なタイムアウト期間内に DCOM に登録しませんでした。

は
https://social.technet.microsoft.com/Forums/windowsserver/ja-JP/2fcaab26-2af8-4b63-9c52-ac0f1a513564/dcom?forum=winserver8

実害が無ければ無視して問題ないことが記載されています。

かな？？？

昨日WindowsUpdate当てて再起動時に
エラーが多発したのでメモ失礼しました。
【論文シリーズ】階層的深層学習

## 原文
[階層的深層モデルによる学習 (Learning with Hierarchical-Deep Models)
Ruslan Salakhutdinov, Joshua B. Tenenbaum, and Antonio Torralba, Member, IEEE (2013)](http://dspace.mit.edu/openaccess-disseminate/1721.1/90947)


## 1. 要約／背景
* 階層ベイズモデルをベースに、階層ディリクレモデルとDBMを組み合わせた学習器を開発した。
* 画像認識、人間の動きの検知に応用できる。

## 2. 骨子の理論
(1)DBM
3層積み上げた時のエネルギー関数は次のようになる。

```math
E({\bf v}, {\bf h}; {\bf \psi}) = - \sum_{ij}W^{(1)}_{ij}v_ih^{(1)}_j - \sum_{jl}W^{(2)}_{jl}h^{(1)}_jh^{(2)}_l - \sum_{lk}W^{(3)}_{lk}h^{(2)}_lh^{(3)}_k
```
RBM同様、可視変数および隠れ変数は、エネルギー関数に基いたボルツマン分布に従う。

```math
P({\bf v};{\bf \psi}) = \frac{1}{Z(\psi)}\sum_{{\bf h}}\exp(-E({\bf v}, {\bf h}^{(1)},{\bf h}^{(2)},{\bf h}^{(3)};\psi))
```

対数尤度の勾配は、次の式に従う。

```math
\frac{\partial \log P({\bf v};\psi)}{\partial{\bf W}^{(1)}} = E_{P_{data}}\big[{\bf v} \, ^t{\bf h}^{(1)}\big] - E_{P_{model}}\big[{\bf v} \, ^t{\bf h}^{(1)}\big] \\
\frac{\partial \log P({\bf v};\psi)}{\partial{\bf W}^{(2)}} = E_{P_{data}}\big[{\bf h}^{(1)} \, ^t{\bf h}^{(2)}\big] - E_{P_{model}}\big[{\bf h}^{(1)} \, ^t{\bf h}^{(2)}\big] \\
\frac{\partial \log P({\bf v};\psi)}{\partial{\bf W}^{(3)}} = E_{P_{data}}\big[{\bf h}^{(2)} \, ^t{\bf h}^{(3)}\big] - E_{P_{model}}\big[{\bf h}^{(2)} \, ^t{\bf h}^{(3)}\big]
```

(2)分布の近似
任意の近似分布を$Q({\bf h}|{\bf v};{\bf \mu})$とする。
隠れ変数の最適な事後分布を、変分下限から次のように評価する。

```math
\begin{align}
\log P({\bf v};\psi) &\geq \sum_{{\bf h}}Q({\bf h}|{\bf v};\mu)\log P({\bf v},{\bf h};\psi) + \mathcal{H}(Q) \\
& \geq \log P({\bf v};\psi) - {\rm KL}(Q({\bf h}|{\bf v};\mu)||P({\bf h}|{\bf v};\psi))
\end{align}
```

事後分布は平均場近似する。

```math
Q^{MF}({\bf h}|{\bf v};\mu) = \prod_{j=1}^{F_1}\prod_{l=1}^{F_2}\prod_{k=1}^{F_3}q(h_j^{(1)}|{\bf v})q(h_l^{(2)}|{\bf v})q(h_k^{(3)}|{\bf v})
```

(3)MCMCによるサンプリング
(4)DBMの積層は、貪欲法により進行する。

一方で、最高層h3に対する事前分布は次のように表される；

```math
P({\bf v},{\bf h}^{(1)},{\bf h}^{(2)}|{\bf h}^{(3)}) = \frac{1}{{\mathcal Z}(\psi, {\bf h}^{(3)})}\exp\big( \sum_{ij}W_{ij}^{(1)}v_ih_j^{(1)} + \\
\sum_{jl}W_{jl}^{(2)}h_j^{(1)}h_l^{(2)} + \sum_{lk}W_{lk}^{(3)}h_l^{(2)}h_k^{(3)} \big)
```


ここで最高層を「トピックモデル」で表現する。
「トピック→ドキュメント」「単語→トピック」の分布は、ディリクレ分布に従う。

```math
{\bf \theta}_n | {\bf \pi} \sim {\rm Dir}(\alpha{\bf \pi}), {\rm for \: each \: document} \: n = 1, ..., N, \\
{\bf \phi}_t | {\bf \tau} \sim {\rm Dir}(\beta{\bf \tau}), {\rm for \: each \: topic} \: t = 1, ..., T, \\ 
x_{in} | {\bf \theta_n} \sim {\rm Mult}(1,{\bf \theta_n}), {\rm for \: each \: topic} \: i = 1, ..., M, \\ 
h_{in}^{(3)} | x_{in}, {\bf \phi}_{x_{in}} \sim {\rm Mult}(1,{\bf \phi}_{x_{in}})
```

## 3. モデル適用例
CIFARの画像データセットによるテストでは、最高のパフォーマンスを示した。
(数値は、Area Under the ROCで、数値が高いほど識別能力が高い。)

![151207223955_8.JPG](https://qiita-image-store.s3.amazonaws.com/0/127228/93dd7101-fed9-37dc-851f-5afd96fe0cfe.jpeg)
COM+ イベント システムはサブスクリプション {51648743-8EE1-46A8-9D1F-7F300F12D9DA}-{00000000-0000-0000-0000-000000000000}-{00000000-0000-0000-0000-000000000000} へのサブスクライバーのマーシャリングをできませんでした。  HRESULT は 80070005 でした。

というエラーが出てきて
グーグルで調査していた際に見つけた
http://www.nekoprint.mobi/cgi-bin/nekonekodiary/archives/56.html
　--------
確認すること："管理ツール" → "サービス" で以下の項目が開始されているか？停止していたら開始させる。

COM+ System Application
System Event Notification
　----------------
で
COM+ System Application
が止まっていたから実行させましたっ
CentOS7へ(CentOS6と同じバージョンの)gcc4.4.7をインストール

* compat-gcc-44 
* compat-gcc-44-c++ 

を使えば良いです。

## 以下古い記事

CentOS6やdebian9だとビルドできるがCentOS7だとビルドできないソースがあった。

| ディストリ | gccバージョン |
|:--|:--|
| debian 9 | 6.3 |
| centos 6 | [4.4.7](http://ftp.iij.ad.jp/pub/gnu/gcc/gcc-4.4.7/gcc-4.4.7.tar.bz2) |
| centos 7 | 4.8.5 |
| gcc4系の最新 | [4.9.4](http://ftp.iij.ad.jp/pub/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.bz2) |

## 準備

```sh:ビルドに必要なパッケージ
yum install -y \
  libmpc-devel mpfr-devel gmp-devel
```

## ビルド

* 参考: [linux - "fatal error: gnu/stubs-32.h: No such file or directory" but stubs-64.h is present - Stack Overflow](https://stackoverflow.com/questions/33059187/fatal-error-gnu-stubs-32-h-no-such-file-or-directory-but-stubs-64-h-is-prese)

```sh:x86_64用にビルド
cd gcc-4.4.7
# --disable-multilib 指定をしないとglibc-devel.i686もインストールしておく必要がある。
./configure --build=x86_64-linux-gnu --disable-multilib
make -j 4

make install
```

```sh:
# /usr/local/bin/gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ./configure --build=x86_64-linux-gnu --disable-multilib
Thread model: posix
gcc version 4.4.7 (GCC) 
```
AWS UbuntuへPythonをコンパイルして導入する手順(virtualenv)

# 概要
- AWS EC2のAWS提供 Ubuntu AMIへ現時点で最新安定版のPython3.6.3を導入します
    - ターゲットイメージ:`Ubuntu Server 16.04 LTS (HVM), SSD Volume Type`
- パッケージではなく、ソースコンパイルします
- 初期状態でPython2系、Python3系も導入済みのため、virtualenvで環境分離します

# ダウンロードページ
- [Python.org](https://www.python.org/)のDownloadあたりから探します
- 今回は下記を使用しました
    - https://www.python.org/downloads/release/python-363/

# ディレクトリ
すべてホーム配下の`local`ディレクトリへ配置します。今回は下記のようにしてみました。

| Path | 内容 |
|------|-----|
| ~/local/src/Python-3.6.3 | ダウンロードしたソースを展開 |
| ~/local/lib/Python-3.6.3 | ビルドしたモジュール出力先 |
| ~/local/p363/ | virtualenvが指す場所 |

# 手順
- コマンドを記述します
- コマンドの実行結果を表現する場合はプロンプト付きでコマンドを記述します

## EC2インスタンスを起動します
- Ubuntu Server 16.04 LTS
    - ターゲットイメージ:`Ubuntu Server 16.04 LTS (HVM), SSD Volume Type`

## 必要パッケージインストール

```bash
sudo apt update
sudo apt upgrade -y
sudo apt install build-essential zlib1g-dev libssl-dev libffi-dev libsqlite3-dev libreadline-dev libbz2-dev libgdbm-dev liblz-dev tk-dev -y
```

## ソースダウンロードと展開

```bash
mkdir -p ~/local/src
cd ~/local/src

wget -qO- https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz | tar zxf -
```

## コンパイル準備とコンパイルとインストール

```bash
cd Python-3.6.3/
./configure --enable-optimizations --prefix=$HOME/local/lib/Python-3.6.3
make
make install
```

## virtualenvによる配置

```bash
~/local/lib/Python-3.6.3/bin/pip3 install virtualenv
~/local/lib/Python-3.6.3/bin/virtualenv --python ~/local/lib/Python-3.6.3/bin/python3 ~/local/p363
```

# 確認
activateを実行(source)することでpythonが指す場所が変化、プロンプトにディレクトリ(p363)が表示されます
（戻す時はdeactivate）

```
$ source ~/local/p363/bin/activate
(p363) $ python --version
Python 3.6.3
```


# ログインスクリプトへ追加
```bash
echo 'source ~/local/p363/bin/activate' >> ~/.profile
```
Docker で nodemon を使って、サーバー再起動を自動化する


方法としては、nodemon を使って、volumes でコンテナー内のファイルを編集できるようにして、index.js の変更を監視してもらうようにした。

``` docker-compose.yml
version: '2'
services:
  IMAGE_NAME:
    build: .
    restart: on-failure
    environment:
      - NODE_ENV
    tty: true
    stdin_open: true
    depends_on:
    volumes:
      - ./package.json:/usr/src/app/package.json
      - ./index.js:/usr/src/app/index.js

```


package.json の bin を設定することで、コマンドを設定できるので、global インストールさせずに nodemon コマンドを叩いている。

Dockerfile ファイルの最後の行で定義した `yarn start` コマンドが `nodemon index.js` にあたるようになるので、dockerを `docker-compose up` で立ち上げたときに、監視されて自動で再起動される。

``` Dockerfile
FROM node:8
MAINTAINER Ryosuke Miyamoto <miyamoto@ndinc.jp>

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY package.json /usr/src/app/

RUN yarn install

COPY . /usr/src/app/

EXPOSE 3000

CMD ["yarn", "start"]

```




``` package.json
{
  "name": "bot",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": ""
  },
  "scripts": {
    "start": "nodemon index.js",
  },
  "keywords": [
  ],
  "author": "yahsan2",
  "license": "MIT",
  "bin": {
    "nodemon": "node_modules/nodemon/bin/nodemon.js"
  },
  "dependencies": {
    "nodemon": "^1.13.3",
  },
  "devDependencies": {
  }
}


```

※ 上記ファイルのコードは、必要な部分を抜粋なので、動作確認していない。
Google Apps ScriptでCSVファイルをGoogleスプレッドシートにインポートする

#はじめに

CSVの形式でデータをエクスポートすることが多いので、そのデータを整理しやすくするためにスプレッドシートにインポートしてしまおう！ということで調べてみました。

同じような記事はいくつかあるのですが、自分なりにまとめようと思います。

##Googleアカウント

タイトル通りGoogleAppsScriptを使うのでGoogleのアカウントが必要です。
ない場合はあらかじめ作っておきましょう。

また、今回はGoogleDrive内にあるCSVファイルをスプレッドシートにインポートするので
GoogleDriveとGoogleスプレッドシートを使えるようにしておきましょう。

#事前準備
まずは、書き込む先のスプレッドシートを用意します。
新しいスプレッドシートを作成し任意のタイトルをつけてGoogleDriveに保存します。

このときGoogleDrive内にフォルダも作ってしまいましょう。

次に、スプレッドーシートに書き込むCSVファイルをエクセルで適当に作りましょう。
この作ったCSVファイルはGoogleDrive内に作成したフォルダの中にアップロードします。

##コード
ここまでの準備が完了したら、コードを書いていきます。

スプレッドシートを開き、ツールバー内にあるツールからスクリプトエディタを開きます。
するとコードを書き込めるエディタが出てきます。
そこに以下のようなコードを書き込みます。

```ruby:csv_import_1.gs
//書き込む対象のSpread Sheetを定義
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();

function import() {
  
  // 対象のCSVファイルが置かれているフォルダ名、ファイル名を定義
  var folderName = "テスト";
  var fileName = "test.csv";
  var folders = DriveApp.getFoldersByName(folderName);
  
  //フォルダとファイルの検索
  while (folders.hasNext()) {
    var folder = folders.next();
    if (folder.getName() == folderName) {
      var files = DriveApp.getFilesByName(fileName);
      while (files.hasNext()) {
        var file = files.next();
        if (file.getName() == fileName) {
          
          //設定しないでShift_JISのままだと文字化けする
          var data = file.getBlob().getDataAsString("Shift_JIS"); 
          
          var csv = Utilities.parseCsv(data);
          
          //セルA1からCSVの内容を書き込んでいく
          sh.getRange(1,1,csv.length,csv[0].length).setValues(csv);
          return;
        }
      }
    }
  }
}
```

GoogleDrive内にあるCSVを探して対象のスプレッドシートに書き込むだけなのですが
対象のスプレッドシートからエディタを起動したので、定義が簡単になっています。

コメントに書いていないコードの詳細は各自調べてもらうといくらでも出てくると思います。

##実行
エディタの上のほうにあるデバッグボタンでデバッグすることができその左のボタンで実行することができます。
実行ボタンを押したあとスプレッドシートを見に行くと、CSVファイルの内容がそのまま書き込まれていると思います。

##最後に
今回はGoogleDrive内にあるCSVファイルをGoogleDrive内のスプレッドシートに書き込んでみましたが、[ローカルの中にあるCSVファイルをスプレッドシートに書き込む](https://qiita.com/ms32/items/7e180c1c1d00fa8df647)こともできるみたいです。

以上でこの記事を終わりにしたいと思います。
PMという用語の使い方は慎重に

Product ManagerをPMと言う人がいますが、これは絶対にやめたいです。
PMはProject Managerです。
Product ManagerはPdMと表記しましょう。
仕事の中味が違うのに、一緒くたに扱われている気がします。
製品を期日までに品質良く仕上げるという意味では似たところがありますが、商品力の向上に知恵を絞るのがPdMの主業務です。
VSCode "情報 code is already running" と出て止められない場合の対処。

いちいちVSCode自体を再起動していたのでメモ。

## 環境
Windows7

# 症状

`Run Code`（ショートカットキー`Ctrl+B`）をすると
”情報 code is already running”と出る。
Ctrl+cを押しても止まらない。

## 状況
VSCodeでショートカットキー`Ctrl+B`を押すと`Run Code`という命令が実行される、
Rubyの場合そのスクリプトファイルを実行してくれる。
（他のソースコードも工夫すればビルドして実行してくれるかも）

しかし、プログラム中に、
`a = gets.to_i`
などの標準入力待ちなどがあると
”code is already running”と出てずっと待機状態のまま。
Ctrl+cを押しても止まらない。



# 止める方法
## 1. 出力のウィンドウを表示させる
メニューからは
表示＞総合ターミナル＞出力
ショートカットキーは
`Ctrl+Shift+U`

## 2. 出力のウィンドウ範囲内で右クリック
右クリック＞Stop Code Runを選択するか、
ショートカットキー`Alt+Ctrl+M`で止める。



# 備考
AtCoderを見ていて、
[A: はじめてのあっとこーだー（Welcome to AtCoder） - practice contest | AtCoder](https://practice.contest.atcoder.jp/tasks/practice_1)
この、チュートリアルの問題をVSCodeで実行しようとすると
標準入力が必要となる。

`Run Code`でRubyスクリプトは実行できるが、標準入力は受け付けていないので（方法はあるかもしれないが、知らないので）、ターミナル画面から`ruby ファイル名.rb`と実行する必要がある。

もし、ここで`Run Code`（ショートカットキー`Ctrl+B`）をすると、
"情報 code is already running"
と出て止められない状況に陥る。

#### 実際に実行したコード

```ruby:run_code_practice_1.rb
a = gets.to_i
b,c = gets.chomp.split(" ").map(&:to_i)
s = gets.chomp
puts ("#{a+b+c} #{s}")
```

## おまけ
（使いやすくするため自分専用のキーバインド設定）
`Alt+Ctrl+M`のショートカットキーを
`Ctrl+Shift+b`に変更

ファイル＞基本設定＞キーボードショートカット
キーバインドの検索
`Alt+Ctrl+M`を`Ctrl+Shift+b`に変える。
babel-preset-es2015がduprecateと言われたのでbabel_preset_envを使ってみたメモ

こんなwarnが出ていたので推奨通りにbabel_preset_envを使ってみました（コンソールでは文字化けしていましたが中々煽る感じの絵文字が含まれていたんですね）

```
npm WARN deprecated babel-preset-es2015@6.24.1: 🙌  Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!
```


# package.json 修正前
babel関係のpackageが5個あります。

その内`babel-plugin-root-import`はreactでcomponentをimportする際に絶対パスで書けるようにするためのものなので、恐らくbabel本体とは無関係のはず。


```json:package.json
{
  "private": true,
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.0.0",
    "babel-plugin-root-import": "^5.1.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "create-next-app": "^0.5.2",
    "css-loader": "^0.28.4",
    "isomorphic-unfetch": "^2.0.0",
    "material-ui": "^0.18.6",
    "next": "^2.4.7",
    "react-redux": "^5.0.5",
    "react-tap-event-plugin": "^2.0.1",
    "redux": "^3.7.2",
    "redux-act": "^1.3.0",
    "style-loader": "^0.18.2",
    "webpack": "^2.6.1",
    "webpack-dev-server": "^2.5.0"
  },
  "dependencies": {
    "react": "^15.6.1",
    "react-dom": "^15.6.1"
  }
}
```


# package.json修正後
当初の目的である`babel-preset-es2015`を含めた4つを削ることにしました。
一応起動は成功。

```json:package.json
{
  "private": true,
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "devDependencies": {
    "babel-plugin-root-import": "^5.1.0",
    "babel-preset-env": "^1.6.1",
    "create-next-app": "^0.5.2",
    "css-loader": "^0.28.4",
    "isomorphic-unfetch": "^2.0.0",
    "material-ui": "^0.18.6",
    "next": "^2.4.7",
    "react-redux": "^5.0.5",
    "react-tap-event-plugin": "^2.0.1",
    "redux": "^3.7.2",
    "redux-act": "^1.3.0",
    "style-loader": "^0.18.2",
    "webpack": "^2.6.1",
    "webpack-dev-server": "^2.5.0"
  },
  "dependencies": {
    "react": "^15.6.1",
    "react-dom": "^15.6.1"
  }
}
```


# まとめ
babelが何をやっているのか殆どわかっていませんしわかりたくもないのが本音です。。
parcelとか出てきたし、ますます混乱してきました。

* babel関係はbabel_preset_env入れておけば良さげ
pythonのversionを切り替える方法

##概要
python3.6を使いながらpython2.7を使いたくなったのでその方法

##環境
windows10 home
Ubuntu 16.04.2 LTS

##方法1-virtualenvを使う-

```
$ sudo apt-get update
$ sudo apt-get install python2.7
```
まずは入れたいversionのpythonをインストールする

```
$ pip install virtualenv
```

つぎに仮想環境を作るためにvirtualenvをインストールする

```
$ mkdir hogehoge
```

作りたい仮想環境の名前を決める

```
$ sudo virtualenv -p python2.7 hogehoge
```

virtualenvのパスを作成したディレクトリに設定する

```
$ source hogehoge/bin/activate
```

virtualenvをアクティブにする

```
$ python -V
```

pythonのバージョンを確認する

##方法2-pyenvを使う-

```
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```
pyenvをgit　cloneしてくる

```
$ echo '#pyenv' >> ~/.bashrc
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bashrc
```
pyenvを導入する

```
$ exec "$SHELL"
```
シェルを再起動させる

```
$ pyenv install -l
```

導入するバージョンのをリストアップする

```
$ pyenv install anaconda2-5.0.1
```

指定したバージョンを持ってくる(いまはanaconda2-5.0.1を指定した)

```
$ pyenv versions
```

導入されているバージョンの確認

```
$ pyenv global anaconda2-5.0.1
```

指定したバージョンをアクティブにする

```
$ python -V
```

pythonのバージョンを確認する



##結果
pythonのバージョンを切り替えることができた。
Rubyの日本語ドキュメントをDash.appで見る

最近Rubyを始めた人間として、このメソッッドは？とかこのモジュールは？という時に、Dashを愛用していて、Dash上でダウンロードしたドキュメントを使っていたが、自分の英語力だと解釈に時間がかかる・・・と思っていたら、日本語のdocsetを公開して頂いているサイトがあってありがたく利用できたのでメモ


↓にアクセスして、欲しいdocsetをクリックするだけ
するとDash.appを起動するかの確認が出て、OKすればダウンロード開始する

http://labocho.github.io/rubydoc-ja-docsets/


## 参考にしたサイト

http://penguinlab.jp/blog/post/2306
Alexaのスキル申請でリジェクトされちゃった理由 


## はじめに
ラッキーなことに、12月初旬に日本版Amazon Echoを購入することができました。
せっかくなので、早速をスキルつくって申請してみました！

実験的に結構無茶なものを申請したのですが、案の定、サクッとリジェクトされましたので、その理由を共有したいと思います。

（スキルの開発手順や申請手順については、他をあたって下さい）

## つくったもの
Alexa端末所有されてる方はご存知かと思いますが、スキルはスマホのAlexaアプリと連携し、"カード"と呼ばれる補足情報をスマホアプリ上に表示することができます。
（Alexaに話しかけた内容が見えてしまうので、家族など複数人で使用する場合はご注意を。）

この性質を利用して、子どもがEchoにクリスマスプレゼントで何が欲しいか話しかけると、サンタさんのAlexaアプリにカードを表示するようなスキルを考えました。

(例）
「アレクサ、クリスマスプレゼントで仮面ライダーのベルトが欲しい」と発話すると、以下のカードをスマホアプリに表示。
<img src="https://qiita-image-store.s3.amazonaws.com/0/64046/9f28a17f-860d-750b-2f0a-89e279617bb4.png" width=50%/>

>参考）スキルの応答にカードを追加する
https://developer.amazon.com/ja/docs/custom-skills/include-a-card-in-your-skills-response.html

## 申請
開発者ポータルから申請すると、受け付けた旨の英文のメールが届きました。
審査結果は７営業日以内に連絡するとのこと。ドキドキ。

## テスト開始
初期審査的なものが終わって、テストフェーズに入ったのこと。
５営業日以内にフィードバックがあるらしい。ふむふむ。

## 審査結果　〜リジェクト〜
数日かかるかと思って気長に構えてたのですが、単純なスキルだったためか、申請の翌日に結果が届きました。
結果はタイトル通りリジェクト。。。今度は丁寧な日本語のメールです。

以下、リジェクトされた理由の一部です。

### 呼び出し名が一般的すぎる
「クリスマスプレゼント」という呼び出し名にして、「クリスマスプレゼントで、○○が欲しい」のように、スキルであることを意識せずに使えることを狙ったのですが、それダメ〜でした。
スキルを使っていることに気づかないような呼び出し名はNGだそうです。

### 子供向けのAlexaスキルの禁止  
１３歳以下を対象にしてはいけないと、ポリシーに明記されています。（米国除く）

>Alexaスキルのポリシーのテスト
https://developer.amazon.com/ja/docs/custom-skills/policy-testing-for-an-alexa-skill.html

申請時のチェックシートでは子どもを対象にしていない、として申請しましたが、Alexaからの返答に子ども向けを示唆する文言が含まれていたため、NGとなりました。
しっかりテストされてますね。
自己申告で対象外にしておけば大丈夫、というものではないようです。

### スロットの内容をユーザーが発話する可能性が低い
あらゆる商品名を網羅するのは現実的ではないので、フリーワードをスロットとして認識するようにしたかったのですが、フリーワード用の```AMAZON.LITERAL```という型が英語のみ対応とのこと。
（日本語での良いやり方ご存じの方はご教示ください）

>Custom Interaction Model Reference　(英語ページ参照） https://developer.amazon.com/docs/custom-skills/custom-interaction-model-reference.html

とりあえず、数行のランダムな文字列をスロット値として登録したのですが、ユーザーが発話するとは思えないとのことで、NGでした。
サンプル発話含め、開発者ポータルで定義した内容もチェックされているようです。

補足) 2017/12/22 追記
Alexa Skill Kitのドキュメントをよく読むと、こんな文書がありました。
もしかすると、数件の正しい商品名を列挙しておけば大丈夫だったのかもしれません。（未検証）

>・スキルには合計で50,000個のカスタムスロット値を指定できます。これは対話モデルで使用するすべてのカスタムスロットの値の合計数です。この制限内に収めるためにスロット値の数を減らす必要がある場合は、使われる可能性が高い値を優先してください。
・カスタム値のリストにスキルで予測される必ずしもすべての値を含めない場合は、代表的な語数の代表的なカスタム値のセットを提供します。たとえば、1～4語の値が想定される場合、リストの値も1～4語のものを使用します。ただし、語数のバランスは使われる頻度に応じて変えるようにしてください。4語の値が10%しかない場合は、リスト内に含める4語の値も10%までにします。

引用元) カスタムスロットタイプの値に関する推奨事項
https://developer.amazon.com/ja/docs/custom-skills/best-practices-for-sample-utterances-and-custom-slot-type-values.html#h3_custom_slot_values

### エラーハンドリングが不十分
ユーザーが「ストップ」や「キャンセル」と言って停止した際、適切なメッセージを返さないといけません。漏れなく実装しましょう。

## おわりに
他にもストア掲載文言に関する指摘などもあり、しっかり審査されている印象です。
また、フィードバックには、どう発話したら問題があったかが明記されていたり、修正方法を教えていただいたりと、フォローも手厚いと感じました。
いずれの指摘も、下記チェックリストにしっかり従って作れば引っかからないものが多いので、企画段階からしっかり確認しておくことをオススメします。

## 参考
>Amazonアプリストア申請前チェックリスト
https://developer.amazon.com/ja/docs/app-submission/presubmission-checklist.html
入力チェックとかの話

# [PHP]簡単な入力チェック用のJSとかとか

## 目的：テキスト欄に入力された値を裏側で確認してみる


主な流れ  
1. 文字の入力  
2. フォーカスを外したら通信  
3. 裏側で入力内容の確認  
4. 照合結果を返す  

### 手順

**1 入力フォームの作成**  

```html
  <form id="edit_form" class="form-horizontal" name="form-regist" enctype="multipart/form-data" method="post" action="/edit" novalidate="novalidate">
    <div class="form-group">
      <div class="col-sm-9">
        <input type="text" class="form-control" id="test_input" placeholder="確認用" name="test" value="">
      </div>
    </div>
  </form>
```

（行の最後にJQueryが読み込めるようにしとこう。）

**2 javascriptを作成**  
ファイル名「test.js」を作成

```javascript
//照合のajax
$('#test_input').blur(function(){
  var hostUrl= '/edit/check';
  var test_text = $('#test_input').val();

  if(test_text == ''){
    return;
  }

  //まず入力可能文字列か調べる。
  var reg = new RegExp("^[0-9a-zA-Z-]+$");
  if (!reg.test(test_text)){
    swal("使用できない文字が入力されています。", "a~z,A~Z,0~9,-,_ のみ入力可能です。", "warning");
    $('#test_input').val("");
  }

  $.ajax({
    url: hostUrl,
    type:'POST',
    dataType: 'json',
    data : {test_text : test_text},
    timeout:10000,
  }).done(function(data) {
    console.log(data);
    if(data.count == 0) {
      //被りなければ何もしない
      return;
    }else{
      //inputの値消す
      swal("", "再度入力してください。", "warning");
      $('#test_input').val("");
    }
  }).fail(function(XMLHttpRequest, textStatus, errorThrown) {
    console.log(XMLHttpRequest);
    console.log(textStatus);
    console.log(errorThrown);
  })
});
```

**3 PHP側で他のデータ等と照合したいと時**  
*FuelPHP  

```php
<?php

/**
  * @package Api
  */
class Controller_Edit extends \Controller
{
  /**
    * @access  public
    * @return  status msg
    * 入力照合
    */
  public function action_check()
  {
    try {
      //コールバック用形式
      header('Content-type: application/json; charset=UTF-8');

      //javascriptからpostパラメータを取得
      $search_key = array(
          'text' => Input::post('test_text', ''),  //入力値
      );

      //DBとかと照合する、、、
      
      //戻り値
      echo json_encode(array(
        'status'  => 0,              //0:正常処理
        'msg'     => 'success',  		//メッセージ内容
      ));

      exit; //処理終了

    //例外処理
    } catch (\Exeption $e) {
      //エラーログ
      \Log::error( 'APIエラー:' . 'text:' . $search_key['text'] . $e->getMessage());
      //戻り値
      echo json_encode(array(
        'status'  => 2,               //異常終了
        'msg'     => 'fatal error ',  //メッセージ内容
      ));
        exit;   //処理終了
    }
  }

```

*これで入力チェックは完成です。この機能を使ってデータベースの値との照合とかにも使えると思います。*

以上
---
【CakePHP2】find検索 の conditions で否定演算子を使う場合

CakePHP2 で find の検索条件(conditions)を使用する場合、以下のように書くと思います。

```php
$query = $users->find('all', [
    'conditions' => [
        'country' => 'Japan',
    ],
]);
```

この条件を否定で書くには、

```php
$query = $users->find('all', [
    'conditions' => [
        'NOT' => [
            'country' => 'Japan',
        ],
    ],
]);
```

とすると思いますが、以下のようにも書けます。

```php
$query = $users->find('all', [
    'conditions' => [
        'country !=' => 'Japan',
    ],
]);
```

否定演算子の `!=` を使いますが、これは `<>` でも動きます。

DB的にはどちらを使ってもいいと思うのですが、[Cookbook](https://book.cakephp.org/2.0/ja/models/retrieving-your-data.html)には `!=` で書かれています。

また、CakePHP2 の Model.php にも `!=` が使われている箇所があります。

```php:Model.phpの_findNeighbors()
$query['conditions'][$field . ' !='] = $value;
```

```php:Model.phpのisUnique()
$fields[$this->alias . '.' . $this->primaryKey . ' !='] = $this->id;
```

プロジェクトのコーディング規約で決まっていない場合、 `!=` を使うのがよいと思います。
ゆるふぁい #2 現場より (2017年 12月 19日に実施)

これは [Delphi Advent Calendar 2017](https://qiita.com/advent-calendar/2017/delphi) の 20 日目の記事です。

2017 年 10 月から始めて、2017 年 12 月 19 日の実施で ３回目 ( 1回目は #0) です。
継続はチカラなりなので、これからもゆる～く続けていきます。

##主にどんなことやってるの？
主催者から参加者への問いかけの LT が最初にあります（一種の自己紹介タイム）
あとは、フリースタイルで井戸端会議のようにわいわいやっています。

##今回はどんなことやっていたんですか？
今回の最初の問いかけは、「if文ってどんな風に書いてますか？」です。

```delphi
if true then 
begin
  hogehoge();
end
else
begin
  hogehoge();
end;
```
な方が殆どでした。

その後は、Helperの話だったり、無名メソッドは便利だぞ的な話だったり、UIの話だったり、データベース関連だったり、最近のあれこれ的な話だったりを、ゆるーく井戸端会議的な感じで話してます。

今回は、初めて参加の方もいらっしゃって、主催者としては喜ばしい限りでした。

##次回はいつ？
次回は 2018 年 1 月 11 日 (木) 実施です！
鏡開きの日ですね。

ご興味ある方は、[こちら](https://yuru-phi.connpass.com/event/71298/)からどうぞ！
GLSLのレイマーチングで地形を描画する

GLSLのレイマーチングで地形を描画する方法です。

地形を描画するには、レイをちょっとずつ進めてレイの位置が地形の高さよりも低くなったら、そこをレイと地形の交点とします。

地形を生成するための関数は次のようになり、平面座標を入力として高さを出力します。
ここでは、異なる周波数のサイン波を複数重ねたもので地形を作っています。

```glsl
float terrain(in vec2 p) {
	p *= 0.2;
	float height = 0.0;
	float amp = 1.0;
	for (int i = 0; i < 10; i++) {
		height += amp * sin(p.x) * sin(p.y);
		amp *= 0.5;
		p *= 2.07;
	}
	return height * 5.0; // 適当な値で高さをスケール
}
```

レイを進めて行く処理は次のようになります。
ループ処理の中で、先ほどのterrain関数から高さを取得して、レイの位置と地形の距離を計算します。
もし、距離が一定以下になった場合は、交差したとみなしてループ処理を中断します。そうでない場合は、距離をもとにレイを進めます。
ここで注意しないといけないのは、距離はレイの進行方向と地形の距離ではなく、あくまでy軸方法との距離だということです。そのため、断崖絶壁のような高さが急激に変わる地形ではノイズが目立つようになると思います。
ここでは、１未満の値を距離にかけて慎重にレイを進めるようにしています。

```glsl

const float tmax = 100.0;
float raymarch(in vec3 origin, in vec3 direction) {
	float t = 0.0;
	for (int i = 0; i < 64; i++) {
		vec3  p = origin + t * direction;
		float height = terrain(p.xz);
		float distance = p.y - height;
		if(distance < 0.02 || t > tmax) {break;}
		t += 0.2 * distance; // 適当な値で距離を小さくする
	}
	return t;
}
```

法線は以下のようにレイマーチングでよく使われる数値差分で求めることができます。

```glsl
vec3 normal(in vec2 p) {
	float epsilon = 0.02;
	return normalize(vec3(
		terrain(p + vec2(epsilon, 0.0)) - terrain(p - vec2(epsilon,0.0)),
		2.0 * epsilon,
		terrain(p +vec2(0.0, epsilon)) - terrain(p - vec2(0.0, epsilon))
	));
}
```

法線をもとにカラーリングを行うとこうなります。
<img width="1258" alt="terrain.png" src="https://qiita-image-store.s3.amazonaws.com/0/61569/1075df67-3bd7-1e0b-b8d6-f8a91d17316e.png">

全コードと動いているところは以下から確認できます。
http://glslsandbox.com/e#44275.0

ここからは、細かいテクニック的な話をします。

raymarch関数の中で、レイと地形との交差判定に以下の式を用いました。

```glsl
if(distance < 0.02 || t > tmax) {break;}
```

これを以下のように、`distance`との比較に`t`を用いることで、近いところほど正確に、遠いところは粗い交差判定を行うことができます。

```glsl

if(distance < 0.001 * t || t > tmax) {break;}
```

同様に、法線の計算でも以下のように交差点の`t`を渡すことで、近いところほど細かい計算を行うようにできます。

```glsl
vec3 normal(in vec2 p, float t) {
	float epsilon = 0.001 * t;
	return normalize(vec3(
		terrain(p + vec2(epsilon, 0.0)) - terrain(p - vec2(epsilon,0.0)),
		2.0 * epsilon,
		terrain(p +vec2(0.0, epsilon)) - terrain(p - vec2(0.0, epsilon))
	));
}
```

他のテクニックとして、次のように交点を一つ前のステップの値と補間することでより正確な`t`の値を求める方法があります。

```glsl
const float tmax = 100.0;
float raymarch(in vec3 origin, in vec3 direction) {
	float t = 0.0;
	float step = 0.0;
	float lastdistance = 0.0;
	for (int i = 0; i < 64; i++) {
		vec3  p = origin + t * direction;
		float height = terrain(p.xz);
		float distance = p.y - height;
		if(distance < 0.02) {
			t  += step * distance / (lastdistance - distance);
			break;
		}
		if (t > tmax) {break;}
		step = 0.2 * distance;
		t += step;
		lastdistance = distance;
	}
	return t;
}
```

詳しくは、次のサイトで解説されています。

http://www.iquilezles.org/www/articles/terrainmarching/terrainmarching.htm

地形のライティングは以下のリンク先の内容が参考になります。
http://www.iquilezles.org/www/articles/outdoorslighting/outdoorslighting.htm
winscpのスクリプトを使って自動でサーバにソースをコピーする

よく使うので

動かすバッチファイル
以下を変換する
{script path} : スクリプトファイル配置場所

```batch:sync.bat
CALL :TEST_SERVER

:END
exit 0

:TEST_SERVER
start winscp /sript={script file}
exit /b
```

winscpのスクリプトファイル
設定ファイル(config.txt)は環境によって異なると仮定して排除
ソース管理はgitで行っていると仮定して排除
以下を変換する
{serverip} : 配置先IPアドレス
{local src path} : ローカル上のパス
{remote src path} : 配置先のパス

```text:winscp_sync.txt
option batch abort
option confirm off

open scp://user:password@{serverip}
synchronize -filemask="| config.txt; .git/" remote {local src path} {remote src path} -delete -nopermissions
keepuptodate -filemask="| config.txt; .git/" {local src path} {remote src path} -delete
exit
```

参考
<a href="https://ja.osdn.net/projects/winscp/wiki/script_commands">winscp コマンドリファレンス</a>