OmniAICreator/Qiita-1.07M huggingface dataset:
【 Dimension CC】カメラの状態を他の３Dソフトで使う

この記事は [Adobe Dimension CC Advent Calendar 2017](https://adventar.org/calendars/2194) 20日目の記事です。 
もう１ヶ月すぎてるけど気にしない！

Adobe Dimension CCはデザイナー向けのお気楽３Dレイアウトソフトなので、PSDへの出力機能はありますが、fbxなど一般的な3Dフォーマットへのエクスポート機能はありません。（今後FBXインポートは追加される様です。出力はソフトのコンセプトを考えるとどうでしょう？）

ですが、 Dimesionで編集中の画面にあわせたモデルを3Dソフト側で用意したい状況が個人的にあったので、MAYA上でにたような画面を再現できるか試してみました。

![ 2018-01-21 17.15.45.png](https://qiita-image-store.s3.amazonaws.com/0/8302/981a81e2-06e9-ec12-b100-ff33063d23bf.png)
まず、カメラのアングルを持って行くことを考えます。単位が不明ですが、カメラのパラメータはここにありますので、

<img width="459" alt=" 2018-01-21 17.17.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/17801166-a6e0-447a-cc7e-470b924521dc.png">
MAYAのシーンに新規カメラを作って値を同じように設定していきます。Dimensionの`視野`の値を、MAYAのカメラシェイプの`ビューアングル`に設定します。

<img width="450" alt=" 2018-01-21 17.17.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/37d42cea-1ee6-af6f-d55f-72b08c49cf10.png">
同様に、`位置`および`回転`の値をカメラトランスフォームの`移動`と`回転`に設定します。なお、MAYAの長さの単位は`cm`になっています。入力項目が青いグレーになっているは値をロックしたからなので、気にしないで下さい。

<img width="549" alt=" 2018-01-21 17.21.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/d83f9b17-c794-7de0-08a3-1525649ca67e.png">
ここでいったんこのカメラからのビューを確認します。あっているような気がしますね。
（ドキュメントの設定はDimensionの画像サイズに合わせてあります。）

<img width="440" alt=" 2018-01-21 17.20.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/3aa3eccb-4a84-8b20-f420-0f0a514df527.png">
わかりやすくするために、Dimensionから書き出した画像をカメラに追従する背景として設定してみます。カメラシェイプの属性のこの辺りから画像選択ができます。

<img width="527" alt=" 2018-01-21 17.21.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/771deaa6-28d7-52ef-6f3d-d38d66f7cc0d.png">
わかりやすくなりました。カメラの位置、パースなど合っている様です。

<img width="414" alt=" 2018-01-21 17.33.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/ae12109a-81bd-cd8c-6711-48bb0680fc5d.png">
テストとして、他のオブジェクトを読み込んでみます。左下のグリーンでハイライトされいるのがカメラで、そこから背景画像の方向を写すので、別のアングルから俯瞰するとこの様になります。面白いですね。

<img width="519" alt=" 2018-01-21 17.38.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/8302/6f32b147-d691-7880-b048-e42f41f0b3ad.png">
読み込んだモデルの位置をあわせてみました。うまくいっている様です。

MAYA側でレンダリングする気が無いので、環境ライトまで持ってきていませんが、持ってこれるといいですね。
中間ファイルとしてどこかに書き出されて無いものだろうか。
AWS Auto Scaling勉強まとめ

・需要に応じて自動的にサーバーが増減し、コストカット

`Auto Scaling Group`
・設定した最小値～最大値に起動インスタンスを収める
・起動台数をAZ間でバランシング
・AZ障害時は他のAZでインスタンス起動

`Launch Configuration`
・AMIやインスタンスタイプ、IAMなどを設定して起動する

`Scaling Plan`
・どのようにインスタンスを起動するか
①Auto Scaling Planの維持
最小台数を維持する。
`Auto Healing`：インスタンスに障害発生時に自動的にサービスから切り離し、健全なインスタンスをサービスイン

②手動管理
インスタンスを手動で変更

③スケジュールベース
CLI/SDKで定義
スケーリング開始は最大2分遅れる場合があるので注意

④動的スケーリング
監視：CloudWatchに応じたインスタンスの増減

上記の複数のプランを組み合わせることも可能

`ヘルスチェック`
①EC2ヘルスチェック：インスタンスのステータスがrunning以外を以上と判断
②ELBヘルスチェック
・ヘルスチェックの猶予期間がある。インスタンス起動からヘルスチェック開始までの時間。アプリケーションデプロイを考慮
・異常と判断されたインスタンスは自動的に終了

`クールダウン`
スケーリングアクション実行後指定した時間は次にスケーリングアクションを実行しない仕組み
→インスタンス初期化中の無駄なスケーリングを回避するため
※シンプルスケーリングポリシーにのみ対応

`ターミネーションポリシー`
①OldestInstance/NewestInstance：起動時刻
②OldestLaunchConfiguration：最も古いLaunch Configuration
③ClosestToNextInstanceHour：課金のタイミングが近い
④Default：②③の順に適用。複数インスタンスが残ればランダム

`インスタンス保護`
任意のインスタンスを削除されないよう保護できる

・インスタンスのデタッチ、アタッチ、スタンバイ

`ライフサイクルフック`
Auto Scalingの起動/終了時に一定時間（デフォルトは1時間、最大48時間）待機させ、カスタムアクションを実行できる

・スケールアウト時の初期化処理
①設定済みのAMIを用いる
②user-dataで初期化スクリプトを実行（Bootstrap処理）
③ライフサイクルフックで初期化

・サーバーをステートレスにする
`ステートレス`：サーバーにセッション情報などがない。スケールアウトに向いている
`ステートフル`：サーバーにセッション情報あり。常にサーバー間で同期が必要なので、スケールアウトに向いていない

・突発的なスパイクには向いていない
→インスタンス作成～アプリ起動の時間がかかるため。
対応策としては、
①CloudFrontなど大きなキャパシティを持ったAWSサービスに処理をオフロードする
②スパイクを裁くのを諦め、スロットリング機能（処理性能の上限）を設ける
③一定以上の負荷を超えたら静的ページに切り替える

・ユースケース
①ELB配下のWebサーバーをAuto Scaling
→EC2は複数AZに分散し、高可用性
ELBのリクエスト数、EC2の平均CPU使用率などがトリガー

②SQSのジョブを処理するWorkerをAuto Scaling
キューのメッセージ数などがトリガー

③Blue/Green
`Blue/Green`
デプロイ時に、既存のインスタンスとは違うインスタンスを作成し、一気に/徐々に作成したインスタンスを使用するようにする。
移行方法は下記
・DNSのWeighted round robinを使用して、徐々にトラフィックを移行
→DNSのTTLを考慮する必要あり。
・ELBを利用して、移行する
→Elastic Container Service(ECS。Dockerコンテナを格納する場所)を利用して、新しいインスタンスを作成することも可能

`In place`
デプロイ時に既存のインスタンスを操作することで対応する

>参考URL：http://aws.typepad.com/sajp/2015/12/what-is-blue-green-deployment.html

`Elastic MapReduce(EMR)`
><Hadoop(分散処理をしてくれるソフトウェア)を動かせる環境を提供してくれるサービス
参考URL：http://mgi.hatenablog.com/entry/2014/05/04/085148

参考URL：https://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-online-seminar-2017-auto-scaling
Codepenテスト - ボールの投射 -

<p data-height="800" data-theme-id="0" data-slug-hash="xpMzBQ" data-default-tab="js,result" data-user="popondelion" data-embed-version="2" data-pen-title="xpMzBQ" class="codepen">See the Pen <a href="https://codepen.io/popondelion/pen/xpMzBQ/">xpMzBQ</a> by popondelion (<a href="https://codepen.io/popondelion">@popondelion</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
centos7 monit で監視

#monitとは？

cron , nginx 等が落ちた時に自動復旧してくれる。
#インストール

```
yum install -y monit
```

##設定ファイルの編集 (デフォルトのままでも良い。)

```
vim /etc/monitrc
```

##スタート
```
systemctl start monit
systemctl enable monit
sudo monit status
```

#自動起動設定ファイルを作っていく

##cron

```/etc/monit.d/crond.rc
check process cron with pidfile /run/crond.pid
  group system
  start program = "/bin/systemctl start crond"
  stop  program = "/bin/systemctl stop crond"
  if 5 restarts within 5 cycles then unmonitor # 5回の監視中に、5回再起動を実施して監視を停止する
```

##sshd

```/etc/monit.d/sshd.rc
check process sshd with pidfile /var/run/sshd.pid
    start program = "/bin/systemctl start sshd.service"
    stop  program = "/bin/systemctl stop sshd.service"
    if 5 restarts within 5 cycles then unmonitor
```

##mysql (mariadb)
199-9-149-299.pid 数字を適宜変更

```/etc/monit.d/mysql.rc
check process mysql with pidfile /var/lib/mysql/199-9-149-299.pid
start program = "/bin/systemctl start mysqld.service"
stop program = "/bin/systemctl start mysqld.service"
if 5 restarts within 5 cycles then unmonitor
```

##redis

```/etc/monit.d/redis.rc
check process redis with pidfile /var/run/redis_6379.pid
start program = "/bin/systemctl start redis.service"
stop program = "/bin/systemctl start redis.service"
if 5 restarts within 5 cycles then unmonitor
```

#構文チェックし、リスタート
これやらずにリスタートするとバグに気づかないのでやっとく。

```
monit -t
sudo systemctl restart monit
```

**ここまで設定完了**

#動作チェック

##pidを確認します

```
find / -name '*.pid' -print
```

##サービス停止してみます

```
sudo systemctl stop nginx
find / -name '*.pid' -print
```

nginx.pid がありませんね。

#30秒待ちまーす

```
find / -name '*.pid' -print
```

nginx.pid 復活しましたね。
Active content with certificate errors の対処方法

# はじめに
firebaseでカスタムドメインを設定したときにSSL証明書が発行されないということから始まりました。

firebaseではカスタムドメインにもSSL証明書が発行されるということで色々と設定をしたんですが、待てど待てども「保護されていません」として扱われるという。

# 原因
chromeのApplicationタブに

```
Active content with certificate errors

You have recently allowed content loaded with certificate errors (such as scripts or iframes) to run on this site.
```

というエラーが出ているではありませんか。

Google翻訳にドバッとやる。

```
証明書エラーのあるアクティブなコンテンツ

最近、証明書のエラー（スクリプトやiframeなど）がロードされたコンテンツをこのサイトで実行することができました。
```

なんだこれは。なんのことやら。


# 解決方法

Applicationタブの中にClear storageというものがありました。これで何かしら削除する必要があるようです。（正確にはわかっていない）

こちらの[stackoverflow](https://stackoverflow.com/questions/44145936/chrome-active-content-with-certificate-errors)に書いてありました。

実際何してるかはこちらの[公式ドキュメント](https://developers.google.com/web/tools/chrome-devtools/manage-data/local-storage?hl=ja#clear-storage)をどうぞ。


- デベロッパーツールを開く
- Storageをクリアする
- タプを閉じて再度新しくあタブを開く

これで解決することができました(T_T)


# 終わりに
時間かかってんかなーって思ってたら自分のせいでした。。。とほほ。
デベロッパーツールのApplicationあんまり確認しないからだいぶ時間かかってしまいました。

firebaseのせいにしてたあのときの自分を責めてます。失礼しました。。。。
XTemplateのxindexの使い方

xindexの使い方でよく迷うのでメモ

ifのなかで使う場合は括弧なしでそのままxindexと記載し、
HTMLの穴埋めに使う場合は{[xindex]}と記載する

## 記載
```js:Template.js
Ext.define('sencha.view.main.Template', {
    extend: 'Ext.Component',
    xtype: 'comptep',
    renderData: {
        abc: [{hoge:'aaaa'},{hoge:'bbbb'}]
    },
    renderTpl: new Ext.XTemplate(
        '<div>',
        '<tpl for="abc">',
        '<tpl if="xindex == 1">',
        '<p>{[xindex]}{hoge}</p>',
        '</tpl>',
        '</tpl>',
        '</div>'
    )
});
```

##結果

![image.png](https://qiita-image-store.s3.amazonaws.com/0/132883/23558c80-f1c0-96f6-6a81-831b203b8e9b.png)
Nefry用のケースを作成

# 起
Nefry BT用のケースを制作した。
Nefry用にはケースやケースデータがあるのだが、Nefry BT用には流石にまだなかったので、Fusion 360で作成した。

<img width="1582" alt="Fusion 360001.png" src="https://qiita-image-store.s3.amazonaws.com/0/125657/9a7356c7-dd81-58a5-2fb5-a9aaeef9e2a5.png">

[GitHub](https://gitlab.com/wanwanco/Nefry-Case)にもSTLデータとしてアップしたので、自由に改変などしてほしい。
できれば、改変したデータはGitHubにアップして貰えると、助かる人もいるだろう。
ちなみに自分自身、基板用の下駄を噛ましていたりするので、これも問題なければ現在のデータから変更しようと思う。

# 結
作成自体は大体30分ぐらいでできた。
ただし、3D Printerの方がいうことを聞かず、出力するのに1日ほどかかってしまった。
本当に3D Printerはクセモノ（不良品）を買うと大変である。
ちょっと高くてもそれなりに名が通った光造形式3D Printerを購入することをお奨めする。
安物買いの銭失いにならないように....
Arduino > link > double型をchar型に変換する > dtostrf()

```txt:動作環境
Arduino IDE 1.6.6
ESP8266実装機版 (ユニバーサル基板)
```

MPU-9250からQuaternionの値を取得しようとしている。
取得済のデータ(double)からUDP通信用にchar型に変換が必要だった。

https://stackoverflow.com/questions/19867227/convert-double-type-into-string-type-in-arduino-sketch
に記載のdtostrf()を使ったところ、char型に変換できた。

Quaternionのx成分だけの通信。

```bash
<PyQt5.QtNetwork.QHostAddress object at 0x7f295f16c828>
qtn,0.51,,

<PyQt5.QtNetwork.QHostAddress object at 0x7f295f16c898>
qtn,0.53,,

<PyQt5.QtNetwork.QHostAddress object at 0x7f295f16c828>
qtn,0.43,,

<PyQt5.QtNetwork.QHostAddress object at 0x7f295f16c898>
qtn,0.23,,
```
pythonのリストにリスト(タプル)型の添え字が振られていて困っている人へ

#インデックスがタプルになっている配列を見つけた

機械学習を始めた初期のころに非常に困らされた割には当時Webで調べても答えが見つからなかったので共有します。

Pythonの標準機能であるリストでは

```python3:list
>>> list = [1,2,3,4] 
>>> print(list)
[1, 2, 3, 4]
#リストをそのまま表示
>>> print(list[2])
3
#リストの3番目の要素を表示

```

となります。当たり前ですね。二次元配列にしたい場合は

```python3:two_dimensional_list
>>> list_list = [[1,2],[3,4],[5,6]]
#二次元配列の作成
>>> print(list_list)
[[1, 2], [3, 4], [5, 6]]
>>> print[0][1]
2
#一番目のリストの二つ目の要素を表示

```

となるでしょう。ここで注目していただきたいのが、
`print[0][1]`

の部分です。最初のリストの最初の要素ですから記法は当然こうなります。添え字の部分に
`[0,1]`とするのは間違いだと思っていました。

しかしある日、実際にlist[0,1]という形式で配列内部の要素を抽出しているのを見つけてしまったのです。

##犯人はNumpyのnumpy.arrayだった

上述の通り、
`list_list = [[1,2],[3,4],[5,6]]`
の"2"を表示するためには
`print(list_list[0][1])`
と書く必要があります。

`print[0,1]`と書こうものなら

````python3:Error
>>> print(list_list[0,1])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers or slices, not tuple
```

というエラーが返ってきます。

"リストの添え字は整数だよ。タプルで渡されても困るよ。"という意味ですね。

<b>しかし、Numpy配列ではデフォルトで添え字にタプルが渡せるのです。</b>以下に例を示します。

```python3:numpy_array
>>> import numpy as np
>>> array = np.array([[1,2],[3,4],[5,6]])
>>> print(array[0][1])  #python標準の表記で2を取り出す
2
>>> print[0,1]  #添え字にタプルを渡しても指定できる
2
```

numpy arrayの仕様だったとは....どなたかの役に立てば幸いです。
GCPでkaggle入門してみた。Titanic: Machine Learning from Disasterをサブミットするまで

##はじめに
###対象読者
*GCPを触ったことがない人
*Kaggleを初めて使う人
*機械学習があまりよくわかっていない人

###このページの目的
*とりあえず、KaggleにチュートリアルのTitanicをサブミットするところまでを環境含めてできるようにする。

###その他
*Qiita初投稿のため読みにくいかもしれません。
*参考サイトを多用します。
*機械学習の中身については触れていません
*個人的メモ（整理）的な側面が強いです

##アジェンダ
1.Kaggleへの登録
2.GCPへの登録と環境の構築
3.処理実行
4.サブミット

##1.Kaggleへの登録
まず、こちらはQiitaの下記記事を参考にしました。
[Kaggle事始め](https://qiita.com/taka4sato/items/802c494fdebeaa7f43b7)

ぶっちゃけ上記記事で完結することは可能です。
今回、私は実行環境にGCPを利用したかったため、別の内容を探しました。

##2.GCPへの登録と環境の構築
GCPへの登録に関しては、下記の解説動画を参考にしました。
動画のVol.1~Vol.3まで見ると環境の構築までわかります。
(Anacondaをインストールするところまで実行しました）
[Kaggle入門動画をつくった](http://yutori-datascience.hatenablog.com/entry/2017/10/24/215647)

tkm2261さんの動画です。
Kaggle用Slackも作成されており、そちらにも参加させていただきました。

ここで、私はWindows環境からGCPへファイル転送を行いたかったため、下記を参考にしました。
[Google Compute Engine にscpでファイルコピーを実施](http://guugo.hatenablog.com/entry/2017/12/05/163148)

##3.処理実行
さて、ここで「1.Kaggleへの登録」の参考サイト記事の元へ戻ります。
Titanicのtrain.csvとtest.csvをWinSCPにてGCPのUbuntuへアップロードし、
さらに実証用コードをtitanic.pyとして同一階層に配置して実行。

```
$_HOME/titanic
             test.csv
             train.csv
             titanic.py

cd $_HOME\titanic
python titanic.py

```

##4.サブミット
処理結果として作成された「titanic_submit.csv」を
Kaggleのページよりアップロード

Learderボードに自分の名前が初登場です。
いやー。嬉しいですね。これから徐々にレベルアップしていきましょう。
WindowsでSelenium（Java）を用いてGhost Driverを利用する

# 概要
SeleniumはWebアプリケーションのテストツールであり、ブラウザでのボタンクリックなどを自動化できる。
しかし、Seleniumでのテスト実行時はブラウザが表示されるので、人間がSelenium実行中のマシンで別の操作をするとテストを妨げてしまう場合がある。
一方、SeleniumでGhost Driverを利用すると、ブラウザが表示されないので前述の理由でテストを妨げることはない。
また、ブラウザが表示されないことで実行時間を短くできる利点もある。
そこで、本記事では、Ghost Driverを身近なOSであるWindowsで手短に体験するための環境準備とテストファイル実行方法を紹介する。

# 環境準備
## 動作確認バージョン
・Windows7 HomePremium
・JDK 1.8.0_151
・Selenium Standalone Server 3.8.1
・PhantomJS 2.1.1
・Ghost Driver 1.2.1
　※[Selenium公式サイト](http://www.seleniumhq.org)にリンクが掲載されているGhostDriverのバージョンは1.2.0だが、今回は1.2.1を使用する。

## インストール方法

### JDK
以下記事のとおりインストールする。
[WindowsへのJDKインストール方法](https://qiita.com/ko2a/items/69fa8a5366d7449500ca)

### Selenium Standalone Server
１．[Selenium公式サイト](http://www.seleniumhq.org)からselenium-server-standalone-3.8.1.jarをダウンロードする。
２．任意のフォルダに展開する。
　　今回は、Cドライブ直下にselenium-server-standalone-3.8.1という名前のフォルダを作成し、その中に展開する。

### PhantomJS
１．[PhantomJSの公式サイト](http://phantomjs.org)にアクセスし、phantomjs-2.1.1-windows.zipをダウンロードする。
２．ダウンロードしたphantomjs-2.1.1-windows.zipを任意のフォルダに展開する。
　　今回は、Cドライブ直下にphantomjs-2.1.1という名前のフォルダを作成し、その中に展開する。

### Ghost Driver
１．[http://grepcode.com/snapshot/repo1.maven.org/maven2/com.codeborne/phantomjsdriver/1.2.1](http://grepcode.com/snapshot/repo1.maven.org/maven2/com.codeborne/phantomjsdriver/1.2.1)にアクセスする。
２．phantomjsdriver-1.2.1.jarをダウンロードし、任意のフォルダに展開する。
３．展開した中身のorg\openqa\selenium\phantomjsフォルダをコピーする。
４．コピーしたphantomjsフォルダをC:\selenium-server-standalone-3.8.1\org\openqa\seleniumフォルダ内にペーストする。

# サンプルファイルの作成、実行

## サンプルファイルの作成
以下ファイルをC:\selenium-server-standalone-3.8.1フォルダに作成する。

```java:GhostDriverTest.java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.DesiredCapabilities;

public class GhostDriverTest  {
    public static void main(String[] args) {
        DesiredCapabilities caps = new DesiredCapabilities();
		caps.setCapability(
			PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
			"C:\\\\phantomjs-2.1.1\\bin\\phantomjs.exe"
		);
		WebDriver driver = new PhantomJSDriver(caps);
        driver.get("http://www.google.com");
        WebElement element = driver.findElement(By.name("q"));
        element.sendKeys("Cheese!");
        element.submit();
        System.out.println("Page title is: " + driver.getTitle());
        driver.quit();
    }
}
```

## サンプルファイルの実行
１．コマンドプロンプトを開き以下のとおり入力する。

```
C:\selenium-server-standalone-3.8.1>javac GhostDriverTest.java
C:\selenium-server-standalone-3.8.1>java GhostDriverTest
```

２．コマンドプロンプトに以下メッセージが表示されるのを確認する。
　　※セッション情報なども表示される。

```
Page title is: Cheese! - Google 検索
```
Unityで360動画を作成してYoutubeにアップする

[2020/02/04追記]
現在RecorderはUnity内Package Managerから取得できるようになっています

[2018/01/21追記]
Unity2018から 360動画を生成できるようになりました。手順は以下の通りです。

- *Unity2018を取得する*
2018/1/20現在はまだベータなので[こちら](https://unity3d.com/jp/unity/beta)にあります。

- *アセットストアからRecorderを取得する*
[こちら](https://assetstore.unity.com/packages/essentials/beta-projects/recorder-94079)からアセットを取得します

- *Recorderを立ち上げる*
![スクリーンショット 2018-01-21 16.03.32.png](https://qiita-image-store.s3.amazonaws.com/0/59911/c72c4fa8-6b31-6559-b451-5a2ecd89f282.png)

- *画面サイズを設定する*
初期状態だと360 3Dムービーになっているので、ここではYoutubeの一般的な視聴に適した単眼360(Equirectangular)にします
![スクリーンショット 2018-01-21 16.06.05.png](https://qiita-image-store.s3.amazonaws.com/0/59911/0d534d52-fc0e-d27d-a0b7-ff8806d0ac18.png)
 - Input(s)>Pixels>Collection Method を360 Viewに
 - Output Widthを2048(または4096)に
 - 　Output Heightを1024(2048)に
 - 　Cubemap Widthを1023(2048)に
 - 　Render in Stereoチェックを外す
 
- *動画を撮影する*
Recorderダイアログの一番下にある[Start Recording]を押すとゲーム画面のレコーディングを開始します。もう一度押すとレコーディングを終了します。

- *動画を確認する*
プロジェクト直下のRecordingsフォルダに、movie.mp4という縦横比1:2の動画が生成されています。
![スクリーンショット 2018-01-21 16.20.31.png](https://qiita-image-store.s3.amazonaws.com/0/59911/a4b3ab3c-6065-2519-2481-c1f00a7f2e98.png)
![スクリーンショット 2018-01-21 16.22.48.png](https://qiita-image-store.s3.amazonaws.com/0/59911/9b2c51b7-e5cc-9374-f7ad-8d2ebbd2df14.png)

- *動画にメタデータを追加する*
[YoutubeのHelp](https://support.google.com/youtube/answer/6178631?hl=ja)にしたがってメタデータ追加ツールをダウンロードします
 - ダウンロード![スクリーンショット 2018-01-21 16.27.04.png](https://qiita-image-store.s3.amazonaws.com/0/59911/7dfff3e5-d2fe-6ccc-a997-c7c084306e1f.png)
 - アプリ起動![スクリーンショット 2018-01-21 16.28.10.png](https://qiita-image-store.s3.amazonaws.com/0/59911/a0526ee2-d3b7-9cbd-3b16-4ac91397e9f8.png)
 - 動画を選択![スクリーンショット 2018-01-21 16.29.29.png](https://qiita-image-store.s3.amazonaws.com/0/59911/cf38e3ae-a5ea-671d-226b-405c1a08e00f.png)
 - Inject metadata ボタンを押すとmovie_injected.mp4が生成される![スクリーンショット 2018-01-21 16.29.53.png](https://qiita-image-store.s3.amazonaws.com/0/59911/0f242828-30fb-8be0-46ab-ad0ed8b80934.png)

- *生成された動画をYoutubeにアップする*
 - 生成された動画をYoutubeにアップします



[動画](https://youtu.be/rbrGUuUJ8-g)（こちらは3D360で作成したものをアップしています）
![スクリーンショット 2018-01-21 16.48.18.png](https://qiita-image-store.s3.amazonaws.com/0/59911/01222d5b-8554-5ca9-7ebf-26af0badfccd.png)
【SAP】SD販売管理 処理流れの基本練習

**用語**
*T-code*：トランザクションコード
*SD*：販売管理


### １．SDとは

SDは sales and distributionの略で販売管理といいます。
販売管理では、ビジネスパートナへの製品の販売および出荷やサービスの提供が行われます。

製品およびサービスならびにビジネスパートナに関するデータが、販売処理の基本データです。
SAP システムの販売処理を使用するには、これらのマスタデータをシステムに格納しておく必要があります。

### ２．SDにおける業務トランザクションの処理

#### 得意先マスタ [T-code:XD01,XD02,XD03]

##### ・得意先登録　第一画面

```sap:
勘定グループ：受注先
会社コード：1000

販売組織：1000
流通チャネル：12
製品部門：00
```
##### ・得意先登録　一般データ

```sap:
（省略）
```

##### ・得意先登録　会社コードデータ

```sap:
勘定コード管理
統制勘定：140000(売掛金-国内)
（その他省略）
```

>自動作成した得意先コード：ZQQ98


#### 受注管理 [T-code:VA01,VA02,VA03]

##### ・受注伝票登録　第一画面

```sap:
受注タイプ：OR(標準受注)
（その他省略）
```

##### ・受注伝票登録　概要
```sap:
（その他省略）
```


>自動作成した受注伝票番号：13314


#### 出荷管理 [T-code:VL01N,VL02N,VL03N]

##### ・出荷伝票登録
scpの結果をファイルに書き出すときに余計なものが出て困った話

サーバのバックアップ用shellを
ちまちまと手作りしていたときに軽くはまったので備忘録として残す。

# 前提
環境は`ubuntu 16.04`のはず。

取得したバックアップファイルをサーバ間で持ち合うようにしたかった。
で、サーバ間でファイルコピーするのにscpを使ったらこいつが意外に曲者だった。

# scp
メモ代わりに使用例だけ。

```
scp -i [秘密鍵ファイル] [転送ファイル] [転送先ユーザ]@[転送先IP]:[転送先ディレクトリ]
```

秘密鍵 key.txt を使って local.txt を転送先サーバの user ユーザの ./remotedir にコピーするときは↓

```
scp -i key.txt local.txt user@xxx.xxx.xxx.xxx:./remotedir
```

# はまったところ
標準出力に出てくる転送結果をファイルに出そうとしたら出ない。。。
何度やっても出ないのでググってみたら、みんな結構同じことで悩んでる。

で、参考にさせて頂いた方法がこちら↓

```
ssh -t -q -A localhost scp -i key.txt local.txt user@xxx.xxx.xxx.xxx:./remotedir >> log.txt
```

実行してみると確かに出力される！イケるやん！
これで`log.txt`の中みて100%以外の結果が出てたらアラート出せばいいかなー、とか思ってたら。。。

# 再度はまったところ
`log.txt`にいらない行が入ってくる。。。

```
^Mlocal.txt                                          0%    0     0.0KB/s   --:-- ETA^Mlocal.txt                                          100% 3268     3.2KB/s   00:00
```

余計な改行コード(CR)と転送開始時のログ？が入ってる。
複数ファイルを転送したときには空白行も入ってくる。

うーむ。結果チェックしづらい。

問題点は以下。
- 改行コード(CR)が邪魔
- 空白行が邪魔
- ETA(Estimated Time Arrival：到着予定時刻 だそうな)の行が邪魔

軽くググってみたけど消し方が分からなかったので、
出てきたモノを取り除いて使うことにした。

# 余計なものが出てくるなら除いてしまえばいいじゃない
と、いう事で。
以下のコマンドで余計なものを取り除く。

```
sed 's/^M/\n/g' log.txt | sed '/^$/d' | grep -v ETA
```
※`^M`はctrl+V→ctrl+Mで入力可能。

今思えば`^M`を改行に置き換える必要なかったけど。。。
まぁ良いか。

```
local.txt                                          100% 3268     3.2KB/s   00:00
```

これで結果チェックしやすくなった！

# 今回のオチ
cronでscpさせるとファイルにも結果でないですやん。。。
調べる~~気力~~暇がなくなってしまったので、
結局scpの結果じゃなくて`ls`使ってローカルとリモートのファイルサイズを比較することに。

意味なし！
実例が増えつつあるIoTの進化の向かう先と難しさ

コマツの建機、GEのジェットエンジンなどの先行事例だけでなく、さまざまな企業でのIoT事例が聞こえてくるIoT。さらなる適用範囲の拡大を可能とする通信会社のインフラサービスも提供されるようになってくる中、IoTの進化の向かう先と一方でIoT普及の難しさを指摘するオンラインメディアの記事をピックアップしてご紹介します。既存の仕組みを一度壊さないといけない企業向けのIT関連では難しい面もありますが、モノにセンサを取り付けて新たなデータを収集することによりサービスに反映させるIoTは一種の「カイゼン」の延長線上のアプローチでもあり、日本人・日本企業向きの新技術分野であることなど、進化しつつあるIoTのいまをご覧ください。

※下記サイトからの転載。ビッグデータ・AIなどに関するトピックを毎週取り上げています。
[TechCrowd: https://www.techcrowd.jp/related/](https://www.techcrowd.jp/related/)

#[IoTが教えるダンプカーの経済的な走り方] (http://jbpress.ismedia.jp/articles/-/52056)

Japan Business Pressの「be CONNECTED ビジネスを革新するデジタルトランスフォーメーション」の記事です。タイヤの世界最大手のブリヂストンが、鉱山用ダンプカーの「タイヤ」にセンサーを取り付け、タイヤのデータを取得・分析することで、タイヤの適切なローテーションや公立的なダンプカーの運用方法の提案などを含むタイヤのサービスビジネス化、”Tire as a Service”を目指すアプローチを解説しています。

その核となる技術がIoT。ブリヂストンが開発したIoT技術は「B-TAG」と呼ぶタイヤの圧力・温度管理機構。鉱山用のダンプカーのタイヤ内側側面にセンサを取り付け、タイヤの温度と圧力のデータを取得するものです。タイヤのデータはブリヂストンの鉱山車両向けクラウドサービス「TreadStat」で管理されます。

ブリヂストンがいま掲げているキーワードは”Tire as a Service”。これまでのタイヤ一つ一つを売り切るビジネスから、タイヤ提供のサービス化を目指している。タイヤの現場における運用・メンテナンス、そして廃棄に至るまでのプロセス全体を支援して、その価値に応じた対価を顧客から得るビジネスへとシフトさせようとしています。

現段階での最もわかりやすいIoTの成功パターンのひとつではないかと思います。


#[IoTの適応領域を拡大するLPWAのインパクト] (https://it.impressbm.co.jp/articles/-/15438?_ga=2.33510846.1298063092.1516500993-930876711.1485585625)

IT Leadersが、IoTの適用範囲をさらに広げると考えられている技術インフラのひとつ、LPWA (Low Power Wide Area)を解説している記事です。

LPWAは低消費電力・広域通信を特徴とする無線通信技術の総称であり、2017年には
通信キャリア各社からLPWAサービスが相次いで発表されました。これまでの無線通信技術でIoTを実現しようとしたときには通信距離やコスト、消費電力が大きいなどの問題があり適用範囲を限定している面がありました。Wi-FiやBluetoothであれば通信距離が数十メートル以内に制約されますし、3Gや4G LTEのような携帯電話網には通信コストの問題がありました。また、いずれの技術にも電源を確保できない場所では使えないという問題がありました。

これらの課題を受けて登場してきているのがLPWA。LPWA規格はたくさんあり、大別すると既存の携帯電話網を改良したもと無線免許を必要としない周波数帯を利用するものに分けられますが、共通する特徴は電池交換なしに数ヶ月から年単位での通信を可能にすることにあります。また、利用帯域を絞り通信モジュールを単純化してデバイスコストを下げるとともに、通信速度を抑えることで通信コストの低価格を実現しています。


#[スマホさえあればIoTは始められる] (http://itpro.nikkeibp.co.jp/atcl/column/17/011000609/011500005/)

ITproのIoTラクラク実践術の記事のひとつで、IoTを簡単にラクに実現できる製品やサービスが続々と登場していることを紹介している記事です。

IoTシステムを開発するうえで技術的なネックとなっていたのが組み込み系や通信に関する知識や技術を必要とすること。これまで企業システムの開発にかかわってきたITエンジニアだと難しいと感じる面がありましたが、そのネックを解消する手法としてスマホを使ったIoTシステムの開発を支援する製品・サービスが登場してきています。

たとえば、ボクシーズが提供するサービス「Putmenu」では、顧客がテーブルの上にPutmenu専用アプリをインストールしたスマホを置き、アプリに表示されたメニューから、注文したい料理を選ぶだけで注文が完了します。Putmenuでは、飲食店のテーブルの下に薄型のビーコンPaperbeaconを貼り付けることにより、顧客のスマホから注文情報とともにテーブルの位置情報を送っています。顧客はスマホから注文したら、テーブルに料理が届くのを待っているだけでようのです。

多くの人がもつスマホを使ったIoTサービス、IoTのセンサや通信装置としてスマホを利用することにより投資額が抑えられる面もあり、これからもいろいろ登場してきそうとのことです。


#[IoT普及に立ちはだかる旧来システムの呪縛] (http://toyokeizai.net/articles/-/205052)

東洋経済ONLINEです。IoTの普及の最大の障害になりそうなものとして、20世紀型の業務システム、ITシステムの存在をあげているものです。

鉄道の相互乗り入れが進み、始発から終点までが長距離化した結果、100km以上離れた場所で発生した事故・故障が路線全体の運転に影響を与えることが増えましたが、ITシステムも似ている側面があるとのこと。既存の業務管理系システムをIoT時代に対応させることにより、末端のシステムの異常が瞬く間に全体に波及する危険性があり、それを避けるためには、スパケティのようにこんがらがったシステムとデータの構造を整理したうえで、IoTのシステムを既存システムにどのように追加していくとよいのかを決めてゆく手順が必要と指摘しています。

また、この問題が難しい理由は、既存のシステムは何の問題もなく動いており、IoTに対応するためとはいっても、既存のシステムの構造の整理だけのために多大な予算を投入しても機能が高まったり使い勝手がよくなるわけではないこと。ただ、この問題は90年代後半から指摘されている業務システムの問題でもあり、IoTによりいよいよ待ったなしの問題となってきたと指摘して記事を結んでいます。
Azure リージョン別のネットワーク速度一覧

クーポンの有効期限が間近になったので、[例によって](https://qiita.com/CloudRemix/items/73c2accbd3708906cec5)Azureのリージョン別ネットワーク速度を計測してみた

日本からのネットワーク速度で、選んだリージョンは日本から近いを条件にした
※韓国南部はクーポンが使えないので対象外


##実際の値シリーズ
1. [IDCFクラウドの全リージョン全プランをUnixBenchしてみた](https://qiita.com/CloudRemix/items/73c2accbd3708906cec5)
2. [Azure リージョン別のネットワーク速度一覧](https://qiita.com/CloudRemix/items/04c66d3e19bb6d5e89b4)
3. [格安SIMの実測値統計 by Speedtest.net](https://qiita.com/CloudRemix/items/28e566cec1a357cbc2ca)
4. [さくらのクラウドのリージョン・プラン別ベンチマーク結果一覧](https://qiita.com/CloudRemix/items/37674f6d32a220cd60aa)
5. [プロバイダーの実測値統計 by Speedtest.net](https://qiita.com/CloudRemix/items/207d36b28133bed345bc)
6. [VPSクラウド と Indigo のベンチマーク結果](https://qiita.com/CloudRemix/items/643035d35187db70af08)

## 計測環境

 - CentOS 7.4 64bit
 - [LinuxでもSpeedtestがしたい（speedtest-cli）](https://qiita.com/CloudRemix/items/ad226ea4aa641427e682)
 - Speedtest.netの日本サーバーすべて（全21箇所）

#計測結果

測定日：2017年12月26日

| リージョン | Ping（ms） | Download（Mbit/s） | Upload（Mbit/s） | エラー※ |
|:-:|:-:|:-:|:-:|:-:|
| 東日本 | 37.8 | 527.9 | 303.4 |  | 
| 西日本 | 43.3 | 460.4 | 245.1 |  | 
| 韓国中部 | 111.1 | 290.8 | 155.1 |  |  | 
| 東南アジア | 131.8 | 232.3 | 107.9 | 1 | 
| 東アジア | 112.9 | 233.0 | 120.3 |  | 
| 米国東部 | 249.5 | 141.7 | 64.0 | 2 | 
| 米国東部 2 | 204.1 | 140.6 | 78.3 | 1 | 
| 米国西部 | 182.0 | 148.2 | 77.7 |  | 
| 米国西部 2 | 161.3 | 121.3 | 62.4 |  | 

※計測エラーの数

## 計測したリージョンとプラン

- 東日本 - B1MS（1コア、2GB）
- 西日本 - B1MS（1コア、2GB）
- 東アジア - B1MS（1コア、2GB）
- 東南アジア - **DS1 v2（1コア、3.5GB）**
- 韓国中部 - B1MS（1コア、2GB）
- 米国東部 - **D1（1コア、3.5GB）**
- 米国東部 2 - **DS1 v2（1コア、3.5GB）**
- 米国西部 - B1MS（1コア、2GB）
- 米国西部 2 - B1MS（1コア、2GB）

※プランが違うのは表示されなかったから（リージョンによっては選べないプランがある？）

## インスタンス環境
用意されているCentOS 7に`yum -y update`しただけ
同時に`UnixBench`と`DiskKBench`もした

#一言
韓国南部の値がすごく気になる結果になってしまった...どうしよ
Androidいろいろメモ

# Androidいろいろメモ

１個ずつ記事にするのは面倒だけど、しょっちゅう忘れてググり直す情報のメモ。

## Gifアニメ

画面の動きをGifアニメにする方法。
ファイルサイズが肥大化するので、 540x960 のところはできるだけ小さくした方が良い。
かと言って小さくしすぎると荒くなる。実際の半分くらいがちょうどいい。

### adb shell screenrecord
```bash
adb shell screenrecord /sdcard/output.mp4 --size 540x960
adb pull /sdcard/output.mp4
```

### mp4をgifアニメに変換
```bash
ffmpeg -i [mp4 file] -an -r 15 -pix_fmt rgb24 -s 540x960 -f gif [output animation gif]
```

### 繰り返し数を指定

↑の方法だと無限ループになる。１回だけにしたい場合
https://qiita.com/sune2/items/734cc4c631bb0d202910

```bash
brew install gifsicle
```
```bash
gifsicle --no-loopcount file.gif > out.gif
```


## CHANGELOG自動生成

https://rcmdnk.com/blog/2017/05/15/computer-github/

```bash
gem install github_changelog_generator
```

```bash
github_changelog_generator
```
メモ: numpyで全点間の距離を求める

多次元座標が入った配列$x$と$y$について、$z_{ij}$に$x_i$と$y_j$の距離が入ったような配列$z$をどのように得るかと言ったお話。
numpyのブロードキャスト機能をうまく使うと簡潔にかけて50倍ぐらい早くなった

```python3

import timeit
x = np.random.random(10000).reshape(500,20)
y = np.random.random(10000).reshape(500,20)
def calic_dist(x,y):
    z = np.zeros((len(x),len(x)))
    for i in range(len(x)):
        for j in range(len(x)):
            z[i][j] = np.sum((x[i] -y[j] ** 2))
    z = np.sqrt(z)
    return z
    
def calic_dist_np(x,y):
    try:
        assert isinstance(x,np.ndarray)
    except AssertionError:
        x = np.array(x)
    try:
        assert isinstance(y,np.ndarray)
    except AssertionError:
        y = np.array(x)
    assert x.shape == y.shape
    z = x.reshape(x.shape[0],1,x.shape[1]) - y.reshape(1,x.shape[0],x.shape[1])
    zz = np.sum(z**2, axis=2)
    zz = np.sqrt(zz)
    return zz

%timeit z = calic_dist(x,y)
%timeit zz = calic_dist_np(x,y)
assert z == zz
```
実行結果はこんな感じ

```
1.34 s ± 22.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
23.3 ms ± 532 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
```
ブロードキャストを使っているのは`z = x.reshape(x.shape[0],1,x.shape[1]) - y.reshape(1,x.shape[0],x.shape[1])`
の部分。なんにせよ50倍ぐらいは速くなっていそうだ。
ただし普通にアルゴリズムとしては$O(n^2)$だと思われるので基本的にはこのような計算は避けたいところではあるのだろう。
初心者がコピペでRaspberry PiとPepperをNode-REDで繋いだ話


頑張ってコピペでraspberry pi 3から信号を送ってPepperが受け取ることを試した

環境
Raspberry Pi 3
OS:Raspbian

Pepper(naoqi2.5.6)

#構成
raspberry pi 3→node-RED→Pepper

#raspberry pi側


クリックしたらPepperが喋る、というのを実現するためにinjectノードを作ります。
<img width="824" alt="スクリーンショット 2018-01-20 18.42.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/222559/0b840db8-5e7d-7291-032a-de5673a83c78.png">

http requestノードの中身はPepperのIPアドレスと、後述するPepperのポートが8000となるためポートも記述します。
<img width="831" alt="スクリーンショット 2018-01-20 18.44.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/222559/97d498bf-2876-9718-89ad-24b7629d2dd7.png">

こんな形にしてinjectノードをクリックするとPepperにリクエストがいくようにします。
<img width="472" alt="スクリーンショット 2018-01-21 14.39.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/222559/f9d796e3-66d8-5252-1e4d-dff5ddbf3ff9.png">

#Pepper側

Pepper側は以下の記事を参考にします。
https://qiita.com/tkawata1025/items/a4f249a981a406b262c9

そのまま参考にして作ったtestボックスとSayボックスを繋いでいます
<img width="437" alt="スクリーンショット 2018-01-21 14.50.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/222559/a6385745-ec43-9bd2-8afb-4595dbbb39e0.png">

HTTP GETリクエストがあるたびにSayボックスに信号を送るように45行目に追記しています。
<img width="866" alt="スクリーンショット 2018-01-21 14.48.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/222559/d8ec6ff9-3238-ede0-e7aa-f68537e96ff8.png">
多次元時系列データをリサンプリング

#はじめに
時系列データを扱っていると、
　・データが一様な時間間隔でサンプリングされていない
　・しかも多次元データ
な場合があります。
一様にサンプリングされていない多次元データを、任意のサンプリングレートで一気にリサンプリングする関数を作成しました。

開発環境
Python 3.5.2 Anaconda 4.2.0 (x86_64)
Mac OS X EI Capitan 10.11.6

#まず時系列データを生成
```python:multidim_interpolate.py
# coding: UTF-8

#各種必要なライブラリをインポート
import pandas as pd
import numpy as np
from datetime import datetime
from scipy import signal, interpolate
import matplotlib.pyplot as plt

collist=["cos","sin","tan"]
df = pd.DataFrame([np.zeros(3)],columns=collist,index=[0])
starttime = datetime.now()
for i in range(1000):
	elapsed = (datetime.now() - starttime).total_seconds()
	sin_df = pd.DataFrame({"sin" : np.sin(elapsed)},index = [elapsed])
	df =  df.append(sin_df)
	elapsed = (datetime.now() - starttime).total_seconds()
	cos_df = pd.DataFrame({"cos" : np.cos(elapsed)},index = [elapsed])
	df = df.append(cos_df)
	elapsed = (datetime.now() - starttime).total_seconds()
	tan_df = pd.DataFrame({"tan" : np.tan(elapsed)},index = [elapsed])
	df = df.append(tan_df)	
```
今回はsin,cos,tanの3次元のデータを取り扱うこととしています。また、各データのタイムスタンプを、pandas.DataFrame()のindexとして保持しています。

#多次元時系列データをリサンプリングする関数
```py
def multidim_resample(df, Hz=100):
	resample_df = pd.DataFrame()
	for col in df.columns:
		tmp_df = df[col].dropna()
		#補間とリサンプリング
		f = interpolate.interp1d(tmp_df.index,tmp_df)
		resample_x = np.arange(tmp_df.index.min(),tmp_df.index.max(),1/Hz)
		resample_y = f(resample_x)
		#リサンプリングした結果をresample_dfに保存
		resample_y= pd.DataFrame(resample_y, index=[resample_x],columns=[col])
		resample_df = pd.concat([resample_df, resample_y], axis=1)
	resample_df = resample_df.dropna()
	return resample_df
```

各列を順番にリサンプリングし、最後にconcatしています。
今回は線形補間として、

```py
f = interpolate.interp1d(tmp_df.index,tmp_df)
```
としましたが、引数を色々と変えることで、スプライン補間やらなんやらも使えるようです。
[scipy.interpolate.interp1d]
(https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html "scipy.interpolate.interp1d¶")

#使ってみる
```py
resample_df = multidim_resample(df,100)
resample_df.plot(ylim=[-1, 1])
plt.show()
```

![resample_df.png](https://qiita-image-store.s3.amazonaws.com/0/232337/791db6d4-b7e6-78d9-794d-2f8ba5319775.png)

いい感じで補間されたっぽいです。


#まとめ
一様にサンプリングされていない多次元データを、任意のサンプリングレートで一気にリサンプリングする関数を作成しました。
サンプリングレートが1秒とかなら、[pandas.DataFrame.resample](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.resample.html "Qiia")で一気にやっちゃうのが楽ですね。
ASP.NET Web Forms でドロップダウンリストの値を復元する

# ASP.NET Web Forms でドロップダウンリストの値を復元する

## Local Storage を使う

```html:WebForm1.aspx
<body>
  <form id="form1" runat="server">
    <asp:DropDownList ID="DropDownList1" runat="server">
      <asp:ListItem Value="0">Item0</asp:ListItem>
      <asp:ListItem Value="1">Item1</asp:ListItem>
      <asp:ListItem Value="2">Item2</asp:ListItem>
      <asp:ListItem Value="3">Item3</asp:ListItem>
      <asp:ListItem Value="4">Item4</asp:ListItem>
    </asp:DropDownList>
    <asp:Button ID="Button1" runat="server" Text="Button" />

    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.min.js"></script>
    <script type="text/javascript">
      $(function () {
        $('#DropDownList1').val(localStorage.getItem('DropDownValue'));

        $('#Button1').click(function () {
          localStorage.setItem('DropDownValue', $('#DropDownList1').val());
        });
      });
    </script>
  </form>
</body>
```

## Cookie を使う

Cookie の期限を指定しないと保存されないのがミソ。

```csharp:WebForm1.aspx.cs
public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
            return;

        var cookie = Request.Cookies.Get("DropDownValue");
        DropDownList1.SelectedValue = cookie?.Value;
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Response.Cookies.Set(
            new HttpCookie("DropDownValue", DropDownList1.SelectedValue)
            {
                Expires = new DateTime(9999, 12, 31)
            });
    }
}
```

## 確認した環境

- 日本語 Windows 10 Home 64-bit
- Visual Studio Community 2017 Version 15.5.4
AI覚書①人工知能の変遷と歴史について


人工知能についての勉強会に参加し始めたので、学習したことのメモをまとめます。
個人的なまとめですので、間違いがあるかもしれません。指摘していただければ幸いです。
まずは、今回のターゲットである「人工知能」の歴史や性質について。

## 1.推論と探索の時代　＠第一次AIブーム
- 1950年代：アラン・チューリング「知性を持つ機械」
機械の知性、という点についての考察の嚆矢となったのがアラン・チューリング氏。氏は、「機械に、知性を持った振る舞いができるか」という問題について考察。
その論文から生まれたのが、「チューリングテスト」である。<br>
*チューリングテスト*
*相手を知らされない状況で、一人の人間がディスプレイ上でチャットを行い、会話相手がbot(機械)であるかを見抜くことができるかというテスト*<br><br>

- 1956年：ダートマス会議「人工知能」
有識者による集会、ダートマス会議において初めて「人工知能(artificial intelligence)」という言葉が用いられる。
この時扱われたテーマは多岐に渡ったが、すでにニューラルネットワークなどのテーマについても触れられていた。<br>
*ニューラルネットワーク*
*人間の脳の構造を模した数学モデル。現在の深層学習の基礎理論となっている。*

<br>
###この時代のAI
ある規則が存在する中で、考えうることの中から最良の正解を志向し（推論）、それを実現する方法を模索（探索）するAI。
オセロなど明確なルールが前提として存在している環境において最善手を探し出すことができたため、機械に知性が宿ったと認識されブームに。
しかし、規則の存在しない現実世界への落とし込みは不可能であったため、ブームは沈静化。いわゆる「冬の時代」に突入することとなる。

- 優れていた点<br>
・前提の明確な、いわゆるゲームなどにおいては、人間の到達し得ない域への到達が可能となった。
- 問題点<br>
・前提が明確でない環境においては、無力であった。


## 2.知識表現の時代　＠第二次AIブーム
- 1970年代「mycin」の登場<br>
エキスパートシステム「mycin」の登場により、第二次AIブームが始まった。このmycinは病原菌の診断システムであり、mycinの発する問いに医師がyes/noで答えることにより病原菌の名称を特定するというものであった。
第一次ブームにおけるAIの課題が現実世界への対応力が皆無であったという点をこのmycinは克服しており、エキスパートシステムこそ人間世界に干渉しうるAIだと持て囃されることとなる。
しかし、このエキスパートシステムの構築には、知識の注入という点で人間の多大な介入が必要であり（mycinの制作にも６年ほどの歳月を要している）、人間世界の諸事象についてシステムを構築するのは現実的でないという理由からブームは沈静化。AI界隈は再び「冬の時代」に突入した。

*エキスパートシステム*
*人間の専門家が答えを導く能力を再現したシステム。特定の　分野についての知識・ルールを集積することにより、それらに基づく判断を行うことができる*

###この時代のAI
ゲームを優れた方法で攻略する、という全時代のAIのあり方から大きく進歩。ルールの存在しない現実問題への対処が可能となった。一義のルールはなくともそれに関する知識はデータベースとして存在する事象は数多くあり、医療のみならず、様々な分野における分化が期待された。
しかしそのシステム構築には多大な労力が必要であり、そうして作られたシステムに果たして労力に見合うだけの価値があるのかという疑問に答えらるだけの事象はそれほどなく、技術的には優れていたもののやはり現実世界への対応という点で普及しなかった。

- 優れていた点<br>
・全時代の課題であった「現実世界への介入」という問題を解決した<br>
・明確の定義が存在していなくとも、膨大な知識を利用することで正解を導き出すことができるようになった
- 問題点<br>
・一つの分野についてですら、そのシステムが成立するだけの知識を与えるためには人間の多大な労力が必要であり、その制作が現実的に難しかった


## 3.機械学習の時代　＠第三次AIブーム
- 2012年：「ディープラーニング」の登場
画像認識の精度を競うILSVRCというコンテストでは、従来エラー率26%前後がトップ値であり、その値を1%更新できたチームが優勝を果たせるというレベルでの戦いが繰り広げられていた。そんな中、2012年に初出場したトロント大学のチームが、従来のエラー率を実に10%も更新する17%という数字を叩き出し優勝し、世間を騒がせた。
この時使用されていたのが「ディープラーニング」である。

ディープラーニングの基礎理論となっているのは、人間の脳構造の模倣、ニューラルネットワークである。
もともとこの分野については多くの研究がなされおり、その嚆矢「パーセプトロン（：脳機能を２層構造で再現）」や３層構造型のニューラルネットワークなどが開発されていた。しかし３層が従来の再現限界であり、そのレベルでは多くの解決し得ない問題が存在していたため日の目を見ない技術となっていた。

そこで登場したのがディープラーニングである。ディープラーニングは４層以上の多層構造を再現することに成功し、多くの現実問題を処理することのできる可能性を秘めた技術となった。

ディープラーニングの大きな特徴は、「自ら対象の特徴を学習できる」という点である。
エキスパートシステムでは、ある判断を行うための材料となる知識を人間がインプットせねばならず、その点がAI普及のボトルネックとなっていた。
しかしディープラーニングは、その材料となる知識を自ら収集する能力を持つ。

現実の諸問題と独力で相対する力を持ったシステムの登場により第三次AIブームが到来。現在、再びの「冬の時代」は訪れていない。


###この時代のAI
現実問題への対応という点について、技術力・労力の点から実現可能性を見出した。
エキスパートシステムがそうであったようにその対応分野は無限大であり、かつエキスパートシステムとは異なり知識収集において人間による注入作業を必要としないため、あらゆる場面においてその導入を検討することができる。
- 優れている点
・自ら対象の特徴量を収集することができるため、そのシステム構築において人間の介入を基本的に必要としない
AWS S3を使ってUnity WebGLの開発で起こったこと。

## まえふり
UnityでWebGL向けに開発し、ネットに公開するには何らかの方法でサーバーが必要になります。
本番をどのように対応するかはさておき、簡単かつ無料でWebGLを公開したいのであればAWSの1年無料枠でS3を使って動作確認しました。

そのときの内容とトラブったことのまとめになります。
個人的に、Unity使ってWebGL向けの開発をしている人で、WebGLのデータを置くサーバーを検討している人やどうするのか分からない人などにこの記事を参考にしていただけると幸いです。

## 環境
* Unity 2017.2.0f3
    * WebGL
* AWS（無料枠）
    * EC2, S3

## Unity WebGLでの開発について

### クロスドメインとCORS
Unity内でサードパーティなどの外部連携の際、[APIをWWWなどで処理させる](https://developers.cyberagent.co.jp/blog/archives/6649/)と思います。

WWWの処理は、Unityがビルドするプラットフォームに合わせて対応しているため、iOS/Androidだったらネイティブの通信処理に合わせた対応が行われており、WebGLはJavascriptのXMLHttpRequestで対応している模様。
[WebGLでサードパーティなどの外部連携を行うと必ず、**クロスドメイン**問題が発生します。](https://docs.unity3d.com/ja/current/Manual/webgl-networking.html)

今回のクロスドメイン問題の対応は、開発しているゲーム専用のAPIも開発していたので、そこを経由して外部連携することにしました。

　
　　　<img src="https://qiita-image-store.s3.amazonaws.com/0/82601/a5100a4b-765a-e238-8905-8fef5de3d18b.png" width=75%>

　

#### 検証: S3でCORSの設定について
[S3には、外部からのアクセスを考慮するためCORSの設定](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/cors.html)があります。これは外部向けに設定するケースっぽいから、今回はその逆なので関係ナッシング。

PHPで説明するところの

```php
header('Content-type: application/json');
header("Access-Control-Allow-Origin: *");
```

を対応しないと解決しないので、実は記事書いている時に気づいたものの、、ふぅ笑

だいたいの人がサーバーを用意することが多いよねー。

関連記事: 
* [WebGL WWW security (Cross-Origin Resource Sharing) help please](https://forum.unity.com/threads/webgl-www-security-cross-origin-resource-sharing-help-please.328419/)
* [Unity 5 の WebGL で外部からテクスチャを与える方法について調べてみた](http://tips.hecomi.com/entry/2014/12/27/155958)


### HTTPS（SSL）
今回、プライベートでの開発でなるべくお金をかけて開発したくなかったため、AWSの1年間無料枠を前提に開発を進めていました。[EC2には**パブリックDNS**](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/using-instance-addressing.html)、S3にはリンクが用意されるので、ドメインを用意することなく動作確認までできちゃいます。


![スクリーンショット 2018-01-21 13.45.08.png](https://qiita-image-store.s3.amazonaws.com/0/82601/46167ebe-7484-0553-4f95-97fb87b81b97.png)

![スクリーンショット 2018-01-21 13.49.37.png](https://qiita-image-store.s3.amazonaws.com/0/82601/19cc6b15-3512-3301-5480-e3552a8d4edc.png)


ただし、S3はhttpsでEC2はhttpなので、S3はAWSが提供しているSDKを使って、データのダウンロードをすることがありますが、直リンクで扱うことも全然あるので、セキュリティ関連で問題になったりならなかったり。

今回、EC2のパブリックDNSによって、「Mixed Content: The page at ...」というエラーに遭遇しました。

#### Mixed Content: The page at ...
実際には↓こんなエラーです。

![スクリーンショット 2018-01-21 14.22.05.png](https://qiita-image-store.s3.amazonaws.com/0/82601/8aa6f2cb-45e4-cc28-26bc-efdff781ec03.png)


[Wordpressでよく遭遇する問題としてよく見かけます](http://pikoro.revows.biz/2016/01/blog-7/)が、今回の場合だと、サードパーティで扱われるAPI群が全てHttpsで用意されていたため、Httpで統一する方法が取れず、EC2のパブリックDNSでは限界がきた感じ。

#### 対応方法
Route53でドメインを購入し、[ACMでSSL証明書を発行してRoute53とロードバランサーと連携する方法](https://qiita.com/gremito/items/2a416b042a0c94d4541d)になるかと思います。


## まとめ
ここまでで大きなトピック２つをご紹介しました。
全て把握すると開発中でなくても情報さえ把握しておけば、今回のようなことは設計段階で解決する内容だと思います。
知っておけば設計段階で問題解決することは、どんな分野でも一緒ってことですねー。

特に経験者には敵いませんねぇ、、ホント笑
Python3でCSVの読み込み


Python2と3では、やり方が少し違うようですので、メモっておきます
はてなブログにも書きましたが、こっちでも書いていきます。
[Python3の基礎　ファイル(CSV)を読み込む編](http://peaceandhilightandpython.hatenablog.com/entry/2017/07/23/134117)

####importするのは2と同じcsv

```
import csv #python2も3もここは同じです

for ......
```


####このCSVを読んでみます

```text:data.csv
1,11,111,1111,11111
2,22,222,2222,22222
3,33,333,3333,33333
4,44,444,4444,44444
```


####読み込んでみる
```
import csv

with open('data.csv',  newline='') as f:
    dataReader = csv.reader(f)
    for row in dataReader:
        print(row)
```

####結果です
```text:実行結果
['1','11','111','1111','11111']
['2','22','222','2222','22222']
['3','33','333','3333','33333']
['4','44','444','4444','44444']
```

##公式ページの解説
[14.1. csv — CSV ファイルの読み書き](http://docs.python.jp/3.3/library/csv.html)

一応解説があります。newlineって何なんでしょ？

> 与えられた csvfile 内の行を反復処理するような reader オブジェクトを返します。 csvfile はイテレータ(iterator)プロトコルをサポートし、 __next__() メソッドが呼ばれた際に常に文字列を返すような任意のオブジェクトにすることができます — ファイルオブジェクトでもリストでも構いません。 csvfile がファイルオブジェクトの場合、 newline='' として開くべきです。

えー、つまりファイルを開くときにはこのnewline=''を書いてねってことだと思われます。
じゃあそれ以外の時は？という疑問にたどり着きますね。
例えばファイルではない形式で、csvが来た時とか。
すみません、今はわかんないので、また調べなおして出直します。。。。

ということで、CSVを読み込む編でした。
JavaScriptで内部関数(名前空間に公開したくない関数)を用いる方法（とっても大事なクイズだよ！）

以下のコードを実行すると test2 関数の方が速いんですけど、みなさんこの理由わかりますか？
両方とも、add、sub という外部に公開したくない内部関数を定義する方法です。

```
31
31
test1: 6.410ms
test2: 3.527ms
```

```js
const COUNT = 1000000

function test1(x, y) {
    function add(a, b) {
        return a + b
    }
    function sub(a, b) {
        return a - b
    }
    return add(x, 11) + sub(y, 22)
}

var test2 = (function () {
    function add(a, b) {
        return a + b
    }
    function sub(a, b) {
        return a - b
    }
    return function(x, y) {
        return add(x, 11) + sub(y, 22)
    }
}());

console.log(test1(10, 32))
console.log(test2(10, 32))

console.time('test1')
for (let i=0; i<COUNT; i++ ) test1(10, 32)
console.timeEnd('test1')
console.time('test2')
for (let i=0; i<COUNT; i++ ) test2(10, 32)
console.timeEnd('test2')
```

上記はブラウザで動作させるプログラムを作る場合の名前空間汚染を避ける手順ですが、Node.js の場合は

```js:test3.js
function add(a, b) {
    return a + b
}
function sub(a, b) {
    return a - b
}
module.exports = function(x, y) {
    return add(x, 11) + sub(y, 22)
}
```

としておいて

```js:main.js
const COUNT = 1000000
var test3 = require('./test3')
console.log(test3(10, 32))
console.time('test3')
for (let i=0; i<COUNT; i++ ) test3(10, 32)
console.timeEnd('test3')
//console.log(add(111,222)) // ← エラーになります。
```

でOKなので楽なんですね。
AVX512で累積和を求める

累積和とは
[1, 2, 3, 4, 5, 6]となる配列が与えられたときに
[1, 3, 6, 10, 15, 21]となる配列のことである。

これを普通に書くとこうなる。

```c++
int loop_num = 16000000;
taeget.p[0] = dest.p[0];
for (auto j = 1; j < loop_num; ++j) {
    taeget.p[j] = taeget.p[j] + dest.p[j - 1];
}
```

さて、
$[a_0, a_1, a_2, a_3, \dots]$を1つ右にずらして足し合わせると
$[a_0, a_0+a_1, a_1+a_2, a_2+a_3, \dots]$となる。
この結果を2つずらして足し合わせると
$[a_0, a_0+a_1, a_0+a_1+a_2, a_0+a_1+a_2+a_3, \dots]$となる。
以降、$2^n$ずつずらして足し合わせるを繰り替えすと累積和が求まる。
この考えでAVX512のコードを書くとこうなる。

```c++
int loop_num = 1000000;
struct alignas(64) Int2 {
    union {
	u32 p[16 * loop_num];
	__m512i m[loop_num];
    };
};
Int2 a; // 初期化のコードは各自追加してください
__m512i mz = a.m[0];
mz = _mm512_xor_epi32(mz, mz); // 0にする
__m512i in = _mm512_add_epi32(a.m[0], _mm512_alignr_epi32(a.m[0], mz, 16 - 1));
in = _mm512_add_epi32(in, _mm512_alignr_epi32(in, mz, 16 - 2));
in = _mm512_add_epi32(in, _mm512_alignr_epi32(in, mz, 16 - 4));
in = _mm512_add_epi32(in, _mm512_alignr_epi32(in, mz, 16 - 8));
a.m[0] = in;
__m512i sum = _mm512_set1_epi32(a.p[15]); // 最後の値を次の累積和にブロードキャストして加える
for (auto j = 1; j < loop_num; ++j) {
	in = _mm512_add_epi32(a.m[j], _mm512_alignr_epi32(a.m[j], mz, 16 - 1));
	in = _mm512_add_epi32(in, _mm512_alignr_epi32(in, mz, 16 - 2));
	in = _mm512_add_epi32(in, _mm512_alignr_epi32(in, mz, 16 - 4));
	in = _mm512_add_epi32(in, _mm512_alignr_epi32(in, mz, 16 - 8));
	in = _mm512_add_epi32(in, sum);
	a.m[j] = in;
	sum = _mm512_set1_epi32(a.p[(j << 4) + 15]); // 最後の値を次の累積和にブロードキャストして加える
}
std::cout << YY.p[16 * loop_num - 1] << std::endl;
```

累積和をとるu32の数と時間のベンチはこんなもの。
1600万
通常コード： 16ms
AVX512コード： 14ms

1億6000万
通常コード： 145ms
AVX512コード： 105ms

大量にやればそれなりに効果はある。
Server Side SwiftをトンネルさせてIoTデバイスのデータをFastsensingでモニタリング #love_swift


特にSwiftでやる必要もないんですけど、 Swift愛好会に来てるのでServer Side Swiftで実装してみます。

## やりたいこと

```
デバイス(Nefry BT) -----> Fastsensing
```

という形でデバイスデータをBIツールになげてリアルタイム可視化です。

![](https://i.gyazo.com/bc01ab6e529dea70203ba8fa4fb52561.png)

ただ、Fastsensing側のAPI側のレスポンスが怪しく、Arduinoのライブラリが途中で死んでしまう問題がありました苦笑。

ということで

```
デバイス(Nefry BT) ---server side swift--> Fastsensing
```

こんな感じでトンネルさせるサーバーを用意してみます。


## Swift側

`/fast/値`の形でHTTPリクエストを受け付けて、来た値をFastSensingのAPI(f-io.net)に対してHTTPリクエストする処理です。

```main.swift
・
(省略)
・
・

drop.get("fast", ":id") { req in
    guard let id = req.parameters["id"]?.int else {
        throw Abort.badRequest
    }
    print(id)
    
    var json = JSON()
    try json.set("hello", id)

    let res = try drop.client.get("http://f-io.net/d1/デバイスID?チャンネル名=\(id)")
    print(res)

    return json
}

・
(省略)
・
・
```

## デバイス側

```fast.ino
#include <WiFiClientSecure.h> // HTTPS通信のために必要

String TARGET_HOST = "xxxxxxxxxx"; //Swiftでたてたサーバー

int analog;

void setup() {
  Serial.begin(115200);
}

void loop() {
  analog = analogRead(A1);
  String trainDelayJson = getTrainDelayJson(analog);   // JSONを取得する
  Serial.print(trainDelayJson);
  delay(1000);
}

String getTrainDelayJson(int sendData) {
  WiFiClientSecure client; // 変数を宣言

  // サーバーにHTTPSのデフォルトポート（443）でアクセスしてみる
  if ( !client.connect(TARGET_HOST.c_str(), 443) ) {
    Serial.println("接続失敗");
    return "";
  }
  
  Serial.print("data: ");
  Serial.println(sendData);
  client.print(String("GET /fast/"+(String)sendData+" HTTP/1.1\r\n") +
               "Content-type: application/json \r\n" +
               "Host: "+TARGET_HOST.c_str()+"\r\n" +
               "Connection: close\r\n\r\n"); // HTTP-GETのリクエストメッセージを書く

  // レスポンスが来るまでちょっと待つ
  delay(500);

  // HTTP-GETのレスポンスを保存しておく変数
  String response = "";

  // レスポンスを変数に格納する
  while (client.available()) {
    response += client.readStringUntil('\r');
  }

  Serial.println("接続成功");
  Serial.println(response);

  return response;
}
```

これで起動すると

デバイス -> Server Side Swift -> Fastsensingという流れでモニタリングができました。

動いてる様子はこんな感じ。

![](https://i.gyazo.com/9bf1d1d84883ab631ade0a979ae53906.gif)
「プログラマの数学」を読んで、指数法則について分かったこと

# 導入

先日、Amzonでベストセラーになっていた、「プログラマの数学」という本を購入しました

Twitterのタイムラインに頻繁に流れてきていたので、前々から気になっていたのですが、なかなかタイミングが合わずやっと購入した次第です

その中で個人的に目から鱗であった指数法則に関する内容を忘れないようにメモしていきたいと思います

余談ですが、筆者はバリバリの文系人間で、数学は高校１年生の時についていけなくなりました

# 指数法則とは

２の２乗など、中学校で学ぶアレ

# 目から鱗だった内容

0乗と-n乗に関する記述

## 0乗

0乗すると1になる

## -n乗

例えば2の-2乗は4分の１となる

## 何が目から鱗であったか

今まで読んできた参考書などでは、0乗すると1になり、-n乗は分数となることは書かれていたものの、何故そうなるかまでは書かれていなかった

「プログラマの数学」の中では、その「何故」が書かれていた

### 法則を考える

個人的に最もポピュラーであると考える、2の乗数を例に書いていく

2の1乗 = 2
2の2乗 = 2 x 2 = 4
2の3乗 = 2 x 2 x 2 = 8

このように２のn乗は2をn回かけることで求めることが出来る

ここで発想を変えて考えてみる

2の3乗 = 2 x 2 x 2 = 8
2の2乗 = 2 x 2 = 4
2の1乗 = 2

2のn乗は、nが1小さくなるにつれて、値が2分の1となっていく

2の０乗も同じように、2の１乗を2分の１したものと考えると、2の１乗は２であるため、その2分の１は1となる

さらに2の-１乗は2の０乗である１を2分の１した値となり、2分の１となる

これこそが今までの私にはなかった発想である

# まとめ

どこか公式的に捉えていたものを、論理的に理解することが出来、非常に晴れやかな気持ちになった

まだ全て読み終えたわけではないので、引き続き読んでいきたいと思う
position: relative;をかけているtdがfirefoxやIEで罫線が切れてしまう場合の対応方法

#tdにposition: relative;をかけていると、firefoxやIEで罫線が切れてしまう
テーブルをcssスタイリングしていてFFやIEで罫線がどうしても切れてしまう場合がある。その場合は、`background-clip: padding-box;`を指定することで解消できる。

参考：MDN：background-clip
https://developer.mozilla.org/ja/docs/Web/CSS/background-clip

サンプル（上：chrome表示、下：FF表示）
<img src="https://qiita-image-store.s3.amazonaws.com/0/165665/c8d1cadc-19bc-c050-ff52-a8452306eef0.png" width=50%>
<img src="https://qiita-image-store.s3.amazonaws.com/0/165665/e629cd2b-457d-3d4f-2328-c2f06bedbe51.png" width=50%>
macOSでOpenGLプログラミング (4-3. 基本のライティングを実装する（平行光源の拡散光に光の色を設定する）)

[macOSでOpenGLプログラミングの目次に戻る](https://qiita.com/sazameki/items/d060f20f621c658046d9)


# はじめに

今回は、平行光源の光に、光の色を足してみましょう。

**あらゆる光源には、光の色があります**。現実世界では、完全な白い光というのはほとんど見ることはありません。蛍光灯であれば青っぽい光、電灯であればオレンジっぽい光の色があり、それに照らされたオブジェクトは、その光の影響を受けて、やはり青っぽい色やオレンジっぽい色で見えることになります。


# 1. 頂点シェーダにコードを追加する

平行光源の光の色を表す変数として、uniform 変数として、`diffuse_color` 変数を頂点シェーダに追加します。「diffuse」は「拡散光」を表す英単語です。そして out 変数である `color` 変数の値を計算する時に、頂点の色を表す `vertex_color` にこの変数の値を掛け算することで、頂点から拡散される光の色をフィルタリングする効果が得られるのです。

```glsl:myshader.vsh
#version 410

layout (location=0) in vec3 vertex_pos;
layout (location=1) in vec3 vertex_normal;
layout (location=2) in vec4 vertex_color;

uniform vec3 light_dir;
uniform mat4 pvm_mat;
uniform mat4 model_mat;
uniform vec4 diffuse_color;

out vec4 color;

void main()
{
    gl_Position = vec4(vertex_pos, 1.0) * pvm_mat;

    vec3 normal = normalize((vec4(vertex_normal, 0.0) * model_mat).xyz);
    float power = dot(normal, -normalize(light_dir));
    power = clamp(power, 0.0, 1.0);

    color = vertex_color * diffuse_color * power;
}
```

たとえば (1, 1, 1) の光の色を設定するということは、RGBすべての光の要素をそのままオブジェクトの色に反映させるということです。それに対して、(1.0, 0.5, 0.5) の光の色を設定したとすると、Rの光の要素はそのままオブジェクトの色に反映させますが、GとBの光の要素は半分の強さでオブジェクト表面で拡散するということになります。このフィルタリング効果は、頂点の色に光の色を掛け算することで得られます。


# 2. 描画コードを追加する

頂点シェーダに追加した `diffuse_color` 変数の値をセットするためのコードを、Render() 関数に追加します。ここでは、ほんのり黄色いライトを想定して、RGBA の成分が (1.0, 0.9, 0.7, 1.0) の光が平行光源として当たっていることにしてみます。

```cpp:Game.cpp（一部）
void Game::Render()
{
    ...
    program->SetUniform("diffuse_color", GLKVector4Make(1.0f, 0.9f, 0.7f, 1.0f));
    glDrawElements(GL_TRIANGLES, (GLsizei)data.size(), GL_UNSIGNED_SHORT, (void *)0);
}
```

それでは、実行してみましょう。比較のために、光の色を足す前の実行結果を見ておきます。次のように、白いウサギがレンダリングされています。

　<img width="320" src="https://qiita-image-store.s3.amazonaws.com/0/166309/e47cc638-154d-d6be-f6db-ee0314c05e62.png">

ほんのり黄色いライトを設定したものが、次の実行結果です。ライトの色を受けて、ウサギの色が黄色くレンダリングされるようになったことが分かります。

　<img width="320" src="https://qiita-image-store.s3.amazonaws.com/0/166309/64a758fe-f0cb-ae39-6c87-96b7b53e29e0.png">

　　ここまでのプロジェクト：[MyGLGame_step4-3.zip](http://sazameki.jp/temp/MyGLGame_step4-3.zip)


# 3. まとめ

今回は、平行光源の光の色を設定できるようにしました。

冒頭でも書きましたが、**現実世界では、完全な白・完全な黒というものを目にすることはまずありません**。レンダリングしようとしている空間の光源を考えた時に、それが太陽なのか、蛍光灯なのか、電灯なのかということをしっかりと分析し、それを光源の色に反映させてやることがとても重要です。

----
[macOSでOpenGLプログラミングの目次に戻る](https://qiita.com/sazameki/items/d060f20f621c658046d9)