OmniAICreator/Qiita-1.07M huggingface dataset:
Lavie Direct HZ に Ubuntu をインストールする

# はじめに

![April 8, 2018 12814 PM GMT+0900.png](https://qiita-image-store.s3.amazonaws.com/0/104970/032b468f-59e7-01b4-bff2-56a0d8f3f966.png)


[Lavie Direct HZ](http://nec-lavie.jp/shop/note/lavie/hz/) を購入しました。
800gの超軽量、スリムベゼル（狭額縁）の採用で13インチモニターでもコンパクトなボディなので、なかなかよさげです。

これまでは、Vaio Pro 11 を使っていました。
両者の重量はあまり変わりませんが 、Vaio Pro 11は剛性が小さく簡単にたわむところがイマイチでした。Lavie Direct HZは結構剛性があります。

私はUbuntuを普段使っています。今回もプリインストールWindowsを削除してUbuntu16.04をインストールします。

いくつかハマった点があったのでログを残します。

# [Errno 5] - Input/output error

こんな感じのエラーが出て、何度やってもUbuntuがインストールができない現象に見舞われました。
あまり参考になりませんが、インストールディスクに用いていたUSBメモリに不良セクタがあったみたいです。

別のUSBメモリを用いると解決しました。

# Wifiドライバが見つからない
上記でUbuntuは無事インストールでできたのですが、Wifi ドライバーを自動的に見つけてくれませんでした。
この[StackOverflow のページ](https://askubuntu.com/questions/235279/my-wifi-adapter-is-not-working-at-all-how-to-troubleshoot)
を参考にして、まずは使われているWifiのハードウェアを特定します。
```
lspci
```
を実行すると Realtek Semiconductor Co., Ltd. Device b822
た接続されていることがわかりました。これが Wireless ネットワークデバイスです。

このドライバはUbuntu16.04には含まれていないので、各自でインストールを行う必要があります。
この[ページ](https://ask.fedoraproject.org/en/question/113339/wireless-realtek-rlt8822be-not-working/)を参考にして、コンパイル・インストールしました。

ドライバは [https://github.com/synthtc/rtlwifi-next](https://github.com/synthtc/rtlwifi-next)にあるので、こちらからダウンロードします。

適当なフォルダに解凍して、
```
make
sudo make install
sudo modprobe rtl8822be
```
したあと再起動することで、Wifi アダプタを有効にできました。


# Alt + tab の挙動の修正

これはUbuntuの問題かもしれませんが、
Alt + tab での挙動が不自然でした。
以下のページを参考にすると修正できました。
https://askubuntu.com/questions/818449/ubuntu-16-04-alt-tab-not-working-properly


function key が効かなくなった
https://askubuntu.com/questions/866437/function-keys-do-not-work-brightness-sound-ubuntu-16-04
Jetson TX1にlibrealsenseをインストールしてみた


## 環境
- Jetson TX1
- JetPack 3.2
- D435
- librealsense v2.10.2

## インストール
```
$ sudo apt install libgtk-3-dev
$ git clone https://github.com/jetsonhacks/installLibrealsenseTX2.git
$ cd installLibrealsenseTX2
$ curl https://gist.githubusercontent.com/jallum/85439ded2c9a78c8948fdceac179d695/raw/56cf13cb80b8c5845b1d11e9707b2e0fccf375fb/1446.patch -o patches/1446.patch
```

``` installLibrealsense.sh
...
# インストール先を書き換える(任意)。
cd $HOME/Projects
# Tagを指定する。
git checkout v2.10.2  
...
# コメントアウトする。
# patch -p1 -i $INSTALL_DIR/patches/uvc-v4l2.patc 
# 下記を追加する。
patch -p1 -i $INSTALL_DIR/patches/1446.patch
...
# 下記のように引数を修正する。
cmake -DBUILD_EXAMPLES=true ../
```

```
$ ./installLibrealsense.sh
```
## 動作確認
$ realsense-viewer

![screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/109483/6a84c6cc-c62c-8032-d758-3c4b804ac337.png)
[問題記録]画像をアップロードする際に元の画像を削除する

ユーザーのプロフィール画像をアップロードするロジックです。

##1.問題点：
画像をアップロード、または更新する際に、元の画像はストレージに残ってしまう。

```php
if($request->file('avatar')){
    
            $path=$request->file('avatar')->storePublicly($user->id);
            $user->avatar=asset('/storage').'/'.$path;
        }

        $user->save();
```



##２.要件：
新しい画像をアップロードする際に、元の画像を削除する

```php
if($request->file('avatar')){
            $files = Storage::allfiles($user->id);
            Storage::delete($files);
            $path=$request->file('avatar')->storePublicly($user->id);
            $user->avatar=asset('/storage').'/'.$path;

        }
        $user->save();
```


参考資料：[Laravel5.4ファイルストレージ](https://readouble.com/laravel/5.4/ja/filesystem.html)


##APPENDIX：

問題：４０４で画像はアクセスできない！！

解決策：

1.シンボリックリンクを張ること。

```
php artisan storage:link
```
publicディスクは一般公開へのアクセスを許すファイルを意味しています。デフォルトのpublicディスクは、localドライバを使用しており、storage/app/public下に存在しているファイルです。Webからのアクセスを許すには、public/storageからstorage/app/publicへシンボリックリンクを張る必要があります。この手法により、公開ファイルを一つのディレクトリへ留め、Envoyerのようなリリース時のダウンタイムが起きない開発システムを使っている場合、各リリース間でファイルを簡単に共有できます。

2.storageの訪問権限

```
# chmod -R 707 bootstrap/cache
# chmod -R 707 storage
```
3.画像のurlは間違っているのか?
絶対パス・相対パスをチェック。
データベースの中のデータを取り出してみる。
Rubyでseleniumを使おうとして導入でつまずいた件


# はじめに

この記事は導入時の簡単なトラブルシュートのメモになります。

つい先日、社会人デビューし配属が決まりました。
そこで`selenium`を使いそうだなぁという勝手なイメージと、
そう言えば名前は知ってるけど使ったことないなぁということで触ってみようと思ったのが発端です。

そこで、

- [WebのUIテスト自動化 - Seleniumを使ってみる](https://qiita.com/edo_m18/items/ba7d8a95818e9c0552d9)
- [Selenium 入門](https://qiita.com/kkakizaki/items/5a0e6f753193f2a1514f)

このあたりの記事を参考に動かしてみるぞ〜！！と意気込んでいたところ、
requireの時点でエラーが出てしまったため今後の自分のためにメモを残すことにしました。

# 何が起きたん？
## selenium-webdriver
まず`selenium-webdriver`のインストール時に、

```bash
gem install selenium-webdriver
```

ではパーミッションエラーが出てしまいました。
こちらは単純に、

```bash
sudo gem install selenium-webdriver
```

で解決できました。


## chromedriver

次に、chromeで動かそうと考えていたのでchromedriverのインストールを試みました。

とりあえず、[ここ](https://sites.google.com/a/chromium.org/chromedriver/downloads)からダウンロードしたchromedriverを実行しながらプログラムを動かしてみたところ...

```bash
Unable to find chromedriver. Please download the server from http://chromedriver.storage.googleapis.com/index.html and place it somewhere on your PATH. More info at https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver. (Selenium::WebDriver::Error::WebDriverError)
```

***ダメでした。***
(最終的にここからダウンロードする必要はありませんでした。)

そこでよくよく調べてみると、`/usr/sbin/`にファイルを入れろ、といった記事をちらほら見つけました。

なるほどガッテンショウチ！と意気揚々と手を動かしたのですが、
[このページ](https://apple.srad.jp/story/15/09/30/1529213/)曰く、

> 保護対象となるのは/usrおよび/bin、/sbin、/System、/Applications/Utilities以下のディレクトリ

> これらのディレクトリにはAppleのコード署名がされたシステムプロセスからしか書き込みが行えない

らしく、`cp`や`mv`ではファイルを移せないわけです(GUIでの移動ももちろん不可)。

リカバリーモードでOSを起動してcsrutilコマンドで設定することで、このrootlessという保護機能を無効化することもできるらしいのですが、そこまで手間を掛けたくない上に、なんか気持ち悪いのでさらに調べました。


すると、

```bash
brew install chromedriver
```

***あ、`Homebrew`にあるのね。***

# おわりに

はい、Homebrewからインストールすることで一瞬で解決してしまいました。

自分は体験したので次回以降はしばらく印象に残っているので大丈夫だと思いますが、
調べていても情報が少なく案外すぐには解決せず、この段階で初心者は折れかねないと感じたのでこのようにメモにしました。

動作確認は、

```ruby

require 'selenium-webdriver'

driver = Selenium::WebDriver.for :chrome #使用するブラウザを選択
driver.navigate.to "http://www.google.com" #URL指定
puts driver.title #ページタイトルを出力

element = driver.find_element(:name, 'description') #セレクタ指定
puts element.attribute('content') #コンソールに出力

driver.quit #ブラウザを閉じて終了

```


こんな感じのものを動かして問題なく終了すれば大丈夫です。
OctoberCMSプラグイン作成：コンポーネントからPage Not Found (404)を返す

OctoberCMSでは今のところ残念なことにLaravelの`abort(404)`が使えません。
404エラーページを表示せずに500エラーとして処理されてしまいます。

フロントエンドのページで404エラーページを表示するには下記の方法が考えられます。
1. `/404` へリダイレクトさせる
2. コンポーネントで404のレスポンスを返させる
3. [ページのPHPセクションで404のレスポンスを返させる](https://qiita.com/pikanji/items/0f3bde360ba03a07aa4c)

ここでは2について説明します。

フロントエンドでコンポーネントから404エラーページを表示するにはコンポーネントクラスの`onRun()`などで下記のようにします。

```php
public function onRun()
{
    if ($this->error) {
        return Response::make($this->controller->run('404'), 404);
    }
}
```

コンポーネントクラスの他の自作メソッドは純粋にデータを返すだけなのでエラーページの表示にはなりません。
上記の実装例の場合、どこかで、`$this->error`フラグを`true`にすることで、テーマに実装された404のページが表示されるようになります。

## 参考
[Building Components: Halting with a response](https://octobercms.com/docs/plugin/components#page-cycle-response)
AWS RDSのログを監視する

#AWS RDSのログを監視する

RDSログを監視する方法がAWSにないのでシェルを定期的に動かして監視するバッチを作る。

##1.AWS上のログをローカルにコピーする
```shell:sample.sh
#! /bin/bash

IFS=','
MAILING_LIST=(
 example@xxx.co.jp
 sample@xxx.com
)

date=`date +"%Y-%m-%d"`

current_hour=`date --date "9 hours ago" "+%k"`
current_file_name_hour=`printf "%02d" $current_hour`
current_file_name="error/postgresql.log.$date-$current_file_name_hour"
local_copy_file="current_postgresql.log"
region="ap-northeast-1"
instance_name=""

aws rds download-db-log-file-portion \
  --region $region \
  --db-instance-identifier $instance_name \
  --no-paginate \
  --output text \
  --log-file-name $current_file_name > $local_copy_file
```

##2.監視してメール出力する
ログに指定文字列が記述されていたらメールを送信する
※sendmailについては割愛

```diff:sample.sh
#! /bin/bash

IFS=','
MAILING_LIST=(
 example@xxx.co.jp
 sample@xxx.com
)

date=`date +"%Y-%m-%d"`

current_hour=`date --date "9 hours ago" "+%k"`
current_file_name_hour=`printf "%02d" $current_hour`
current_file_name="error/postgresql.log.$date-$current_file_name_hour"
local_copy_file="current_postgresql.log"
region="ap-northeast-1"
instance_name=""

aws rds download-db-log-file-portion \
  --region $region \
  --db-instance-identifier $instance_name \
  --no-paginate \
  --output text \
  --log-file-name $current_file_name > $local_copy_file

+ current_log=$(cat $local_copy_file)
+
+ filter_word="ERROR"
+ mail_subject="alarm notice"
+ mail_body="mail body"
+
+ if [[ `echo $current_log|grep $filter_word` ]]; then
+   echo "Subject: $mail_subject \n\n $mail_body" | /usr/lib/sendmail + ${MAILING_LIST[*]}]}
+ fi
```

###ソースコード
https://github.com/soartec-lab/rds_log_watch/
[brew-cask] Error: undefined method `<=' for nil:NilClass

# 概要

なんかbrew-caskで一覧見ようとしたらエラーが出たので、調べてみた。

# エラーの概要

```bash
suguruoki$ brew cask list
Error: undefined method `<=' for nil:NilClass
Did you mean?  <=>
Follow the instructions here:
  https://github.com/caskroom/homebrew-cask#reporting-bugs
/usr/local/Caskroom/java7/.metadata/1.7.0_80/20160324040755.144/Casks/java7.rb:38:in `block in load'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cask.rb:23:in `instance_eval'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cask.rb:23:in `initialize'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cask_loader.rb:31:in `new'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cask_loader.rb:31:in `cask'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cask_loader.rb:67:in `cask'
/usr/local/Homebrew/Library/Homebrew/compat/hbc/cask_loader.rb:10:in `cask'
/usr/local/Caskroom/java7/.metadata/1.7.0_80/20160324040755.144/Casks/java7.rb:1:in `load'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cask_loader.rb:57:in `instance_eval'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cask_loader.rb:57:in `load'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cask_loader.rb:170:in `load'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/scopes.rb:41:in `block in installed'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/scopes.rb:31:in `map'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/scopes.rb:31:in `installed'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cli/list.rb:40:in `list_installed'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cli/list.rb:14:in `run'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb:35:in `run'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cli.rb:98:in `run_command'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cli.rb:168:in `run'
/usr/local/Homebrew/Library/Homebrew/cask/lib/hbc/cli.rb:132:in `run'
/usr/local/Homebrew/Library/Homebrew/cmd/cask.rb:8:in `cask'
/usr/local/Homebrew/Library/Homebrew/brew.rb:100:in `<main>'
```

上記を見るとなんかjava7が邪魔をしているみたい。


```bash
/usr/local/Caskroom/java7/.metadata/1.7.0_80/20160324040755.144/Casks/java7.rb:38:in `block in load'
```
この件は[GitHubのIssue](https://github.com/caskroom/homebrew-versions/pull/3914)にも投稿されており、解決済みの模様。


> Two casks have a java('6') only dependency.
argouml updated
logitech-harmony
I'll check and see if they work with java 8.

上記のようにjava6にハードコーディングで依存している部分があるため、うまくいかないっぽい。
なので、とりあえずjava7をrmコマンドで削除することで対応できる。
もしこれ消すのは危ないという方は一度フォルダごと移動して試して見ると良いかも。


```bash
ookiyuu-no-MacBook-Pro:usr suguruoki$ rm -rf /usr/local/Caskroom/java7/
ookiyuu-no-MacBook-Pro:usr suguruoki$ brew cask list
atom                                                         java                                                         xquartz
```

これでとりあえずはなんとかなった感じ。
ちなみにgitでも同じようなエラーが出る現象が確認されており、その場合もcaskに入っているgitのフォルダを削除することで対応可能。これも[GitHubのIssue](https://github.com/caskroom/homebrew-cask/issues/44173)に投稿されているので、詳しくはそちらへ。
Linuxのsendmailを使ってテーブルを監視

# 例えば、PostgreSQLコマンドの実行結果をメール送信する

```shell:sample.sh
#! /bin/bash

PG_USER=""
PG_PASSWORD=""
PG_HOST=""
PG_PORT=""
DB_NAME=""

export PGPASSWORD=$PG_PASSWORD
IFS=','

date_now=`date +"%Y-%m-%d %k:%M:%S.%3N"`

GET_USER_SQL="
SELECT 
  id, name 
FROM 
  user;
"
GET_POST_SQL="
SELECT 
  user_id, content 
FROM 
  post;
"
    
result=`psql -U $PG_USER -h $PG_HOST -p $PG_PORT -d $DB_NAME <<_EOD
   \timing
   $GET_USER_SQL
   $GET_POST_SQL
_EOD
`

MAILING_LIST=(
  sample@ne.jp
  example@xxx.com
)
SUBJECT="Excute Result"

mail_body=`
echo
echo date_now
echo $result | sed -e '1,1d'
`
echo -e "Subject: $SUBJECT \n\n $mail_body"  | sendmail ${MAILING_LIST[*]}
```
PostgreSQLコマンドでクエリを実行する方法

# 例えば、SELECT結果を表示させるスクリプトを作る

## 1. -c オプションで実行
```shell:sample.sh
USER=""
HOST=""
PORT=""
DATABASE=""
CMD1="SELECT * FROM USER;"
CMD2="SELECT * FROM POST;"
CMD3="SELECT * FROM CONTENT;"

echo `psql -U $USER -h $HOST -p $PORT -d $DATABASE -c $CMD1`
echo `psql -U $USER -h $HOST -p $PORT -d $DATABASE -c $CMD2`
echo `psql -U $USER -h $HOST -p $PORT -d $DATABASE -c $CMD3`
```

##2. ヒアドキュメントで実行
```shell:sample.sh
USER=""
HOST=""
PORT=""
DATABASE=""
CMD1="SELECT * FROM USER;"
CMD2="SELECT * FROM POST;"
CMD3="SELECT * FROM CONTENT;"

echo ¥
psql -U $USER -h $HOST -p $PORT -d $DATABASE <<_EOD
$CMD1
$CMD2
$CMD3
_EOD
```

##3.パイプラインで実行
```shell:sample.sh
USER=""
HOST=""
PORT=""
DATABASE=""
CMD1="SELECT * FROM USER;"
CMD2="SELECT * FROM POST;"
CMD3="SELECT * FROM CONTENT;"

echo $CMD1 | psql -U $USER -h $HOST -p $PORT -d $DATABASE
echo $CMD2 | psql -U $USER -h $HOST -p $PORT -d $DATABASE
echo $CMD3 | psql -U $USER -h $HOST -p $PORT -d $DATABASE
```
Python3とPyQt5のインストール

PyQt5をインストールしようと思ったらWebページが変わっていたりでいろいろ躓いたのでまとめてみた。2018年4月現在の内容なので、最新をチェックする必要あり。

大まかにすることは以下の通り。
まとめてみると結構簡単だけれど、正解にたどり着くまで結構時間がかかってしまった。
1. Qtのインストール
2. Pythonのインストール
3. SIPのインストール
4. PyQt5のインストール
5. インストールの確認

インストール環境は以下。
Windows 10 Home

# Qt5のインストール
これが一番の難関。
まずは以下にアクセス。
https://www.qt.io/download
以前の記事を見て回ると64bit版をダウンロードすることになっているが、Webページの様式が変わっているようでたどり着けない。
仕方ないので「Open Source」の「Get open source」からQt Online Installer for Windowsをダウンロードする。インストーラーの名前が`qt-unified-windows-x86-3.0.2-online.exe`だけれど今の所動作しているのでおそらくオッケー。
普通にインストールしてるとストレージをアホほど使うので、環境に合わせてできるだけ不要なパッケージを減らす。

# Pythonのインストール
いろんなところを参考にインストールする。
https://qiita.com/Keiji2827/items/45f11f1fced915cc651c
現行の最新バージョンは`Python-3.6.5`。

# SIPのインストール
Windowsのコマンドプロンプトから以下を実行。

```
>pip install SIP
Collecting SIP
  Using cached sip-4.19.8-cp36-none-win_amd64.whl
Installing collected packages: SIP
Successfully installed SIP-4.19.8
```

SIPはC++プログラムをpythonで利用できるようにするものらしい。
PyQt5はSIPを使ってQtをPythonから使えるようにするとのこと。

# PyQt5のインストール
SIPと同様にWindowsコマンドプロンプトから以下を実行。

```
>pip3 install PyQt5
Collecting PyQt5
  Using cached PyQt5-5.10.1-5.10.1-cp35.cp36.cp37.cp38-none-win_amd64.whl
Requirement already satisfied: sip<4.20,>=4.19.4 in h:\python\lib\site-packages (from PyQt5)
Installing collected packages: PyQt5
Successfully installed PyQt5-5.10.1
```
# インストールの確認
適当なサンプル集から引っ張ってきて動作できればオッケー。
開発環境は好きなように。
~~説明になってない。。。~~
画像認識の手法を自分で考えてみた。

## 概要
　自分で何かアルゴリズムを作りたいという一心で画像認識の手法を自分で考えてみた。考え付いたのはかなりシンプルな方法でどうせ誰かが提唱しているでしょう。調べるのめんどくさいんでどなたか知っている人いらっしゃったら教えて下さい。

　教師データが存在している状況を仮定する。得られた画像を認識する際、教師データとのアダマール積を取る。同じラベルであるなら同じ要素の数値が似ている確率も大きくなるので、得られる行列の値も大きくなるのではないかという考えから実験してみた。

## アルゴリズム
1. 行列のノルム`l`を要素に持つベクトルを**L**とする.
2. 判定したい画像`x`と教師画像`t_i`のアダマール積を取る.**（ここが肝）**
3. 得られた行列のノルム`l_i`を計算する.
4. **L**の中のラベルに対応する要素に`l_i`を加算代入する.
5. 1~4を繰り返す. (教師画像: t_1, t_2, ..., t_n)

## 実装

当然のようにmnistで精度を計算する。

```python
import numpy as np
from time import sleep
from tqdm import tqdm
from keras.datasets import mnist
from keras.utils import to_categorical

def load_mnist():
    (x_train, y_train), (x_test, y_test) = mnist.load_data()

    x_train = x_train.reshape(-1, 28, 28, 1).astype('float32') / 255.
    x_test = x_test.reshape(-1, 28, 28, 1).astype('float32') / 255.
    y_train = to_categorical(y_train.astype('float32'))
    y_test = to_categorical(y_test.astype('float32'))
    return (x_train, y_train), (x_test, y_test)


(x_train, y_train), (x_test, y_test) = load_mnist()
iteration = 1000
cnt = 0
prediction = [0.0 for i in range(10)]

acc = []
while(iteration < 100000):
    for i, image in enumerate(tqdm(x_train[0:100])):
        for j in range(iteration):
            rnd = np.random.randint(len(x_test))
            image = np.reshape(image, (28, 28))
            t_image = np.reshape(x_test[rnd], (28, 28))
            image = np.array(image)
            t_image =np.array(t_image)
            prediction[np.argmax(y_test[rnd])] += np.linalg.norm(image * t_image)
        if np.argmax(y_train[i]) == np.argmax(prediction):
            cnt += 1

        prediction = [0.0 for i in range(10)]

    print('iteration:', iteration, '\t', 'acc:', cnt / len(x_train[0:100]))
    iteration += 1000
    cnt = 0
    acc.append(cnt / len(x_train[0:100]))

print(acc)
```

## 結果

![result.png](https://qiita-image-store.s3.amazonaws.com/0/221435/f020e4d9-4fa3-478f-9b20-c1a013b595cb.png)


accu=0.75程度（精度：75%）という結果で理論が通ったのはわかった。

やっぱり黙ってcnnしよう。。。
error 追跡

### window.onerrorを使う。
```js
window.onerror=fn.trace(sender)
```
### 全部
```html
<button onclick="a()">a</button><pre></pre> <!--a() is born the error-->
```
```js
let fn={}
fn.trace=function(sender=()=>{}){return function (msg, url, lineNo, columnNo, error){
//https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror.html 
  let o={msg:msg,url:url,lineNo:lineNo,columnNo:columnNo,error:error}
  sender(o);
  return false;
}}
;
let sender=(d)=>{document.querySelector('pre').textContent=JSON.stringify(d,null,2)}
window.onerror=fn.trace(sender)
```

### 本格的なものはsentryというサービスがある。
https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror.html

### 追記
Error.prototype.stackは非標準だがデバック環境では事実上標準化されている。
よって、error.stackを出力すれば、デバッガが出力するトレースに近いものが出る。

```js
let o={....,error:{message:error.message,stack:error.stack}}
```
Android SDK のインストール(zip)

1. https://developer.android.com/studio/index.html?hl=ja ここから sdk の zip をダウンロード(sdk-tools-[OS 名]-[バージョン].zip
2. 適当なディレクトリに展開
	zip を展開した ANDROID_HOME ディレクトリになるのでそれっぽい名称にしておく(ここでは /opt/android-sdk で展開したことに)
3. 色々ツールインストール

	```
	$ cd /opt/android-sdk/tools; ./android update sdk
	-> 規約への同意が必要なので途中 2 会ほど y Enter
	```

4. PATH 周りの設定
	以下の通りでいいと思うんだけど、、、

	```
	echo 'export ANDROID_HOME=/opt/android-sdk' >> ~/.bashrc
	echo 'export PATH="${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${PATH}"' >> ~/.bashrc
	```
kube-aws v0.9.9が突然動かなくなって焦った件

# 概要
kube-awsでAWS上にKubernetes環境を構築しているが、ある日突然、`kube-aws validate`の実行が失敗するようになった。
CloudFormationのValidationが強化されたことが原因のようだが、幸いbug fixはされているため、v0.9.9にbug fixを取り込んでBuildする手順を記載する。
なお、本書はkube-aws v0.9.9のbug fix版がリリースされるまで、もしくはv0.9.10がリリースされるまで有効とする。

# 問題の発端
Kubernetesクラスターを構築しようとしたところ、`kube-aws validate`に失敗。

```
$ kube-aws validate --s3-uri=s3://mybucket
Validating UserData and stack template...
Error: failed to validate node pool #0: create volume dry-run request failed: InvalidParameterCombination: The parameter iops is not supported for gp2 volumes.
    status code: 400, request id: xxxxx
```

調べて見ると[既知の問題](https://github.com/kubernetes-incubator/kube-aws/issues/1170)らしい。
投稿者は1ヶ月くらい前から発生しているらしいが、私の環境では2週間くらい前には発生していなかった。
リージョンの違いだろうか。

対応手順が書いてあったため、手順を本書に記載する。

# 対応手順
kube-aws v0.9.9にbug fixと取り込んでbuildする。

- GOPATHを設定し、v0.9.9のkube-awsをcloneする（GOPATHは任意のディレクトリで問題ない）

```
$ export GOPATH=$HOME/go
$ git clone --branch v0.9.9 https://github.com/kubernetes-incubator/kube-aws.git $GOPATH/src/github.com/kubernetes-incubator/kube-aws
$ cd $HOME/go/src/github.com/kubernetes-incubator/kube-aws
```

- bug fixのコミットを取得する

```
$ git cherry-pick 5e15ac9059a95c051600c378cec204621c3a722f
```

- kube-awsをbuildする

```
$ make build
```

- buildで作成したバイナリを配置する（Macの場合）

```
$ cp bin/kube-aws /usr/local/bin
```

この対応の後、無事に`kube-aws validate`を実行できた。

# 最後に
AWS側の変更により突然動かなくなるのはなかなかつらいところ。
今回は幸いbug fix版のコードを見つけることができたが、次回は見つからない可能性もある。
緊急時に手詰まりになることを避けるため、暫定対応として自分でbug fixしてbuildする手順は確立しておいた方がいいかもしれない。
Node.jsでMattermost Botを作成する

[Redmine](http://www.redmine.org/)とChatOpsとで新しいシステム運用の形を模索している8amjpです。
今回は、チャットツール[Mattermost](https://about.mattermost.com/)での発言に自動応答する簡単なプログラム、いわゆるBotをNode.jsで作成してみます。
今回作成するのは、誰かが「寝てる？」と発言したら、「寝てないよ！」と返事するだけのBotです。

## Node.js

```app.js
const http = require('http');
const server = http.createServer();　
server.on('request', (req, res) => {
  const responseBody = {"text": "寝てないよ！"}
  res.setHeader('Content-Type', 'application/json');
  res.write(JSON.stringify(responseBody));
  res.end();
})
server.listen(3000);
```

Node.js側で用意するソースはたったこれだけです。
出来上がったら、`node app.js`で起動してください。
3000番ポートでリクエストを待ち受け続け、リクエストがあったら「寝てないよ！」というレスポンスをJSON形式で返します。ほんとにたったこれだけ。
(ちなみに、終了させるときは`Ctrl + C`で。)

## Mattermostの設定

続いてMattermost側の設定です。

### Integrations(統合機能)

外部システムとの連携は、「Integrations(統合機能)」の「Outgoing Webhook (外向きのウェブフック)」で設定します。

タイトル(Title): 特になんでもいいです。
コンテントタイプ(Content Type): `application/json`を指定します。
チャンネル(Channel): ウェブフックを作動させるチャンネルを指定します。とりあえずデフォルトで作成されている「Town Square」にします。
トリガーワード(Trigger Words): 外部のプログラムを呼び出すトリガーになるキーワードです。「寝てる？」という言葉を指定すれば、その言葉に反応します。
コールバックURL(Callback URLs): トリガーワードに反応した時にアクセスするURLを指定します。先ほど作成したNode.jsのプログラムのURL、 http://localhost:3000 を指定します。
(別のホストでプログラムを稼働させている場合は、そのホストのアドレスを指定してください)

### システムコンソール(System Console)での設定

さて、Outgoing Webhook(外向きのウェブフック)の設定は以上ですが、これだけでは動作しません。localhostへのアクセスは、セキュリティ上の理由で動作が制限されているので、システムコンソールで変更する必要があります。
(別のホストでプログラムを稼働させている場合は特に考慮する必要はありません)

#### 開発者の設定(Developer Settings)
メニューの一番下、「開発者(Developer)」を選択してください。
「信頼されていない内部接続を許可する: (Allow untrusted internal connections to:)」の項目で「localhost」と指定し、通信を許可する必要があります。
(その下に書かれている注意書きもよく読んでくださいね！)

## 完成
以上で完成です。
「Town Square」チャンネルで「寝てる？」と聞いてみましょう。「寝てないよ！」という発言が帰ってきたら見事成功です。おめでとうございます。
なお、発言者はウェブフックの作成者と同じアカウントになり、名前の横に「BOT」と表示されます。

……これだけでは何の役にも立たないBotですが、これを応用すれば、発言に応じて何らかの処理を走らせ、その結果を返すBotなんかも作成できます。これこそがChatOpsの真髄ですねー。
Appium をインストールする(docker)

Appium で端末操作を自動化するのにコードを書きたい
かつ、ホスト(Windows) にはあんまり色々いれたくないので、Hyper-V 上の Linux 上の Docker コンテナに Appium をインストール

# インストールする環境
- OS: CentOS 7.4.1708(Docker コンテナ)

# 手順
1. https://nodejs.org/ja/download/ から Linux 版バイナリをダウンロード
2. ダウンロードしたファイルを適当な場所に展開(ここでは /opt)
3. リンク作る(やんなくてもいい)

	```
	# cd /opt; ln -s node-v8.11.1-linux-x64 node
	```
4. Node 用のユーザを作る **(重要)**
	root ユーザで npm 実行したら permission denied でパッケージがインストールできない(Node のポリシー?)。ということで、Node 用のユーザとグループを作成し、Node パッケージのインストールはこのユーザで行う

	```
	# groupadd node
	# useradd node -g node
	```
5. g++ インストール
	Appium のインストール中に heapdump のリビルドをするらしく g++ が必要になるので

	```
	# yum install gcc-c++
	```
6. Path を通す & 権限変更

	```
	# echo 'export PATH="/opt/node/bin:${PATH}"' >> /home/node/.bashrc
	# chown -R node.node /opt/node*
	```

6. Appium & wd インストール

	```
	# su - node -c 'npm install -g appium
	# su - node -c 'npm install -g wd
	```



# 最後に
ホスト上に突っ込む場合はこんなことせずに済むと思うんだけど、、、
一年ほど前には、Electron で同じようなことを
AndroidStudioでtess-twoを使用する（2018年4月8日現在）

tess-twoをAndroidStudioで使用する際、セットアップに時間がかかった（調べた方法が古かったり、失敗したりした）為、現在の使用方法を備忘録も兼ねて記録しておきます。

#1.導入準備
AndroidStudioのSDKManagerを開き、SDKToolsから、CMake、LLDB、CMakeをインストールする。
<img width="1280" alt="スクリーンショット 2018-04-08 10.07.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/166924/fdb51bb6-d314-ae4c-867c-747d258750a8.png">

　gitでtess-twoをインストールする。

```
git clone https://github.com/rmtheis/tess-two.git
```

#２.プロジェクト作成
1. 空のプロジェクトを作成する。<br>このとき、[Inclde C++ support]と[Inclde Kotlin support]にチェックはしない。
2. 作成が完了したら、プロジェクトの```app/src/main```の位置に```assets```ディレクトリを作成し、```assets``` ディレクトリ内に```tessdata```ディレクトリを作成する。
3. [ここ](https://github.com/tesseract-ocr/tessdata)から```.tessdata```の拡張子がついた学習データ(英語:eng.tessdata 日本語：jpn.tessdata)を持ってきて```tessdeta``ディレクトリの内部に入れる。


あとは以下のリンク先のコードを写せば撮影済みの画像から文字を読み取るプログラムが作成できる。
http://tyatran.hatenablog.com/entry/2017/10/09/142015
GPUのない環境でCUDAを用いたプログラムをビルドする

#概要

GPUのない環境でもCUDAを用いたビルドすることができる
CUDA Toolkitをインストールするときにドライバを除外する

#環境

Windows 10
GPUなし

#インストール
## Visual Studio Community 2017のインストール
C++とWindows 10 SDKのチェックを忘れずに

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244927/4ac3b7fd-0f1c-2d56-638d-8e856e5487f6.png)

## CUDA Toolkitのインストール

今回はGPUなしの環境でのインストールなのでカスタムを選択してドライバ以外をインストールする

# プロジェクトの作成とコンパイル

Visual Studioを立ち上げる

## プロジェクトの作成

インストールが完了していればテンプレートが使える

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244927/9e8e5c81-d9ac-2730-e9b8-af4a4b2efb43.png)

単純なプログラム`kernel.cu'が含まれるプロジェクトが作成される

## Platform Toolsetの設定

2018年4月現在、最新のCUDA Toolkitは最新のVisual Sudioに対応していないようでビルド時にエラーがいくつかでる。
プロジェクトのプロパティからPlatform Toolsetを2015のものにするのが無難。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244927/a56cccef-32aa-cf36-f692-522f0b92820d.png)

## ビルド

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244927/89002e7b-4854-19c3-f185-7beecd5e0552.png)



参考文献

https://devtalk.nvidia.com/default/topic/1008361/cuda-setup-and-installation/unable-to-install-cuda-8-0-on-machine-without-cuda-gpu/

https://devtalk.nvidia.com/default/topic/1027299/cuda-setup-and-installation/cuda-9-failed-to-support-the-latest-visual-studio-2017-version-15-5/
Django: テンプレート関連Tips

# Django: テンプレート関連Tips

## settings.pyなどで定義した変数をテンプレート内で直接使用する方法
- 結論：django-settings-export モジュールを使用すると手軽
- 参照元：[Can I access constants in settings.py from templates in Django?](https://stackoverflow.com/questions/433162/can-i-access-constants-in-settings-py-from-templates-in-django)
- 用途例：Django標準の各種view（django.contrib.auth.urls など）をそのまま使用し、テンプレート上ではsettings.pyで定義した変数を表示させたい場合など（例：settings.pyで定義した変数をDjango標準実装のログイン画面に表示させる）
- 手順
	- django-settings-exportモジュールを追加

	```
$ pip install django-settings-export
	```

	- settings.pyを編集
		- TEMPLATES の context_processors 内に 'django_settings_export.settings_export', の一行を追加
		- テンプレートから参照したい変数を定義：MY_HOGE = 'hogehoge'
		- テンプレートで参照可能にする変数名を SETTINGS_EXPORT リストに登録：SETTINGS_EXPORT = [ 'MY_HOGE', ]

	**settings.py**

	```
	TEMPLATES = [
	{
		'OPTIONS': {
			'context_processors': [
				'django_settings_export.settings_export',
			],
		},
	},
	]
	MY_HOGE = 'hogehoge'
	SETTINGS_EXPORT = [
		'MY_HOGE',
	]
	```


	- テンプレートファイル内で settings.(変数名) で参照

	**template.html**

	```
<div>MY_HOGE = '{{ settings.MY_HOGE }}'</div>
```
ECSデプロイツールを公開しました

## 概要
AWS ECSを運用するために内製で開発したデプロイツールを公開しました。

## リポジトリ

https://github.com/metaps/genova

## 何ができるのか
Slack botに対し `deploy` と打つと、ECSクラスタに対象となるソースをデプロイします。またコマンドベースのデプロイやGitHubのPushをトリガーとした自動デプロイもサポートします。

## 機能詳細

* サービスやタスクスケジューリングのデプロイ、タスク実行をサポート
* YAMLベースのタスク定義
  * 環境変数に渡した秘匿値の暗号化・復号に対応 (KMS)
* デプロイ形式
  * Slackを用いた対話形式のデプロイ
  * コマンドベースのデプロイ
  * GitHubのPushをトリガーとした自動デプロイ
* デプロイ状況を可視化するWebコンソールの提供
* デプロイコマンドが実行する処理
  * イメージのビルド
  * イメージのプッシュ (ECR)
  * タスクのデプロイ

図解。

![](https://raw.githubusercontent.com/wiki/metaps/genova/assets/images/overview.png)

Webコンソールはデプロイの状況を可視化します。「誰が」「いつ」「どこに」「何を」デプロイしたか、ひと目で把握することができます。

![](https://raw.githubusercontent.com/wiki/metaps/genova/assets/images/console_index.png)

詳細ページからはデプロイの状況を確認できます。

![](https://raw.githubusercontent.com/wiki/metaps/genova/assets/images/console_show.png)

## 設定ファイル

デプロイ設定ファイルとタスク定義ファイルを作成する必要があります。詳しくは [Wiki](https://github.com/metaps/genova/wiki/) を参照してください。

### タスク定義ファイル

アプリケーションディレクトリ下に `config/deploy/{services}.yml` を作成します。名前は何でも構いません。ファイルにはコンテナごとのタスク仕様を定義します。指定可能なパラメータは [タスク定義パラメータ](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html) と同じです。
環境変数にパスワードなどの秘匿値を渡す場合、KMSで暗号化した値を指定すると良いでしょう。値はデプロイのタイミングで復号され、環境変数として展開されます。

```
family: sandbox-productiton
task_role_arn: ''
network_ode: bridge
container_definitions:
- name: app
  image: ***.dkr.ecr.ap-northeast-1.amazonaws.com/sandbox-app-production:{{tag}}
  memory: 1024
  port_mappings:
  - container_port: 3000
    host_port: 0
    protocol: tcp
  essential: true
  environment:
  # Private value can be encrypted with KMS
  - name: SECRET_KEY
    value: ${***}
  readonly_root_filesystem: false
  log_configuration:
    log_driver: fluentd
    options:
      fluentd-address: ***:24224
      fluentd-async-connect: "true"
      tag: docker.sandbox-app-production
```

### デプロイ定義ファイル

デプロイルールを定義した `config/deploy.yml` ファイルを作成します。`clusters` にアプリケーションのデプロイ先となるクラスタやサービスを定義します。

```
clusters:
  # クラスタ名
  - name: sandbox
    services:
      # サービス名
      production:
        # タスク定義ファイルの相対パス
        path: ./config/development.yml

        # コンテナごとのビルドファイル指定
        containers:
        - name: web
          build:
            # etc/docker/web/Dockerfileを参照
            context: ../etc/docker/web
```

## デプロイ形式

### コマンドベースのデプロイ

対象リポジトリ・クラスタ・サービス (必要があればブランチ) を指定することで、デプロイが始まります。

```
$ docker-compose run --rm rails thor genova:deploy service -r {repository} -c {cluster} -s {service} -b master
```

### Slackを用いた対話形式のデプロイ

Slack Appをセットアップすることで、`deploy` コマンドで対話形式のデプロイが始まります。

<img src="https://raw.githubusercontent.com/wiki/metaps/genova/assets/images/slack_deploy.png" width=50%>

## GitHubのPushをトリガーとした自動デプロイ

Pushイベントをトリガーとして特定のサービスに対し自動デプロイが走ります。

```
auto_deploy:
- branch: master
  cluster: sandbox
  service: production
```
この設定は「`master`ブランチへのPushを検知した時、`sandbox`クラスタの`production`サービスをデプロイする」という意味になります。また実行結果はSlackに通知されます。
Matplotlib > plt.close('all') > EclipseやPyDevでは有効ではない?

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04.4 LTS desktop amd64
TensorFlow v1.7.0
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
gnustep-gui-runtime v0.24.0-3.1
PyMieScatt v1.7.0
```

PyMieScattのサンプルコードを見ていて、自分が見慣れていない記載があった。

http://pymiescatt.readthedocs.io/en/latest/examples.html#angular-scattering-function-of-salt-aerosol

```py
#%% Make graphs - lots of this is really unnecessary decoration for a pretty graph.
plt.close('all')
```

https://stackoverflow.com/questions/15012309/close-pre-existing-figures-in-matplotlib-when-running-from-eclipse

Eclipse/PyDevでは有効ではないとのこと（自分の使用環境ではない）。

### link

- [Matplotlib > plt.clf() [Clear the current figure] の理由 | plt.get_fignums()](https://qiita.com/7of9/items/a478f84df3e8a8562cc0)
ServiceNowのフォームのラベルやメッセージを多言語対応する

# 概要

ServiceNowには.NETアプリケーションのように、現在の言語設定に応じて自動的に言語を切り替える仕組みが備わっている。
多言語表示用の文言は、文言のキーと言語のキーごとにテーブルに保存されている。
ユーザーが表示言語を切り替えると、自動的にその言語をキーとする文言を多言語テーブルから取得し表示される。

# 環境

バージョン：KINGSTONE(Developer Instance)

# フォームのラベル

ServiceNowのFormはTableのカラム情報を元に生成される。Formの表示ラベルはTableのカラム情報の設定で多言語表示用のラベルを追加する。
Language列に「ja」を設定したレコードを追加することにより、ユーザーの言語設定が日本語の場合に、その「Label」列の文言がFormに表示される。

![tablelabelmultilanguage.png](https://qiita-image-store.s3.amazonaws.com/0/197947/737888b5-3e63-949b-6c69-e1a55ac96054.png)

なお、各テーブルのカラム情報のLabelsに追加したレコードは、「Field Labels」に追加されている。「Field Labels」に直接追加しても同様の結果が得られる。一括で多言語対応の文言を追加したい場合は、「Field Labels」に直接追加した方が効率が良い。

![FieldLabels.png](https://qiita-image-store.s3.amazonaws.com/0/197947/41fbe5d6-1981-4fa0-1284-b24cd36e65ad.png)


# メッセージ

サーバースクリプトで使用するメッセージについて、リテラルの文字列を埋め込んでしまうと当然ながら多言語対応ができない。

```javascript:多言語化対応前のソース
gs.addErrorMessage("When needed date cannot be in the past.  Your request has not been saved to the database.");
```

```javascript:多言語化対応後のソース
gs.addErrorMessage(gs.getMessage('date_validatte_message'));
```

なお、「gs.getMessage」の引数はメッセージリソースのキーである。
メッセージリソースは、「System Localization」の「Messages」レコードの追加により追加する。

## ユーザーの言語が英語の場合の表示
![systemlocalization_message.png](https://qiita-image-store.s3.amazonaws.com/0/197947/6d44c012-e541-1967-2b45-ec66ce879779.png)

## ユーザーの言語が日本語の場合の表示
![message_english.png](https://qiita-image-store.s3.amazonaws.com/0/197947/b7f56a86-6303-48c0-6100-1cd6b02118fd.png)
![message_japanese.png](https://qiita-image-store.s3.amazonaws.com/0/197947/3be563fa-eb6c-76fb-068a-fd05d8d11714.png)

## ユーザー言語の切り替えについて

ユーザー言語の切り替えは、SeriveNowで直接ログインする場合は、ログイン時に選択が可能だ。

![servicenowlogon.png](https://qiita-image-store.s3.amazonaws.com/0/197947/0c3f1a8c-c634-088c-a38a-537f17dc6b90.png)

シングルサインオン(SSO)などで別の認証システムから連携されて自動的にログインした場合は、ホーム画面の右上のギアアイコンをクリックし、設定画面から設定変更する。

![homegear.png](https://qiita-image-store.s3.amazonaws.com/0/197947/da891760-7f2a-ccca-bed2-8b0fb541e951.png)

General（一般）設定のLanguageから言語を選択する。
なお、選択可能な言語はそのServiceNowのシステムにインストールされている言語に限定される。

![servicenowsystemsettings.png](https://qiita-image-store.s3.amazonaws.com/0/197947/89de1b18-569a-c24d-afff-f7c356adbbfd.png)



# 参考

ServiceNowのDeveloper Instanceの初期状態では、日本語リソースがインストールされていない。
下記を参考に、日本語リソース表示用のプラグインのインストール後、日本語の切り替えが可能となる。日本語以外の言語も同様の方法で追加が可能である。

[ServiceNow初期設定 インスタンスを日本語化する](https://qiita.com/Kisaragi13/items/abbc205134d1696ff644)
SphinxでアニメーションGIFに開始・停止ボタンをつけた

## 背景

- Sphinxで作成するHTMLドキュメントをわかりやすくするために、アニメーションGIFを使いたい。
- Sphinx標準でも、アニメーションGIFを単純にimageファイルとして挿入することはできる。
- しかし、これだとアニメが自動で動き始め、テキストを読む進捗と同期せず読み勝手が悪い。
- アニメの開始・停止を読み手が制御できるようにしたい。

## 調べてわかったこと

アニメーションGIFに開始・停止ボタンを追加するのは、[gifffer](https://github.com/krasimir/gifffer) を使うとできる。
具体的には、Sphinxで出力されるHTMLが以下のようになればよい。

1. HTMLに次のタグを追加する

    ```html
    <script src="https://cdn.rawgit.com/krasimir/gifffer/c5044af8/build/gifffer.min.js"></script>
    ```

1. `<img>`タグの属性`src`を`data-gifffer`に置換する

    ```html
    置換前：<img src="_images/hello_world.gif" />
    置換後：<img data-gifffer="_images/hello_world.gif"/>
    ```

1. HTMLに次のタグを追加する

    ```javascript
    <script>jQuery(window).on("load", function(){Gifffer();});</script>
    ```

## 実現方法

これを実現するために、Sphinxを以下のように拡張・設定する。

1. `_static/js/init.js` を作成する

    ```javascript:_static/js/init.js
    jQuery(window).on("load", function(){Gifffer();});
    ```

1. `conf.py` の最後に以下を追加する

    ```python:conf.py
    import posixpath
    from sphinx.writers.html import HTMLTranslator
    class GiffferTranslator(HTMLTranslator):
        def visit_image(self, node):
            olduri = node['uri']
            if olduri in self.builder.images:
                node['uri'] = posixpath.join(self.builder.imgpath,
                                             self.builder.images[olduri])
            uri = node['uri']
            if uri.lower().endswith(('gif')):
                atts = {'data-gifffer': uri}
                if 'width' in node:
                    atts['data-gifffer-width'] = node['width']
                if 'height' in node:
                    atts['data-gifffer-height'] = node['height']
                atts['data-gifffer-alt'] = node.get('alt', uri)
                self.body.append(self.emptytag(node, 'img', '', **atts))
                return
            HTMLTranslator.visit_image(self, node)
    def setup(app):
        app.require_sphinx("1.3")
        app.add_javascript('https://cdn.rawgit.com/krasimir/gifffer/c5044af8/build/gifffer.min.js')
        app.add_javascript('js/init.js')
        app.set_translator('html', GiffferTranslator)
    ```

# まとめ
これで画像ファイルが `.gif` の時に `gifffer` が適用されるようになった。

```
.. image:: ../images/hello_world.gif
```

- 出来上がったページは[これ](https://frontops-docs.exhands.org/quickstart.html)
- Sphinx 1.7.2で動作確認した (1.3b1 より前は、`set_translator` がないので動かない)
- Sphinxの[HTMLTranslator#visit_image](https://github.com/sphinx-doc/sphinx/blob/master/sphinx/writers/html.py#L596-L635) を参考にして作成
- アニメじゃないGIFかどうか判定していないが、アニメじゃない画像にはPNGを使うようにしているので実用上問題はない。
Link > PyMieScatt > example > General Usage tips and Example Scripts

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04.4 LTS desktop amd64
TensorFlow v1.7.0
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
gnustep-gui-runtime v0.24.0-3.1
PyMieScatt v1.7.0
```

下記にPyMieScattの使用例がある。
[General Usage tips and Example Scripts](http://pymiescatt.readthedocs.io/en/latest/examples.html)

Shapelyをインストールしたわりに、Shapelyを使用している例はないようだ。
Matplotlibを使っている。
grep > cソースの関数宣言だけを抜き出す

```txt:動作環境
Windows 7 Pro (64bit)
SmartGit 17.1.1 #11182
```

### 関数の宣言だけを抜き出す

```shell-session
$ cat xxx.c | grep -E ")$" | grep -v "if" | grep -v "for" | wc
79
$ cat xxx.c | grep -E ")$" | grep -v "if" | grep -v "for"  > function_list.txt
```

### 上記が有効な条件

`1. 下記のような関数宣言の記述

```xxx.c
void someFunc()
{
```

`2. 関数名にifやforを含めていない
(grepでifやforを除くのは、if()文やfor()文がgrep検索されてしまうため)

### 参考

[grepでこういう時はどうする?](https://qiita.com/hirohiro77/items/771ffb64dddceabf69a3) by @hirohiro77 さん

行の末尾の記載方法を参考にしました。

情報感謝です。


### 備考

結局、別の方法でソース構造の整理をした（秀丸エディタのアウトライン解析）。

上記の方法が有用になる時はあるだろうか？
convnet.jsの作法

#概要
convnet.jsの作法を調べる。

#convnetjs.Vol

基本単位
ネットへの入力、出力に使用する。
sx,syは、shapeサイズ。
depthは、length.
wは、value.
dwは、weight.

例  var x = new convnetjs.Vol([0, 1, 2, 3, 4]);

```
 + * : object = [object Object]
 |  + sx : number = 1
 |  + sy : number = 1
 |  + depth : number = 5
 |  + w : object = 0,1,2,3,4
 |  + dw : object = 0,0,0,0,0
 |  + get : function = function (x, y, d) {
			var ix = ((this.sx * y) + x) * this.depth + d;
			return this.w[ix];
		}
 |  + set : function = function (x, y, d, v) {
			var ix = ((this.sx * y) + x) * this.depth + d;
			this.w[ix] = v;
		}
 |  + add : function = function (x, y, d, v) {
			var ix = ((this.sx * y) + x) * this.depth + d;
			this.w[ix] += v;
		}
 |  + get_grad : function = function (x, y, d) {
			var ix = ((this.sx * y) + x) * this.depth + d;
			return this.dw[ix];
		}
 |  + set_grad : function = function (x, y, d, v) {
			var ix = ((this.sx * y) + x) * this.depth + d;
			this.dw[ix] = v;
		}
 |  + add_grad : function = function (x, y, d, v) {
			var ix = ((this.sx * y) + x) * this.depth + d;
			this.dw[ix] += v;
		}
 |  + cloneAndZero : function = function () { 
            return new Vol(this.sx, this.sy, this.depth, 0.0)
        }
 |  + clone : function = function () {
			var V = new Vol(this.sx, this.sy, this.depth, 0.0);
			var n = this.w.length;
			for (var i = 0; i < n; i++) 
            {
                V.w[i] = this.w[i];
            }
			return V;
		}
 |  + addFrom : function = function (V) { 
            for (var k = 0; k < this.w.length; k++) 
            {
                this.w[k] += V.w[k]; 
            }
        }
 |  + addFromScaled : function = function (V, a) {
            for (var k = 0; k < this.w.length; k++) 
            {
                this.w[k] += a * V.w[k];
            }
        }
 |  + setConst : function = function (a) { 
            for (var k = 0; k < this.w.length; k++)
            {
                this.w[k] = a;
            }
        }
 |  + toJSON : function = function () {
			var json = {}
			json.sx = this.sx;
			json.sy = this.sy;
			json.depth = this.depth;
			json.w = this.w;
			return json;
		}
 |  + fromJSON : function = function (json) {
			this.sx = json.sx;
			this.sy = json.sy;
			this.depth = json.depth;
			var n = this.sx * this.sy * this.depth;
			this.w = global.zeros(n);
			this.dw = global.zeros(n);
			for (var i = 0; i < n; i++) 
			{
				this.w[i] = json.w[i];
				//this.dw[i] = json.dw[i];
			}
		}

```

#調査したコード

```
function print_r(obj) {
	var count_obj = 0;
	function _output(str) {
		document.writeln(str);
	}
	function _print_r(obj, name, level) {
		var s = "";
		if (obj == undefined || level > 1) return;
		for (var i = 0; i < level; i++) 
		{ 
			s += " | "; 
		}
		s += " + " + name + " : " + typeof(obj) + " = " + obj;
		_output(s);
		if (name == "document" || typeof(obj) != "object") return;
		for (key in obj) 
		{
			if (count_obj++ > 100) return;
			_print_r(obj[key], key, level + 1);
		}
	}
    document.writeln("<textarea cols=80 rows=40>");
	_print_r(obj, "*", 0);
    document.writeln("</textarea>");
}

var x = new convnetjs.Vol([0, 1, 2, 3, 4]);
print_r(x);


```

#成果物

http://jsdo.it/ohisama1/4FHz




以上。
[PHP 7] isset & empty & is_null を比較してみる

# 動機
最近PHPを触り始めて、POSTされた値の空判定を***isset***、***empty*** などの関数をどのように使うのがベストか迷ったので、***isset*** と ***empty***、ついでに***is_null*** を比較してベストな判定方法を検討したいと思います。
よりいい方法があればコメント下さい。

# 関数の概要
|関数 |説明|
|:---:|:--|
|isset|指定した変数がセットされていない、またはNULLであればFALSEを返し、それ以外はTRUEを返す|
|empty|指定した変数が空でないならFALSEをかえし、それ以外はTRUEを返す|
|is_null|指定した変数がNULLであればFALSEを返し、それ以外はTRUEを返す|

## emptyの判定条件の***空***とは？
>次のような値は空であるとみなされます。
1. "" (空文字列)
2. 0 (整数 の 0)
3. 0.0 (浮動小数点数の 0)
4. "0" (文字列 の 0)
5. NULL
6. FALSE
7. array() (空の配列)
8. $var; (変数が宣言されているが、値が設定されていない)
[(PHP Manualより引用)](http://php.net/manual/ja/function.empty.php)

上記のようにemptyの場合は、FALSEと等価とみなされる値を空と定義しています。
ログインフォームなどの場合はemptyを使っても問題はないと思いますが、
厳密に空かどうか判定したい時には不適切です。

# 関数の判定例

```php

$a = "";
var_dump(isset($a));    // TRUE
var_dump(empty($a));    // TRUE
var_dump(is_null($a));  // FALSE

$a = NULL;
var_dump(isset($a));    // FALSE
var_dump(empty($a));    // TRUE
var_dump(is_null($a));  // TRUE

$a = "hello world";
var_dump(isset($a));    // TRUE
var_dump(empty($a));    // FALSE
var_dump(is_null($a));  // FALSE
```

このようになるので、POSTフォームからname="test"かつ未入力の状態(空文字)で送信された、すなわち$\_POST['test'] = "" となる時、
1. ***isset***は空判定ができない、つまりPOSTされたかどうかの判定を意味するものとなる
2. ***empty***は先にも述べたように厳密の意味での空判定ができない
3. ***is_null***を用いるのはもってのほか

では、どのようにすればベストなのでしょうか？

# Best Practice
```php
if (isset($_POST['test'])) {
   if ($_POST['test'] != "") {
       // 空でない
   } else {
       // $_POST['test']はセットされNULLではないが、空文字である
} else {
   // $_POST['test']はセットされていない
}
```

これがいい方法なのではないでしょうか。

※上記の例では、判定の結果が分かりやすいようにif,else文をちゃんと書いていますが、必ずしも書く必要はありません。


# 参考
- [isset](http://php.net/manual/ja/function.isset.php)
- [empty](http://php.net/manual/ja/function.empty.php)
- [is_null](http://php.net/manual/ja/function.is-null.php)
- http://manaminmemo.sblo.jp/article/72490577.html
Laravel5.6で署名付きURL(時間制限付き)の実装が簡単に出来るようになったので試した

#Laravel5.6で署名付きURL(時間制限付き)の実装が簡単に出来るらしい

署名付きURLは実際のプロダクトで使用する機会も多いし、
時間制限付きの1時間以内にクリックしてくださいとかよくあるので、
簡単に実装できると凄くありがたいので試した。

公式の機能で追加になったらしいので、とりあえず確かめて見る。

以下のドキュメントを参考にした。
[URL Generation](https://laravel.com/docs/5.6/urls)

## 環境
- PHP 7.1.16
- Laravel Framework 5.6.15

## 実装
app/Http/Kernelに以下を記載する。

```php:app/Http/Kernel.php
protected $routeMiddleware = [

    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,

];
```

あとは例に合わせてURLを作って、viewでリンクを作ってみる。

`SignedRoute(...)・・・署名付きURL生成`
`temporarySignedRoute(...)・・・署名付きURL生成（時間制限付き）`

今回は時間制限付きを試したいので`temporarySignedRoute`を使う。

- 実際に実装で使いそうなuseridを指定している。(とりあえず固定で１)
- 第２引数に有効時間を設定。下記の例は5秒以内にクリックしないとエラーになる。(`now()->addSeconds(5)`)

```php:routes/web.php
use Illuminate\Support\Facades\URL;
use Illuminate\Http\Request;

Route::get('/', function () {
    // URL生成
    $url = URL::temporarySignedRoute('unsubscribe', 
                                      now()->addSeconds(5), 
                                      ['user' => 1]);

    // とりあえずwelcomページにリンクを出して見る
    return view('welcome')->with('url',$url);
});
```

そして上の設定のルート先の内容が以下。
5秒以内にリンクをクリックすると、`view('safe')`のページが出る。
5秒以降のエラー遷移は`->middleware('signed');`がやってくれる。

```php:routes/web.php
Route::get('/unsubscribe/{user}', function (Request $request) {

    return view('safe');

})->name('unsubscribe')->middleware('signed');
```
エラー遷移は`->middleware('signed');`がやってくれる。と書いたが、
このミドルウェアは自動的に`403`エラーレスポンスを返すと書いてあるので
`resources/views/errors/403.blade.php`を用意した。

## 動作確認
まず、ルート画面に生成したURLを埋め込むと、以下のようなリンクが出た。

```
http://.../unsubscribe/1?expires=1523128426&signature=63b4744eb3aea943ddd7411d92bf2d8cea528dda011e29a9da128fac5c7e8ab7
```

- 5秒以内にクリック
→`view('safe')`の画面が表示された。

- 5秒以降にクリック
→`403`エラーの画面が表示された

## validation

また実際に使いそうな処理としてvalidation判定して処理を分ける場合は、
`$request->hasValidSignature()`を使うため、`->middleware('signed');`を外した。
今度は`401`エラーを使いたいので`resources/views/errors/401.blade.php`を用意して確認した。

```php:routes/web.php
Route::get('/unsubscribe/{user}', function (Request $request) {
    if (! $request->hasValidSignature()) {
        abort(401);
    }
    return view('safe');

})->name('unsubscribe');
```

- 5秒以内にクリック
→`view('safe')`の画面が表示された。

- 5秒以降にクリック
→`401`エラーの画面が表示された


# 結果
本当に簡単に実装できた。時間制限設定も簡単。
今後、Laravel５.６以上で1時間以内にクリックとかでURLメール送る機能とかを作る時が来たら使って見る。
Unityちゃんに「ファイティングユニティちゃん」のモーションを適用する方法

　「ファイティングユニティちゃん」のアニメーションをUnityちゃんに適用するのに地味に手間取ったので、自分のために方法を記録しておく。

<img width="960" alt="Unity_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/186254/34d640b6-9e48-705a-296f-97e5bd1e4fbe.png">

　上記の画像のように、インストールした「ファイティングユニティちゃん」のfbxを選択した状態で、Inspector欄のRigを選択し、Animation TypeをHumanoidにし、Applyボタンを押したら操作完了。これで、Unityちゃんに「ファイティングユニティちゃん」のモーションを適用できるようになる。


　「ファイティングユニティちゃん」に限らず、ほかのアニメーションもこの方法で大丈夫なのかな？:rolling_eyes:
SQLパフォーマンス

SQLの書き方によるパフォーマンスチューニング
SQLを作成するうえで気を付けるべき基本的な事

# ソート回避
物理メモリが使用されると劇的に遅い

- GROUP BY
- ORDER BY
- SUMやMAXなどの集計関数
- DISTINCT
- UNIONなどの集合演算子
- RANKなどのOLAP関数

# インデックスを確実に使う

インデックスが使われない書き方

- 項目に計算している (amount * 1.1 > 1000など)
- IS NULL  
　※MySQL、PostgreSQLはNULLをインデックスに格納する
- <>,NOT INなどの否定形
- OR文
- 復号インデックスと列指定条件順序が異なる
- 部分一致、後方一致
- 暗黙の型変換

また、インデックスは適切に作成する
- カーディナリティの高いカラム
- マルチカラムインデックスの検討する
- カバリングインデックスを使用する

# 中間テーブルを減らす

- サブクエリNG
- 集約より先に結合する
- Viewは使わない

# メモリアクセスを減らす
- レコードの存在チェックでCOUNTを使わない  
　※LIMITやROWNUMを使用する

# そもそも遅いのはなぜか
- 1つのSQLが遅い
 - チューニングする
- 1回では遅くないSQLを複数回実行している
 - 1回でまとめてとるなど、実行回数を減らす

# 最初は早かったけど運用していく中で遅くなる
- 単純にデータ量の増加
- 機能変更などによりデータアクセスパターンの変化
- アクセス量の増加

# 大量データ削除で考える事
リソースを奪ってしまい、サービスが停止/遅くなるのを防ぐ。
途中sleepを入れながら、少しずつ削除する。
fpdfの開発例（余白を無くす設定例）


phpで下記の様に記述する

<?php
require("fpdf/mbfpdf.php");

//用紙サイズA5の場合 $pdf=new MBFPDF('P', 'mm','A5');とするがとpdf->SetXY(x,y)のxyの規定範囲が狭いので
//以下の様に用紙サイズカスタム設定

   $pdf=new MBFPDF('P', 'mm', array(170,250));

   $pdf->AddMBFont(GOTHIC ,'SJIS');

for($i=0;$i<=1;$i++){

   $pdf->AddPage();

   $pdf->SetFont(GOTHIC,'',20);

  $pdf->SetXY(0, 0.0);

  $pdf->Write(10,'文字列の出力',0,0,"L");

  $pdf->SetXY(30.0, 30.0);

  $pdf->Write(10,'次の文字列',0,0,"L");

  $pdf->SetXY(0,190);

  $pdf->Write(10,'その次の文字列',0,0,"L");

}
$pdf->Output();
?>
![pdftest_img001.jpg](https://qiita-image-store.s3.amazonaws.com/0/101462/53b1bbc1-92ba-81e0-44d6-a87d5dcc548b.jpeg)
Everything in Kotlinについて考える①

# Everything in Kotlinとは？
バックエンド、Webフロントエンド、デスクトップアプリ、Android、iOS、全てをKotlinを使って実装しょうという私の考えに名前を付けただけです。

# 全てを同じ言語で書く理由
私は業務の変更に強いサービスを作るため、業務内容(ビジネスロジック)を素直に表す層(ドメイン層)を作り、他の層(プレゼンテーション層やインフラ層)に依存しない実装にするというDDDの考え方が好きです。
ですが、せっかくドメイン層を作っても、バックエンド、Webフロントエンド、Android、iOSそれぞれで使用する言語が変わればドメイン層のドメインモデルを使い回すことが出来ないので全て同じ言語で実装したいと思いました。

# Kotlinを選んだ理由
Kotlinで書いたコードは様々なプラットフォームで動かすことが出来る形(Javaバイトコード、JavaScript、ネイティブバイナリ)に変換することが出来ます。JavaScriptでもNode.jsやCordova、React Native、Electronを使って同じようなことが出来ますが、ドメインモデルを動的型付け言語で表現するのは難しいと感じたため、静的型付け言語であるKotlinを選びました。

# 現状、どこまでKotlinで書けるのか？
現状共通化出来るのはバックエンド、Webフロントエンド、デスクトップアプリ、Androidぐらいです。
共通化する上で大事なのは、kotlinx(Kotlin Common Moduleのライブラリ)のcoroutines(非同期処理)、serialization(シリアライズ、デシリアライズ)が対応しているかどうかです。

現在(2018/04)、Kotlin/Nativeは対応していないのでiOSアプリは共通化が難しくなっています。
ですが、Kotlin/NativeをサポートするIssueは立っているのでiOSアプリも共通化出来る未来は来ると思います。

[kotlinx.coroutines Add support for Kotlin/Native](https://github.com/Kotlin/kotlinx.coroutines/issues/246)
[kotlinx.serialization Add support for Kotlin/Native](https://github.com/Kotlin/kotlinx.serialization/issues/86)

# 最後に
次回は、バックエンド、Webフロントエンド、デスクトップアプリ、Androidをどう共通化するのかを[Kotlin Academy](https://blog.kotlin-academy.com/)アプリの[実装例](https://github.com/MarcinMoskala/KotlinAcademyApp)から見ていきたいと思います。

「全てをKotlinで」をグーグル翻訳で翻訳しただけなので、「Everything in Kotlin」よりいい感じの翻訳があれば教えて下さい
DialogflowのFulfillmentでユーザ入力のパラメータを取得するときにハマった

Google Homeアプリを開発している時に、DialogflowのFulfillmentでユーザ入力のパラメータ（例. Aさん「◯◯を教えて」の◯◯の部分）を取得するときに悪戦苦闘したので、メモを残しておきます。

# どこでハマったの？

```javascript:index.js
...省略...

const App = require('actions-on-google').DialogflowApp;

...省略...

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const app = new App({request, response});

...省略...

});
```

```:Firebaseのログ
TypeError: App is not a constructor
    at exports.dialogflowFirebaseFulfillment.functions.https.onRequest (/user_code/index.js:11:15)
    at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:26:47)
    at /var/tmp/worker/worker.js:676:7
    at /var/tmp/worker/worker.js:660:9
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)
```

どうやら、npmの`actions-on-google`パッケージがうまく動作していない模様。ただ`index.js`は以下公式サイトを参考に作成したので、スクリプト自体はあっているはず。。

[Dialogflow で初めてのアプリをビルドする  |  Actions on Google  |  Google Developers](https://developers.google.com/actions/dialogflow/first-app)

# 原因は`package.json`の中にありました
**原因は`package.json`の中で定義している`actions-on-google`のバージョンでした。**


FulfillmentのInline Editorにある、デフォルトの`package.json`内の`actions-on-google`だとうまく動作しないようです。修正後のバージョンにすると動きました！

```json:デフォルトのpackage.json
{

...省略...

  "dependencies": {
    "actions-on-google": "2.0.0-alpha.2",

...省略...

  }
}
```

```json:修正後のpackage.json
{

...省略...

  "dependencies": {
    "actions-on-google": "^1.0.0",

...省略...

  }
}
```

# まとめ
Google Homeアプリ開発はまだまだ情報が少ないのでよくつまづきます。もっともっと開発者が増えてこういったメモが増えると嬉しいですね。