OmniAICreator/Qiita-1.07M huggingface dataset:
UnityでgRPCを動かす #1 コンソールアプリ

ゴール：Unity(iOS/Android)でgRPCを動かす

* UnityでgRPCを動かす #1 コンソールアプリ
* [UnityでgRPCを動かす #2 Unity](https://qiita.com/nakaken0629/items/2cda78997befb71f7e3d)
* [UnityでgRPCを動かす #3 iOS](https://qiita.com/nakaken0629/items/0e2d6cdb7eb5283a7d34)
* [UnityでgRPCを動かす #4 Android](https://qiita.com/nakaken0629/items/bd86a62e762f7fd073ae)

~~開発環境：macOS Sierra + Unity 2017.3.0f3~~
開発環境：macOS Mojave + Unity 2019.1.5f1
今回はその１です。

# コンソールアプリでgRPCのサンプルを動かす

C#で開発するのでVisual Studio for Mac（以下vs）をインストールします。

https://www.visualstudio.com/ja/vs/visual-studio-mac/?rr=https%3A%2F%2Fwww.google.co.jp%2F

次にgRPCの本体＋サンプルをcloneします。

$ cd （個人の作業用フォルダ）
$ git clone https://github.com/grpc/grpc.git

サンプルのソリューションファイルを開きます。cloneを実行したフォルダに入り、次のコマンドを実行します。するとvsが起動します。

$ open examples/csharp/helloworld/Greeter.sln

<img width="1008" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/c80979c7-a262-a754-b83b-f6113880bb6d.png">

GreeterServerプロジェクトを右クリックして「プロジェクトの実行」を選択します。するとC#で書かれたサーバー側のプログラムが起動します。

<img width="682" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/240d7224-f277-8b35-1f0c-d23e97a78c8a.png">

GreeterClientプロジェクトを右クリックして「プロジェクトの実行」を選択します。C#で書かれたクライアントのプログラムが実行されて、サーバーのメソッドを呼び出します。

<img width="682" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75307/f56d6e82-b536-8e85-0aba-3f9c8c246c03.png">

# 次回予告

ここまで、C#のコンソールアプリとしてサンプルを動かしてきました。次はクライアントをUnityで作成してみます。
【SQL】select文の加工

 勉強したことのメモ(・∀・)

#select文の加工

・order by （並べ替え）
・limit　（表示する件数を指定）
・distinct （重複するデータを除外）
-- 集合演算子 --
・union （和集合）
・except,minus （差集合）
・intersect（積集合）　

例 : Purchase　テーブル

|id|day| contents | money|
|:---|------------:|:------------:| :------------:|
| 01 | 2018-02-01  |文房具|1000|
| 02 | 2018-02-02  |食費|2000|
| 03 | 2018-02-03  |食費|500|
| 04 | 2018-02-04  |光熱費|10000|
| 05 | 2018-02-04  |文房具|3000|
| 06 | 2018-02-05  |食費|2000|

例 : Purchase2　テーブル

|id|day| contents | money|
|:---|------------:|:------------:| :------------:|
| 01 | 2018-01-03  |食費|5000|
| 02 | 2018-01-03  |食費|5000|
| 03 | 2018-01-07  |食費|1000|
| 04 | 2018-01-22  |光熱費|10000|
| 05 | 2018-01-29  |交際費|13000|
| 06 | 2018-01-030  |食費|4000|


## order by（並べ替え） 使用例

<font color="Fuchsia">※</font>DBMSには、負荷の掛かる作業。使いすぎには注意。

・金額（降順）に並べ替えて抽出

```sql
select * from Purchase
order by money desc
```

・金額（昇順）に並べ替えて抽出
※昇順の場合ascを省くことができる。デフォルトがascの為。

```sql
select * from Purchase
order by money asc
```

## limit（表示する件数を指定）使用例
・order by で並べ替えた結果の上位3件のみ抽出

```sql
select * from Purchase
order by money desc limit 3
```

<font color="Fuchsia">※</font> sql serverでは未対応。sql serverではtopを利用

```sql
select top 3 * from Purchase
order by money desc
```

## distinct（重複するデータを除外）使用例

・重複を省いたデータのみを表示

```sql
select distinct contents from Purchase
```

## 集合演算子

<font color="Fuchsia">※</font>集合演算子は、複数の結果を1つの結果として返す。
結果の列数とデータ型を一致必須させる必要あり。

## union（和集合）使用例

・select文2つの結果を足して抽出 重複するデータは1行にまとめる

```sql
select day, contents, money from Purchase
where contents = '食費'
union
select day, contents, money from Purchase2
where contents = '食費'
order by day desc
```
・select文2つの結果を足して抽出 重複するデータをまとめず全て抽出

```sql
select day, contents, money from Purchase
where contents = '食費'
union all
select day, contents, money from Purchase2
where contents = '食費'
order by day desc
```

## except,minus（差集合）使用例

<font color="Fuchsia">※</font>select文の順番重要!　基準をどのselectにするか。

・select文2つの結果から、select1にしかないcontensを抽出　重複する場合は1行にまとめる

```sql
select contents from Purchase
except
select contents from Purchase2
```

・select文2つの結果から、select1にしかないcontensを抽出　重複する場合まとめず全て抽出

```sql
select contents from Purchase
except all
select contents from Purchase2
```

## intersect（積集合）使用例

・select文2つの結果から、共通するcontensを抽出　重複する場合は1行にまとめる

```sql
select contents from Purchase
intersect
select contents from Purchase2
```

・select文2つの結果から、共通するcontensを抽出　重複する場合まとめず全て抽出

```sql
select contents from Purchase
intersect all
select contents from Purchase2
```

以上！
EPEL(Extra Packages for Enterprise Linux)リポジトリの追加

Linuxにて、いざ環境構築をしようとyumコマンドを叩いたもののパッケージが見つからないといったことがあり、
全然目新しい話ではないんですけど、毎回EPELについて調べなくてもいいように備忘メモ。

EPELとは「Extra Packages for Enterprise Linux」の略で、
「Fedoraで開発、テスト、改良された高品質のパッケージを、RHELやCentOS/Scientific Linuxのような
互換ディストリビューションで利用可能にすることです。」を、目的としてます。
<a href="https://fedoraproject.org/wiki/About_EPEL/ja"># 引用元：About EPEL/ja</a>

そんなEPELリポジトリが用意されていない環境には、wgetでrpmファイルを持ってくる必要があるので、以下手順。

```linux-config
# Red Hat Enterprise Linux 7の場合
$ yum install wget <= wgetがないとき
$ wget https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
$ rpm -ivh epel-release-7-11.noarch.rpm 
$ yum install epel-release

# インストールされたかを念のための確認
$ yum repolist
~
repo id                                              repo name                                                            status
epel/x86_64                                          Extra Packages for Enterprise Linux 7 - x86_64                       12,266
~
```

上記ではRHEL7を例に取り上げましたが、RHEL6などの場合はwgetで参照するURLを適宜変更する必要があります。
やり方として、以下URLのところまでブラウザでアクセスして、後はよしなにって感じです。

```
# 一旦ブラウザでアクセスしてみるURL、その後自分の環境に応じて適宜探す
https://dl.fedoraproject.org/pub/epel/

# 大体は下の感じになってると思います
https://dl.fedoraproject.org/pub/epel/<OS_ver>/<OS_bit>/Packages/e/epel-release-X-XX.noarch.rpm
```

epelが使えるようになると、pipとかgitとか色々と使えるようになるんで、ポリシーとかなければぜひ追加すべしです。
Atomで下にあるバーが消えたときの対処方法


なんか半年以上前にKobitoに下書きされてて、とりあえず公開してよさそうだから投げた。どっちかっていうとKobitoからQiitaに投稿ってできるのかな感覚。

----

Atom使ってて、下にある**あのバー**がいろいろと便利じゃないですか。

![Kobito.wCFqaA.png](https://qiita-image-store.s3.amazonaws.com/0/58800/e6190ee6-3a21-de69-be0c-6aa65d4421cb.png "Kobito.wCFqaA.png")

これですね。いろいろと表示してくれるので便利。

何の操作をしていたのか非表示になって、どうやって戻すかわからないってなりました。

ぐぐるかってなるわけですけど……。

**「あれ名前なんていうんだっけ？なんてぐぐればいいの？なんとかバーだろう。何バーだ？わからん。」**

ぐぐってもわからない（そもそもまともに検索できてない）ので、

![Kobito.ueSTD7.png](https://qiita-image-store.s3.amazonaws.com/0/58800/01fa5a5a-0831-e3dc-e2ab-9b19e084536c.png "Kobito.ueSTD7.png")


結局コマンドパレット開いて、`Toggle`で見てみれば何かしら見つかるだろうということで見つけました。

## Toggle Status Bar


![Kobito.TAxsTu.png](https://qiita-image-store.s3.amazonaws.com/0/58800/bd5a2665-88fc-6901-505a-cac3d362bf3a.png "Kobito.TAxsTu.png")

割と下の方に、Status Barって文字列が見えて、アハ体験。

下のやつの名はステータスバーでした。言われてみれば、当然これはステータスバーだよなって感じなんですけど、下の便利なバーみたいな覚え方してたせいで解決に手こずってしまいました。
Linux bashでプロセス監視

```bash:WatchProcess.sh
#!/bin/bash
PROCESS_NAME="IcedTea-Web Control Panel"
PROCESS_GREP="[i]tweb-settings.itweb"
PROCESS_COMMAND="itweb-settings.itweb &"
DATE_COMMAND="date '+%Y-%m-%d %H:%M:%S'"
SLEEP_SEC=5
LOG_FILE="/var/log/WatchProcess/WatchProcess.log"

while true
do
	if [ $(ps -ef | grep ${PROCESS_GREP} | wc -l) = 0 ]
	then
		echo "$(eval ${DATE_COMMAND}) ${PROCESS_NAME} is down. Starting..." | tee -a ${LOG_FILE}
		eval ${PROCESS_COMMAND}
		echo "$(eval ${DATE_COMMAND}) ${PROCESS_NAME} is started." | tee -a ${LOG_FILE}

	else
		echo "$(eval ${DATE_COMMAND}) ${PROCESS_NAME} is alive."
	fi
	sleep ${SLEEP_SEC}
done
```

```text:/etc/logrotate.d/WatchProcess
/var/log/WatchProcess/WatchProcess.log {
	daily
	rotate 365
	missingok
	ifempty
	dateformat .%Y%m%d
}
```
omise API でカスタマーIDを元に課金履歴を取得する


仕事でOmiseのAPIを使ってcustomerIDごとに課金履歴を取得したかった。ChargeやChargeScheduleのところを見てもそれっぽい記述がなくOmiseのカスタマーサポートにお問い合わせ。  
15分ぐらいで返答きました（はやい！）。  今後のために忘れないためにも纏めておきます。


どうやら検索APIで検索すると出来るらしい。
[omise - search API] (https://www.omise.co/ja/search-api)

APIキーやIDは適宜設定してください。

### curl
CURLだとしたみたいなかんじ。

```bash
  curl 'https://api.omise.co/search?scope=charge&query=cust_test_xxxxxxxxxxxxx' \ 
  -u skey_test_xxxxxxxxxxxxxxxxxx
```


### php 
Omise PHP Clientを使った場合。
[omise-php](https://github.com/omise/omise-php)

```php
    $result = OmiseSearch::scope('charge')->query($customerId);
    var_dump($result['data']);
```
RaspberryPiからTwitter APIでツイートするまでにやったことメモ

#前提
- Twitterアカウントは持っている（人間が見たり書いたりする用）

#準備
##Twitter API用のアカウントを作成する
正しくはアプリ登録と呼ぶらしい。
https://apps.twitter.com/
から登録。

##その前にTwitterアカウントに電話番号を登録
アプリ登録には電話番号登録が必要だ。
PCでTwitterを開き、電話番号を入力してSMSで認証コードが届くのだが、これが中々届かなくて困った。
MVNOだから？と思って楽天モバイルの設定とか調べたが該当箇所なく。
悩みながらPCではなくてスマホのTwitterアプリから登録したら、PCから入力した分も含めてSMSが返ってきた。
なんだったのだ。。。

##アクセストークンを生成
Consumer Key, Consumer Secret は最初からできているが、
Access Token, Access Token Secret は明示的に生成する必要がある。

#ツイート用のPythonコードを書く
https://qiita.com/yubais/items/dd143fe608ccad8e9f85
↑のURL通りにやれば問題なし。
Requests-OAuthlibのインストールはGitHubに記載の通り、
```pip install requests requests_oauthlib```
でOK.

#結果
![test_tweet.png](https://qiita-image-store.s3.amazonaws.com/0/187660/f85cc397-7d4c-7728-b08f-507cbda7b42d.png)

おぉぉぉ・・・なんか嬉しい。

以上
Mac High Sierra 10.13.2 で Blender 2.79 で視点切替に困ったら

# この記事は？
Mac High Sierra で [Blender render doesn'work with Mac High Sierra](https://developer.blender.org/T53424) を読んで
> Everything is fine with 2.79.

と書いてあるのに気づいたり

[Blender 2.79 リリースノート](https://wiki.blender.org/index.php/Dev:JA/Ref/Release_Notes/2.79) で

> AMD OpenCL 最適化

あたりを読んで
狂喜乱舞し意気揚々とダウンロードしたが、導入したら視点切替（123... のショートカットキー）が使えなくて困っている方

# 対象者
以下を利用しているユーザ

* Mac High Sierra 10.13.2
* Blender 2.78 or 2.79

# なぜ動かなくなったのか？
チェックボックスが外れている Layers の部分に注目してください。
既存で Mac のキーボードの 1, 2, 3,... を使って視点移動していた人は Any 1 が優先されてレイアウトが切り替わってしまうことが原因
![SetLayers.png](https://qiita-image-store.s3.amazonaws.com/0/84122/1e52f6f0-d102-4e23-2c7a-c629716ca644.png)

# 解決策
上記のように Layers に設定されていた Any 1, Any 2, Any 3,... の設定を変更するか外すなどして、 下記の [←] の View に関するキーバインドが Numpad 1, Numpad 2, Numpad 3,... に設定されているはずなので、以下のように 1, 2, 3,... に変更することで解消できる
![ResetView.png](https://qiita-image-store.s3.amazonaws.com/0/84122/5ce458e5-9dcf-059d-0a0e-88478f19624f.png)

# 雑感
[BlenderはOS Xを放棄する？「OS XのGPUドライバにはApple以外修正できないOpenCLの不具合がある」としてLuxRenderの開発チームがTim Cook氏へ公開状を送る。](https://applech2.com/archives/44609189.html) あたりを読んでいた人は今回の更新はかなり嬉しいものになりそうですね！
Scrapyの取得結果をブラウザで開く

`open_in_browser`を使用すると、取得結果をブラウザで開いてくれる。
って、公式ドキュメントに普通に書いてあった。

``` python
from scrapy.utils.response import open_in_browser

def parse_details(self, response):
    if "item name" not in response.body:
        open_in_browser(response)
```

https://doc.scrapy.org/en/latest/topics/debug.html#open-in-browser
google-api-php-client v2.2.1を使ってPHPからGoogleカレンダーに登録する

#はじめに
Google Calendarにwebページから投稿するフォームを実装しようとしてつまずきました。

webページのフォームからGoogle Calendarに投稿する方法は多くのページで紹介されていますが、バージョン2.0以降のgoogle-api-php-clientを使用しているページが見当たらなかったので自分の覚書も兼ねて投稿します。

#環境
- google/google-api-php-client v2.2.1

https://github.com/google/google-api-php-client/releases
こちらからダウンロードできます。
投稿時のLatest releseがv2.2.1だったのでこちらで紹介します。

#準備
まず基本的な導入方法は変わらないので割愛します。
自分は以下のページを参考にしました。

”PHPを使ってGoogleカレンダーにフォームから予定を登録してみる”
https://www.spiceworks.co.jp/blog/?p=10254

#変更点
上記のページの方法で実装するとエラーが発生します。
これはv1.0→v2.0にアップグレードした際に色々と変更があったことが原因のようです。
変更点に関する詳細は以下のページで見ることが出来ます。
https://github.com/google/google-api-php-client/blob/master/UPGRADING.md

さて、実装における具体的な変更点は次の通りです。
1. vendorディレクトリの追加
　ダウンロードして解凍したgoogle-api-php-client-2.2.1の中に新たにvendorというディレクトリが増えています。
参考ページのようにsrcディレクトリのみコピペするとエラーが出るのでvendorディレクトリも配置する必要があります。
そのため、サーバー上に作成したgoogle-api-php-clientディレクトリ以下のディレクトリは次のようになります。

>google-api-php-client/
　├ src/
　├ vendor/
　└ key/

2．autoload.phpのpathの変更
　v1.0ではsrcディレクトリ以下にあるautoload.phpを参照していましたが、v2.0ではvendorディレクトリ以下に変更されたようです。
ですので、参考ページの⑫にあるソースコードの2行目は次のように変更します。

```form.php
require_once __DIR__.'/google-api-php-client/vendor/autoload.php';
```

3.jsonファイルからGoogleClientを生成する方法の変更
　ここの書き方が大きく変わっているようです。

↓参考ページの⑩にあるソースコード

```functions.php
<?php
/**
 * jsonファイルからGoogleClientを生成します
 */
function getGoogleClientByJson() {
    $json_path = __DIR__.'/google-api-php-client/key/xxxxxxxxxxx.json'; // jsonファイルのパスをここに書いてください。
    $json_string = file_get_contents($json_path, true);
 
    $json = json_decode($json_string, true);
 
    $private_key = $json['private_key'];
    $client_email = $json['client_email'];
 
    $scopes = array(Google_Service_Calendar::CALENDAR);
 
    $credentials = new Google_Auth_AssertionCredentials(
        $client_email,
        $scopes,
        $private_key
    );
 
    $client = new Google_Client();
    $client->setApplicationName("Google Calendar PHP API");
    $client->setAssertionCredentials($credentials);
    if ($client->getAuth()->isAccessTokenExpired()) {
        $client->getAuth()->refreshTokenWithAssertion();
    }
    return $client;
}
?>
```

↓変更後のソースコード

```functions.php
<?php
/**
 * jsonファイルからGoogleClientを生成します
 */
function getGoogleClientByJson() {
   $json_path = __DIR__.'/google-api-php-client/key/xxxxxxxxxxx.json'; // jsonファイルのパスをここに書いてください。

    $scopes = array(Google_Service_Calendar::CALENDAR);

    $client = new Google_Client();
    $client->setApplicationName("Google Calendar PHP API");
    $client->setAuthConfig($json_path);
    $client->setScopes($scopes);
    if ($client->isAccessTokenExpired()) {
	$client->refreshTokenWithAssertion();
    }
    return $client;
}
?>
```
書き方が簡略化されたようです。

変更箇所は以上です。
無事カレンダーに登録されました。めでたしめでたし。

#さいごに
実際に実装してから投稿まで少し日にちが空いてしまったので不備やミスなどあるかもしれません。
お気づきの際には教えていただけると幸いです。
Cake browserのUIが今までのブラウザの常識を覆している件

Twitterで元TechCrunch編集長の西村さんが、Smoozの加藤さんに紹介していた、スマホブラウザをダウンロードしてみました。

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">おお、これは良さそう。Smoozの加藤さん <a href="https://twitter.com/sassymanyuichi?ref_src=twsrc%5Etfw">@sassymanyuichi</a> 、このUI良くないですか？ 検索結果をプリロードって凶悪かもですがw<a href="https://t.co/k2RrlnKPMo">https://t.co/k2RrlnKPMo</a></p>&mdash; Ken Nishimura / 西村賢 (@knsmr) <a href="https://twitter.com/knsmr/status/959350607818637313?ref_src=twsrc%5Etfw">February 2, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

[Cake](https://cakebrowser.com/)というアプリ。
何が新しいかというと、ChromeやSafariといった既存のブラウザが、検索ワードを入力->検索実行後に、検索結果画面に遷移するのに対して、Cakeは、いきなり検索結果1位のページが表示され、タブで次のページ、次のページと遷移するという点。

UIはこんな感じ。
<img width="375" alt="IMG_0520.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/209160/75680118-9993-34ad-b7dc-1c653600e037.png">
5つ並んでいる丸いアイコンで何で検索するか（普通に検索 or 画像検索 or ニュース検索...）決められる。

そして検索を実行するといきなり、Cake browserのページへ。
<img width="375" alt="IMG_A83C62E91600-1.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/209160/2298b245-6b21-f478-0988-1e0714bccafe.jpeg">
左にスワイプしていくと、検索結果2位のページ、3位のページとみていくことができます。
最初は、「いや、普通に検索結果みてから好きなページに遷移したいだろw」と思ってましたが、案外最初の4~5タブをみるだけでそれなりに、満足のいく情報を得られる。

しかも検索結果にいちいちブラウザバックしなくて良いので、情報収集スピードも速くなる。


[Cake raises $5 million for a swipeable mobile browser](https://techcrunch.com/2018/01/30/cake-raises-5-million-for-a-swipeable-mobile-browser/)
このTechCrunchの記事で言われてるのは、

> “Browsers today are still very similar today to what they were 15 years ago,” explains Hulet. “They weren’t reimagined for mobile – they’re basically desktop experiences crammed onto a mobile phone,” he says.

確かに検索UIには検索結果が必ずないとダメだよねっていう固定概念はあった・・・
実際3日ほどChromeの代わりに使ってみて、あまり不自由していない、むしろ結構使いやすいので、デフォルトブラウザでも良いかなと思っているところ。

ちなみにアイコンがおしゃれで、ドックに置いておきたくなるアプリでもあります。
Scrapyのログ出力方法を独自のものに変更する方法

# 問題点

Scrapyはログ出力のフォーマットを変更する程度なら設定ファイルをいじるだけで簡単に出来るが、
ログ出力の方法そのものを（メール送信などに）変更する方法が公式ドキュメントで見当たらず困った。

# 結論

以下のようなPython Scriptを書いたら出来た。

+ Scrapyがルートロガーを追加するのを抑止する
+ ルートロガーをプログラムで追加する
+ Spiderを起動する

通常通りコマンドラインなどを使用して起動するとScrapyがルートロガーを追加してしまうので、Spiderを起動するPython Scriptを自前で書いてルートロガーを制御した上で起動する必要がどうしてもありそう(このあたりよく分からず)

# ScrapyのロガーをDjangoのものに変更する例

今回はDjangoのカスタムコマンドから、Scrapyを起動したのでその例。
Djangoにはエラーログをメールで送ってくれるロガーがついており、スクレイピングに失敗したらメールを飛ばしてくれるのがなかなか便利。
`logging.root.addHandler(handler)`の部分を変更すればお好みのLoggerが使用できると思う。


```python3
# -*- coding:utf-8 -*-
import os
import sys
from django.conf import settings
from django.core.management.base import BaseCommand
# 今回はcrawlerを別ディレクトリにおいていたので、Pythonのパスに追加
sys.path.append(os.path.join(settings.BASE_DIR, "crawler"))
from scrapy.crawler import CrawlerProcess
from scrapy.utils.log import configure_logging
import logging.handlers
from crawler import settings as scrapy_settings

class Command(BaseCommand):
  def handle(self, *args, **options):
    # ルートロガーへの追加を抑止
    configure_logging(install_root_handler=False)
    # Djangoのロガーから、ログハンドラーを取得してルートロガーに追加する
    handlers = logging.getLogger("standard").handlers
    for handler in handlers:
      logging.root.addHandler(handler)

    process = CrawlerProcess({key:getattr(scrapy_settings, key) for key in dir(scrapy_settings) if key[0].isupper()}, # Scrapy用のsettingsモジュールを辞書形式にして渡す
                             install_root_handler=False # ルートロガーへの追加を抑止
    )
    process.crawl(起動したいSpiderクラス)
    process.start()
```
SCNFloorにテクスチャを設定する


### はじめに

SCNFloorのテクスチャ の設定につまづいたのでメモしておく。

通常、何も設定しないと下記のイメージのような無機質な床が表示される。
![IMG_0111.png](https://qiita-image-store.s3.amazonaws.com/0/200963/4c393ea5-b66e-a2c0-5fb5-a1ca1edb805b.png "IMG_0111.png")


SCNNodeのテクスチャはfirstMaterialプロパティの[diffuse](https://developer.apple.com/documentation/scenekit/scnmaterial/1462589-diffuse)で設定することができる。
そのため、SCNFloorでも次のようにテクスチャを設定してみると、テクスチャ画像が引き伸ばされて表示されて思い通りに表示されなかった。

``` Swift
let floor = SCNFloor()
floor.firstMaterial?.diffuse.contents = UIImage(named: "art.scnassets/textures/grass.jpg")
let floorNode = SCNNode(geometry: floor)
scene.rootNode.addChildNode(floorNode)
```

![IMG_0113.png](https://qiita-image-store.s3.amazonaws.com/0/200963/5e8d9671-f222-ed36-df77-b66c2e4b4224.png "IMG_0113.png")


### 原因と対応
diffuseに設定した画像は指定が無ければその面に合わせて自動的に引き伸ばしがされることが原因。
画像のサイズを指定してやれば、引き延ばしで埋めるのではなく画像をタイルのように繰り返しあてはめて埋めるようになる。
したがって、SCNMatrix4MakeScaleで実際のテクスチャ画像と同じサイズを指定してやれば良い。


``` diff 
let floor = SCNFloor()
floor.firstMaterial?.diffuse.contents = UIImage(named: "art.scnassets/textures/grass.jpg")
+ floor.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(128, 128, 0)
let floorNode = SCNNode(geometry: floor)
scene.rootNode.addChildNode(floorNode)
```

![IMG_0112.png](https://qiita-image-store.s3.amazonaws.com/0/200963/9ae62d82-7a57-af08-6993-1d95852fb4b6.png "IMG_0112.png")
LPICレベル1 101試験合格手記

# LPICレベル1 101試験合格手記

## 購入した本

[Linux教科書 LPICレベル1 スピードマスター問題集 Version4.0対応](https://www.amazon.co.jp/Linux%E6%95%99%E7%A7%91%E6%9B%B8-LPIC%E3%83%AC%E3%83%99%E3%83%AB1-%E3%82%B9%E3%83%94%E3%83%BC%E3%83%89%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E5%95%8F%E9%A1%8C%E9%9B%86-Version4-0%E5%AF%BE%E5%BF%9C-%E6%9C%89%E9%99%90%E4%BC%9A%E7%A4%BE%E3%83%8A%E3%83%AC%E3%83%83%E3%82%B8%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3/dp/4798141895/ref=sr_1_1?ie=UTF8&qid=1517750577&sr=8-1&keywords=lpic)

## もう一夜漬けで試験にしかないそこのあなたへ

### **重要度★★★ -> 章末模擬試験 -> 重要度★★ の順に丸暗記しましょう!**

★★★ ... 60%
★★ ... 5%
★ ... 0%
章末模試 ... 30%
未知 ... 5%

感覚値ですがこんな配分です。
（たまたま運がよかったのかもしれませんが...）

本当に知識がつくかはともかく、★★★と章末問題を

- 問題と答えを丸暗記する
- 「記述できるようにしましょう」を全部覚える<br>

だけで合格ボーダーは超えるかと思います。

## 勉強方法/感想
もともと簡単なwebサーバー(LNMP)や会社の研修程度しかLinuxは触っておりませんでした。第６章の「ファイル管理」まではなんとか腹落ちできたのですが、第７章の「ソフトウェア管理」、８章の「システムアーキテクチャ」はこのテキストだけだと少し厳しかったです。そもそもLinuxとは、の基礎の部分から固めた方が、より知識が身につくと感じました。

[1週間でLPICの基礎が学べる本 第2版 (徹底攻略)](https://www.amazon.co.jp/dp/4844335308/)

基礎固めにはこちらの本が良さそうなので、購入してみたいと思います。やはりコマンドを調べてコピペしてきた身としては試験内容を本当に理解するのは難しいことを痛感しております（汗）。
配列　

#配列とは
<dl> 
 <dd><strong>配列とは</strong></dd>
　　<dd>同一種類の複数データを順序を付けて格納する箱</dd>
　 <dd><strong>注意点</strong></dd>
　　<dd>・順序付けは、「０」からスタートする</dd>
　　<dd>・１つの箱には同一種類のデータしか格納出来ない</dd>
</dl>

#配列の作成

<dl> 
 <dd><strong>作成順序</strong></dd>
　　<dd>①配列変数の作成（箱の作成）</dd>
<code>要素のデータ型[]　配列変数名;</code>
 <dd></dd>
　　<dd>②要素の作成と代入（中身の作成）</dd>
 <code>配列変数名 = new 要素のデータ型[要素数]　;</code>   ※newを使用する場合
</dl>

<dl> 
 <dd><strong>箱と中身の作成を同時に行う場合</strong></dd>
 <dd></dd>
<code>要素のデータ型[]　配列変数名 = new 要素のデータ型[要素数]　;</code>
</dl>

#配列の初期値
<dl> 
 <dd>変数と違って、配列は<strong>初期値が決まってる！</strong></dd>
 <dd>初期値は以下の通り</dd>
</dl>

| データの種類 　　　　　　　　　| 初期値 | 
|:----------|--------:|
|数値型        |0|
|boolean型    |false|

#配列の初期化

 <dd>以下の表記で配列の新規作成と初期化が出来る</dd>
　　<dd><strong>省略した書き方①</strong></dd>
`要素のデータ型[]　配列変数名 = new 要素のデータ型{初期値1,初期値2,初期値3,初期値4,・・・}　;`

　<dd><strong>省略した書き方②</strong></dd>
`要素のデータ型[]　配列変数名 = {初期値1,初期値2,初期値3,初期値4,・・・}　;`

#配列をfor文で使用する
<dd><strong>使用例</strong></dd>
```
int[] score = {20,30,40,50,80};
	for (int i = 0; i<score.length; i++) {
	  System.out.println(score[i]);
    {
```
<dd>・20、30、40、50、80が順に表示される</dd>
<dd>・<code>score.length</code>には「５」が入る</dd>
<dd>・<code>i</code>には「０〜４」までが入る</dd>

<dd><strong>書き方</strong></dd>
`for(int i = 0; i<配列変数名.length; i++)`

#拡張for文

<dd><strong>書き方</strong></dd>
`for(要素の型 任意の変数名:配列変数名){
 }`
<dd>→ループが１週する度、変数の中身が更新される</dd>

#配列が裏でどのように処理されているか
<dd><strong>まずはじめに・・・</strong></dd>
`int[] score =new int{5}が実行された場合`
<dd>　①メモリ上にint型の要素を５つ持つ配列が作成される</dd>
<dd>　②int[]型の配列要素、scoreがメモリ上に作成される</dd>
<dd>　③scoreに配列の先頭（０）の、メモリ上の位置情報が代入される</dd>

<dd><strong>その後・・・</strong></dd>
`プログラム上でscore{２}`が実行された場合`
<dd>　④scoreの先頭（０）の、メモリ上の住所が検索される</dd>
<dd>　⑤先頭から{２}個目のメモリの読み書きをする

#ガベージコレクション
<dd>通常、ifブロック内で作成した変数はブロックが消えたら適用されない。</dd>
<dd>newで確保された要素たちは、ブロックが終了しても消えずに、メモリ上にゴミとなって残り続ける。</dd>
<dd>これらを自動で削除してくれるJavaの機能が、<strong>ガベージコレクション。</strong></dd>

#null値
```
	  if ( b== true) {
		int[] i = {1,2,3};
        i=null;
	   }
```
以上の様に、null値を代入することで、変数の値が格納されたメモリへ参照しなくなる

#多次元配列
<dd>２次元配列の宣言</dd>
`要素の型[][] 配列変数名 = new 要素の型[行数][列数]`

<dd>２次元配列の要素の利用時の記載方法</dd>
`配列変数名[行の番号][列の番号]`

<dd>２次元配列の初期化方法</dd>
`要素の型[][] 配列変数名 = {//１行目{//１列目　要素数　//２列目　要素数 //3列目要素数・・},//２行目{},//3行目・・・}`
~/.aws/(config|credentials) の設定から assume roleするラッパーをgolangで実装して、goreleaserでリリースしてみた

最近のgolangのCI周りを勉強する目的で、fujiwaraさんの[aswrap - ~/.aws/(config|credentials) で定義した AssumeRole 定義から一時キーを取得してコマンドを起動してくれる wrapper] (http://sfujiwara.hatenablog.com/entry/2017/12/13/122952)をgolangで再実装してみた。

-> https://github.com/masahide/assumer

まだMFA対応のtodoが残ってたり本家より劣化しているところはありますが、一時キーのキャッシュ保存に対応させたり、rpm,deb,brewのパッケージを作成したので導入が簡単なところぐらいが少ない取り柄

## 今回やりたかったこと/やったこと

* [goreleaser](https://github.com/goreleaser/goreleaser)を使ってrpm,deb,homebrewのパッケージのリリースを自動化
* [codecov.io](https://codecov.io)でカバレッジの可視化
* [gometalinter](https://github.com/alecthomas/gometalinter)で行単位でのignore設定


## [goreleaser](https://github.com/goreleaser/goreleaser)

golang製のソフトウェアのリリース処理を全部引き受けてくれてる便利なツールです。具体的には・・

* goのクロスコンパイル
* バイナリのtar.gzアーカイブやrpm,debパッケージ、dockerイメージの作成
* github.comの[Github Releases](https://github.com/masahide/assumer/releases)への添付
* dockerhubへの登録
* homebrewのFormula作成
などかなり幅広く対応しています。

使い方に関しては、 [goreleaserを使ってGoで書いたツールのバイナリをGithub Releasesで配布する
](http://blog.shibayu36.org/entry/2017/10/04/193000) を参考にしつつ、goreleaser自身の[.travis.yml](https://github.com/goreleaser/goreleaser/blob/master/.travis.yml) や [.goreleaser.yml](https://github.com/goreleaser/goreleaser/blob/master/.goreleaser.yml)がとても参考になるのでこの辺りを真似ながらで基本的に問題ないかと。


## [codecov.io](codecov.io)でカバレッジの可視化

以前、 [golangの静的解析,カバレッジ解析,バイナリリリースをCircleCIで簡単に整える](https://qiita.com/yamasaki-masahide/items/4f7db9ba3a15411dd6b3)で使った[coveralls](https://coveralls.io)より導入が簡単だった。
事前にcodecov.ioでトークンを取得して、travisのenvに`CODECOV_TOKEN`として設定しておいて、あとは、基本的にはこちらもgoreleaserの[.travis.yml](https://github.com/goreleaser/goreleaser/blob/master/.travis.yml)を参考にしましたが

```yaml:.travis.yml
after_success:
  - bash <(curl -s https://codecov.io/bash)
```
これだけで良いみたいですね。 


## [gometalinter](https://github.com/alecthomas/gometalinter)で行単位でのignore設定

gometalinterで様々な静的解析が走るけどその解析ツール毎にignoreを設定するのは大変だなぁと思ってたんですが・・・

https://github.com/masahide/assumer/blob/master/cmd/assumer/main.go#L170

```go
defer cf.Close() // nolint errcheck
```

のように行単位で`// nolint <解析ツール名>` でチェックを除外できるようです。
[comment-directives](https://github.com/alecthomas/gometalinter#comment-directives) に記載されてます。
Ripple Developer Center 解説 Fee Voting

#引用元の記事
https://ripple.com/build/fee-voting/

#Fee Voting
バリデータは，reserve requirements(いずれ別記事で解説するかも)と同様にトランザクションの手数料も投票で変更することができます。
バリデータのコンフィグ上の設定がRippleネットワークの現在のコンフィグと異なる場合，バリデータは周期的に自身の設定をRippleネットワークに対して発信します。
※preferencesをなんと訳せば良いかわかっていないです。。。
一定数のバリデータがその変更に賛成した場合，その変更を反映させます。
このような変更は様々な理由で行われ，例としては長期的なXRPの価格の変更による調整が挙げられます。
※XRPの価格が30円から1000円に変わったらトランザクションの手数料も変更したいと考える，ということですよね。Rippleはトランザクションの手数料で儲けるというビジネスモデルではないため，手数料は可能な限り小さく調整していくと推測しています。

トランザクションの手数料やreserve requirementsは，rippledにおける「rippled.cfg」というコンフィグファイルの[voting]のセクションで設定することができます。
【参考】
https://github.com/ripple/rippled/blob/develop/doc/rippled-example.cfg
931行目付近

注意：不適切な変更の要求は，RippleネットワークをDOS攻撃にさらす恐れがあります。
※RippleネットワークではDoS攻撃に対しては手数料を調節することで，攻撃を防ぐ効果があるとのことなので，あまり変な手数料に変更するとDoS攻撃を防ぐ効果が弱まってしまうのかもしれないですね。このあたりはいずれ仕組みをしっかり勉強したいところです。

手数料について変更可能なパラメータは下記のとおりです。

①reference_fee
トランザクションを送信される際に破棄されるXRPの量。
※Rippleネットワークでは手数料はマイナーの収益になるのではなく，破棄され，誰もアクセスすることができなくなります。

②account_reserve

③ owner_reserve
Mac版Keyhacでアプリごとにまとめてキーバンド設定

みなさんEmacs使ってますか？ 私はもはやエディタのEmacs自体は使ってないけど指が永遠のEmacs派です。atomでもまず[atomic-emacs](https://atom.io/packages/atomic-emacs)を入れます。

ということで私物のMacでは[Karabiner](https://pqrs.org/osx/karabiner/)を使ってるもののなんか微妙に思い通りにならず(設定が悪いだけかも)、会社でWindowsからMacに乗り換えたのを機にWindowsでも使っていた[Keyhac](https://sites.google.com/site/craftware/keyhac-ja)のMac版を試してみました。KeyhacはPythonで設定をかなり柔軟に書けるのが魅力です。

基本的にはWindows版とまったく同じように使える……のですが、キーバインドをアプリごとに変えるところで若干躓きが。
複数のアプリをまとめて設定するために例えば[ここ](https://gist.github.com/emkjp/b5bc24be91b94d718b30)のように

```python:config.py
def is_im_target(window):
    if window.getProcessName() in ("cmd.exe",            # cmd
                                   # ……
                                   "MobaXterm.exe"):     # MobaXterm
        return True
    return False

keymap_im = keymap.defineWindowKeymap(check_func=is_im_target)
```

`defineWindowKeymap`メソッドの`check_func`引数にアプリを判定する関数を指定してやれば良いのですが、Macでは`window.getProcessName()`が使えません。
んで調べてみると[開発者が答えていて](https://github.com/crftwr/keyhac/issues/5)、微妙にわかりづらいんですが要は

```python:config.py
def is_emacs_target(app):
    # Mac版ではこうやってアプリ名を取得
    if ckit.getApplicationNameByPid(app.pid) \
        in (
        # ここでは除外したいアプリ名を列挙
        "com.apple.Terminal", # terminal
        ):
        return False
    return True

keymap_emacs = keymap.defineWindowKeymap(check_func=is_emacs_target)
keymap_emacs[ "Ctrl-P" ] = "Up"                  # Move cursor up
```

プロセスIDを取得→`ckit.getApplicationNameByPid`に渡す、と。めでたしめでたし。
WEKAの使い方

#WEKAとは

[機械学習統合環境 Wekaと ベンチマークデータ - 山本 研究室](http://www.iip.ist.i.kyoto-u.ac.jp/member/akihiro/Weka12.pdf)
>フリーの機械学習統合環境
- 研究，教育，実務など幅広い利用が可能
- データの前処理，多様な学習アルゴリズム，評価手法の理解ができる．
- データの可視化などのGUIを備えている

だそうです．
初めて機械学習に触れるには手っ取り早い方法です．
自分で取ってきたデータを様々な機械学習アルゴリズムで分類することができます．

#インストール
以下のリンクから，自分のOSに合わせてダウンロード
[Weka 3](https://www.cs.waikato.ac.nz/ml/weka/downloading.html)

![スクリーンショット 2018-01-28 16.07.48.png](https://qiita-image-store.s3.amazonaws.com/0/102996/94020c83-73b0-e25f-8005-f46b839881e5.png)

#分類するデータの用意
WEKAは自分が用意したデータを読み込んで分類することができます．
この際，arffと呼ばれる形式にする必要があります．

```test.arff
@relation keyboard

@attribute time real
@attribute speed real
@attribute angle real
@attribute curve real
@attribute emotion {sad, happy}

@data
1,0.1,46,1.81,sad
2,0.6,187,4.7,happy
```

###```@relation [文字列]```
keyboardがデータセットの名前です．
好きなように設定します．

###```@attribute [属性の名前] [属性の型]```
属性の名前と属性の型を記述します．
属性の型は，データが数値の場合は，real．
そうでない場合は，{}で囲みます．
また，分類したいものを最後に記述します．

###```@data```
これ以降に，自分のデータを入力します．
自分が記述した属性データに合わせて記述します．
今回は，time, speed, angle, curve, emotionの値が1行に入ります．

#決定木で機械学習
1. Explorerを開きます
![スクリーンショット 2018-01-28 16.07.48.png](https://qiita-image-store.s3.amazonaws.com/0/102996/e8d73f23-f65c-c01b-8437-b54612bbd709.png)

2. Open fileから先ほど作成したtest.arffを選択
![スクリーンショット 2018-01-28 16.31.04.png](https://qiita-image-store.s3.amazonaws.com/0/102996/e9ce4f50-06b6-aa10-1de1-13368cbf1566.png)

3. Classifyタブを選択
![スクリーンショット 2018-02-04 19.47.38.png](https://qiita-image-store.s3.amazonaws.com/0/102996/faf65862-f369-7f1a-a45c-f242e8edfce6.png)

4. Chooseからweka>classifiers>trees>J48を選択
![スクリーンショット 2018-02-04 19.47.38 2.png](https://qiita-image-store.s3.amazonaws.com/0/102996/ed735b05-c8ca-fd9c-0704-6b64d6785ced.png)
![スクリーンショット 2018-02-04 19.52.11.png](https://qiita-image-store.s3.amazonaws.com/0/102996/45783368-9d79-447f-beb7-29f88968896d.png)

5. Test optionでどんな検定をするか設定できます．デフォルトだと10分割交差検定．
![スクリーンショット 2018-02-04 19.53.15.png](https://qiita-image-store.s3.amazonaws.com/0/102996/8ee3dfa5-8191-2431-65df-b32de1c49544.png)

6. Test optionの下に表示されているものが，分類される対象のデータとなります．
test.arffの属性の最後の行に記述されているものが表示されますが，タップして変更することもできます．
![スクリーンショット 2018-02-04 20.00.36.png](https://qiita-image-store.s3.amazonaws.com/0/102996/98b9f60a-d020-592d-9146-ae17412974df.png)

7. Startボタンを押すだけ！

SummaryのCorrectly Classified Instancesに書かれているのが，分類精度となります．
今回だと，79.1683%です．

![スクリーンショット 2018-02-04 20.03.37.png](https://qiita-image-store.s3.amazonaws.com/0/102996/0eb740c5-7c9e-f589-366b-3196a69f852c.png)

#まとめ
WEKAを初めて使う際の参考になれば幸いです．
Classifierを選択する際に他のものを選択するだけで，SVMやRandom Forestなども簡単にできます．
Google Cloud Speech API on Windows 10 Nodeを使うときに困ったこと

最近Google Cloud Speech APIをNodeで触り始めました。
サンプルを動かしながら覚えていこうとしていたのですが、
すんなりと動いてくれませんでした。。。
今回はWindows環境でサンプルを動かすまでの設定を紹介します。

# 直面したエラー

```
Listening, press Ctrl+C to stop.
events.js:183
      throw er;  Unhandled 'error' event
Error: spawn rec ENOENT
    at _errnoException (util.js:1022:11)
    at Process.ChildProcess._handle.onexit 
```

# 今回の環境
OS:windows 10
Node:8.9.4
SoX:14-4-2
node-record-lpcm16:0.3.0
google-cloud/speech:1.0.1
[サンプルコードページ：音声ストリームでのストリーミング音声認識](https://cloud.google.com/speech/docs/streaming-recognize?hl=ja#speech-streaming-mic-recognize-nodejs)

# 対策
## 1.node-record-lpcm16を使うときはrecordProgramに'sox'を指定する
recordProgramはサンプルコードでは'rec'になっていますが、
Windows環境で'sox'を設定してください。

## 2. node-record-lpcm16のindex.jsを書き換える
node-record-lpcm16のindex.jsの29行付近を下記のように書き換えてください。

```javascript:index.js
// Capture audio stream
  var cmd, cmdArgs, cmdOptions
  switch (options.recordProgram) {
    // On some Windows machines, sox is installed using the "sox" binary
    // instead of "rec"
    case 'sox':
      // ---- 追記ここから ----
      cmd = 'sox'
      cmdArgs = [
        '-q',                                     // show no progress
        '-t', 'waveaudio',                        // input-type
        '-d',                                     // use default recording device
        '-r', options.sampleRate.toString(),      // sample rate
        '-c', '1',                                // channels
        '-e', 'signed-integer',                   // sample encoding
        '-b', '16',                               // precision (bits)
        '-t', 'raw',                              // output-type
        '-'                                       // pipe
      ]
      break
      // ---- 追記ここまで----
    case 'rec':
    default:
      cmd = options.recordProgram
      cmdArgs = [
        '-q',                     // show no progress
        '-r', options.sampleRate, // sample rate
        '-c', '1',                // channels
        '-e', 'signed-integer',   // sample encoding
        '-b', '16',               // precision (bits)
        '-t', 'wav',              // audio type
        '-',                      // pipe
            // end on silence
        'silence', '1', '0.1', options.thresholdStart || options.threshold + '%',
        '1', options.silence, options.thresholdEnd || options.threshold + '%'
      ]
      break
    // On some systems (RasPi), arecord is the prefered recording binary
```
デフォルトのcmdArgsに2つオプションが足りないようです。
'-t', 'waveaudio',                        // input-type
'-d',                                     // use default recording device

この対策を行った結果サンプルコードが動かせるようになりました。

# 参考
https://github.com/gillesdemey/node-record-lpcm16/issues/8
https://github.com/gillesdemey/node-record-lpcm16#options
コマンドラインを使ってソフトウェアアップデートをリモート実行する方法を検証してみた。

## なんでそんなことしようと思ったのか

自分の家でMacを熟知しているのが自分以外いないのでソフトウェアアップデートしてくれとかいうと

「全然わかんないからやって:frowning2:」と言われるのでなるべくコマンドを使って一発更新出来るようにしたいなと思いました。

## 検証した環境

対象のMac：MacbookAir (mid 2013)
OS：MacOS 10.13.3(High Sierra)

## やり方

下準備としてMacをローカルネットワークでssh出来るようにRemoteLoginをオンにしておく

![Image 2018-02-04 20-23-06.png](https://qiita-image-store.s3.amazonaws.com/0/89244/6e931871-bcef-1a83-5165-733ae5e2d3c9.png)

自分のターミナルからsshでログインします。

入れるアドレスは、このコンピュータにログインするには”hoge＠hoge"と入力してくださいという欄を入力

OSのアップデートなどはAdministerの権限がないと行けないのでsudoが使えるアカウントで実施してください。

```
$ssh User＠HostName.local
```

ログインが出来たらsoftwareupdarteコマンドでAppStoreでインストールができるリストを確認


```
$ softwareupdate --list
```

今回の場合はOSのアップデート情報と、iTunesが出ました。

```
出力例

$ softwareupdate --list

Software Update Tool

Finding available software
Software Update found the following new or updated software:
   * macOS High Sierra 10.13.3 Update-
	macOS High Sierra 10.13.3 Update ( ), 1925876K [recommended] [restart]
   * iTunesXPatch-12.7.3
	iTunes (12.7.3), 180272K [recommended]

```

特定のインストールを行いたい場合は*が付いている箇所をコピーして実行します。

例：iTunesをインストールする場合

```
$ softwareupdate -i iTunesXPatch-12.7.3
Software Update Tool

Downloading iTunes
Downloaded iTunes
Installing iTunes
Done with iTunes
Done.
```

また一括でインストールを実施したい場合は -iaオプションで実行できます。
※基本的には全部インストールをすることが良いですが、一度 --listで確認してから実施してください。

```
$ softwareupdate -ia
```

OSのインストールをする場合は再起動が必要な場合があるのでリモートのMacが再起動してもいい状態の場合はリブートして完了です。

```
$ sudo reboot
```

## 感想

１台なら特にこれをやらんでもいいかもしれない。だかCLIが好きな人間としてはこういう方法もあるんだなといい勉強になりました。

今度はこれを自動化して自動アップデートにしたいですね。

## 参考にしたリンク

[コマンドラインを使ってソフトウェアアップデートをリモートインストールする方法](https://support.apple.com/ja-jp/HT200113)
Raspberry Pi での Node-RED 利用

# Raspberry Pi での Node-Red 利用
Raspberry Pi で Node-RED の管理画面へ接続する方法を記載します。

## Node-RED の起動
Node-RED を起動します。
[Raspberry Pi での Node-RED 起動](https://qiita.com/minatomirai21/items/55141cd5b3e06a166ff5)

## 接続先の確認
ブラウザからアクセスする管理画面の情報を確認します。
Node-RED 起動に表示されている「[info] Server now running at」のURL末尾「:」以降を控えます。
下記の場合「1880」です。

~~~
$ node-red-pi --max-old-space-size=256
4 Feb 20:47:46 - [info]

Welcome to Node-RED
===================

4 Feb 20:47:46 - [info] Node-RED version: v0.18.1
4 Feb 20:47:46 - [info] Node.js  version: v6.12.3
4 Feb 20:47:46 - [info] Linux 4.9.79-v7+ arm LE
4 Feb 20:47:48 - [info] Loading palette nodes
4 Feb 20:47:54 - [info] Settings file  : /home/pi/.node-red/settings.js
4 Feb 20:47:54 - [info] User directory : /home/pi/.node-red
4 Feb 20:47:54 - [warn] Projects disabled : set editorTheme.projects.enabled=true to enable
4 Feb 20:47:54 - [info] Flows file     : /home/pi/.node-red/flows_raspberrypi.json
4 Feb 20:47:54 - [info] Starting flows
4 Feb 20:47:54 - [info] Started flows
4 Feb 20:47:54 - [info] Server now running at http://127.0.0.1:1880/
~~~

## 管理画面の表示
Raspberry Pi のデスクトップ上から直接アクセスする場合、ブラウザから「 http://127.0.0.1:1880/ 」にアクセスします。
他の端末からアクセスする場合、Raspberry Pi のIPアドレスと上記で控えた番号を組み合わせたURLにアクセスします。
Raspberry Pi のIPアドレスが 192.1668.1.1 で上記の表示内容場合、「 http://192.1668.1.1:1880/ 」となります。

## その他
[Node-RED アップデート](https://qiita.com/minatomirai21/items/2bccb1a76e0e9651d227)
[Node-RED 認証有効化](https://qiita.com/minatomirai21/items/6a7e38456bbce1de8cee)
[Node-RED の表示言語](https://qiita.com/minatomirai21/items/d8a5e72a51657ddcfa3e)
ブラウザで環境操作を間違えない為のユーザスクリプトを導入してみる

# はじめに
実装や設定ミスなどで、開発環境やステージング環境でテストしていたつもりが、本番環境で操作していたなんてことが稀に発生したりします。

インシデントを未然に防ぐ為に、取扱注意な画面が表示された場合、ユーザスクリプトでブラウザにタグを挿入してユーザに警告を表示する仕組みを作ります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/104642/b075da3d-1494-9145-7289-d864edd0a336.png)

# ユーザスクリプト
ChromeであればChromeアプリの[Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=ja)。Firefoxならアドオンの[Greasemonkey](https://addons.mozilla.org/ja/firefox/addon/greasemonkey/)などで実行可能です。今回はChromeでの方法を紹介します。


## Tampermonkeyのインストール
Chromeアプリの[Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=ja)をインストールします。「CHROMEに追加」をクリックするだけです。インストールが完了すると、URLの隣にこんなアイコンが表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/104642/b7189093-73b5-d026-760b-80c8e5d96521.png)

## Tampermonkeyの設定
アイコンをクリックして、「新規スクリプトを追加...」をクリック。以下のソースを追記して上書き保存。有効にして完了です。

今回は仮にgoogleさんの環境ごとのURLが以下の想定での設定です。
`http://www.google.co.jp`に遷移すると画面上部に赤い帯状のものが表示されることがわかります。クリックすると非表示になるような処理になっています。

- 本番　　　　：`http://www.google.co.jp`
- ステージング：`http://stg.www.google.co.jp`
- 開発　　　　：`http://dev.www.google.co.jp`

```javascript
// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.google.co.jp/
// @grant        none
// ==/UserScript==

(function () {
    var config = [
        // google
        ['www.google.co.jp',        "#faa", "【※※※　本番環境っすよ！ ※※※】"],
        ['stg.www.google.co.jp',    "#afa", "ステージング環境"],
        ['dev.www.google.co.jp',    "#aaf", "開発環境"],
    ];

    function appendBanner(bgColor, message) {
        var newHTML         = document.createElement ('div');
        newHTML.innerHTML   = '<div id="serverEnv" style="display: block; position: fixed; top: 0; width:100%; z-index: 10000; opacity: 0.7; background-color:' + bgColor +'" onclick="this.style.display=\'none\';"><p style="font-size:12px; height:50px; text-align:center; height: 50px; line-height: 50px;">' + message + '</p></div>';

        document.body.appendChild (newHTML);
    }

    for (var i = 0; i < config.length; i++ ) {
        if (document.domain == config[i][0]) {
            appendBanner(config[i][1], config[i][2]);
        }
    }
})();
```

# 終わりに
今回のサンプルはdivタグを挿入しただけですが、javascriptなんで自分好みに簡単にカスタマイズが可能です。また、上記のコードとは別に`@include`でURLを判別する方法などもあります。

# 参照
- Metadata Block - GreaseSpot Wiki https://wiki.greasespot.net/Metadata_Block
- UserScriptの書き方メモ http://www.m-bsys.com/code/userscript-memo
(Ruby)標準ライブラリのcannot load such file

開発環境はMac、Deploy先はCentOSでRailsアプリの開発をしてます。
今回、標準ライブラリのrequireで*"cannot load such file"*が発生した原因を記しておきたいと思います。

# 結論
該当エラーが発生した原因はOSの違いによるものでした。
Mac・Windowsは大文字・小文字を区別しないため、下記は区別されません。

```ruby:sample.rb
  require 'RSS'
  require 'rss'
```
しかし、Linuxでは大文字・小文字が識別されます。
開発環境(Mac)でライブラリ名を大文字で指定していたため、Deploy先でエラーが発生していました。


※以前からOSによる大文字・小文字の違いについては認識していたのですが、環境構築中での発生だったため原因特定に時間を要してしまいました・・・。自身への教訓のためと、同じ事象でハマっている人の参考になればと思い記事を作成しました。
PCのキッキング、そこそこいけてる環境を最速で構築

# この記事について
この記事は、平凡なエンジニアが新しいパソコンで仕事をする準備を備忘録的に淡々とメモしたものです
過度な期待はしないで下さい

筆者は環境にこだわりは特になく、誰でも作れるまずまずの環境を目標にしています
そのため細かい設定などは必要なく、丁寧な解説もしていません
また、shellにfishを採用しており、カスタマイズしたzshを手放せない方などにはおすすめできません

概ね下記の準備を行います

- コミュニケーションツールなどエンジニアに限らないオフィスワーク用のキッキング
- rubyの開発環境基礎
- フロントエンド開発環境基礎(react, Angular, Vueなど)

# 作業を行ったPC
MacBook Pro (13-inch, 2017, Four Thunderbolt 3 Ports)
macOS High Sierra
version 10.13.1

## オフィスワーク用キッキング
- Chromeインストール
- Apple IDログイン
- [Magnet(筆者的にmacでの作業に必須アプリ)](http://www.howknow.link/entry/magnet)
- Dropbox(筆者は他のPCとの設定、下記KeePassXのDB共有などに使用する)
- KeePassX
- Slack
- カレンダーに仕事用googleアカウントを連携
- Dockを最小限にする

## エンジニアリング用キッキング
- 基礎
    - Xcodeインストール
    - iTerm2
    - brew
    - fish
- ruby周り
    - rbenv
    - ruby-build
    - readline
- DB周り
- フロントエンド周り

# エンジニア用キッキング
## Xcodeインストール
Xcodeは使わなくても、含まれるものはよく使う
App Storeからインストールし、初回起動で規約同意まで済ます
__※５GBを越えるため、DL・インストール完了まで非常に時間がかかる__

## iTerm2
デフォルトのターミナルより断然使いやすい、必須と言っていい
インストールするだけ

## brew
これがなければ始まらない

```bash
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

## fish関連
### fish
bash, zshなどあるが、細かい設定なしに補完など使用できる上、
oh-my-zshのように重くもないし、将来のカスタマイズを邪魔しないため、標準shellにfishを採用

```bash
brew install fish
echo "/usr/local/bin/fish" | sudo tee -a /etc/shells
chsh -s /usr/local/bin/fish
```

### fisherman
fish拡張のプラグインなど便利に扱うためのもの
遅かれ早かれ入れることになるので、早速入れる

```bash
curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisherman
fisher up
```

### shellをもっとモダンにしたいなら
Qiitaの偉大な先人の記事を参考にしてください
https://qiita.com/susieyy/items/ac2133e249f252dc9a34

## ruby周り
```bash
brew install rbenv ruby-build readline
```

### fish・fisherから使用するために
```bash
fisher rbenv
```

### localで使用する特定verのrubyをインストール
```bash
rbenv install VERSION
rbenv local VERSION
```

## DB
今回はmysql

```
brew install mysql
```

特にversion指定や設定変更せず

### DB管理tool Sequel Pro
下記URLからダウンロード
https://www.sequelpro.com/

## front
- nodeパッケージマネージャー
- nodejs
- yarn

### nodeパッケージマネージャー
```bash
fisher fnm
```

### nodejs
```bash
fnm VERSION
```

### yarn
```bash
brew install yarn
```

# 最後に
この記事に含むのは、基礎基本でしかありません
カスタマイズはできるので必要に応じて各人で行ってください

もっと便利にしたいなとは思っているので、導入が簡単で、メンテをほとんど必要としない便利ツールなどあればぜひ教えて欲しいです
Node.jsでMQTTブローカーを立てて、ブラウザから確認する


[Nefry BT（ESP32）でMQTTを使ってみよう Subscribe編](https://dotstud.io/blog/nefry-bt-connect-mqtt/)などでMQTT実装をNode.jsで試してみましたが、Web側で情報を受け取るためにはBrokerサーバーにHTTPサーバーも載せて実装する必要があります。

[MQTT over Websockets](https://github.com/mcollina/mosca/wiki/MQTT-over-Websockets)などを参考に作ってみました。

## Broker+Webサーバーの準備

Webサーバー（のフレームワーク）としてexpress、Brokerサーバーとして[mosca](http://www.mosca.io/)を利用します。

```
npm i --save express mosca
```

```broker.js
'use strict';

const express = require("express");
const http = require('http');
const mosca = require('mosca');

const HTTP_PORT = 3000;
const MQTT_PORT = 1883;

const app = express();
const httpServer = http.createServer(app);
const broker = new mosca.Server({port: MQTT_PORT});

broker.on('ready', () => console.log('Server is ready.'));
broker.on('clientConnected', client => console.log('broker.on.connected.', 'client:', client.id));
broker.on('clientDisconnected', client => console.log('broker.on.disconnected.', 'client:', client.id));
broker.on('subscribed', (topic, client) => console.log('broker.on.subscribed.', 'client:', client.id, 'topic:', topic));
broker.on('unsubscribed', (topic, client) => console.log('broker.on.unsubscribed.', 'client:', client.id));
broker.on('published', (packet, client) => {
    if (/\/new\//.test(packet.topic))return;
    if (/\/disconnect\//.test(packet.topic))return;
    console.log('broker.on.published.', 'client:', client.id);
});

app.get('/',(req,res) => res.sendfile('./index.html'));

broker.attachHttpServer(httpServer);
httpServer.listen(HTTP_PORT);
```

これで起動すると、 1883ポートでBrokerサーバーが起動しつつ、そこでPubliserから受けたパケットは3000ポートで待ち受けてるWebSocket側にも配信（Subscribe）されます。

## ブラウザ側 (Subscriber)

ブラウザ側ではWebSocketを内部利用しつつ、MQTTのインターフェイスでアクセスできます。ブラウザ側が受信機能(Subscriber)になります。

[mqtt.js](https://www.npmjs.com/package/mqtt)を読み込ませます。

`https://unpkg.com/mqtt/dist/mqtt.min.js`にアクセスすると最新のバージョンが表示されるので、参照しましょう。

```index.html
<html>
    <head>
        <title>websocket</title>
    </head>
    <body>
        <script src="https://unpkg.com/mqtt@2.15.1/dist/mqtt.min.js"></script>
        <script>
     
        const client = mqtt.connect();
        client.subscribe("n0bisuke");
        
        client.on("message", (topic, payload) => {
            console.log(topic,payload.toString('utf-8'));
        });

        client.publish("mqtt/demo", "hello world!");

        </script>
    </body>
</html>
```

`n0bisukeトピック`に送られた情報をコンソールに表示します。

## Publisher（おまけ）

Publisher側は何か適当に用意すれば良いですが。Node.jsでやる場合はこんな感じです。

```
npm i --save mqtt
```

```publisher.js
'use strict';

const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://localhost');

client.on('connect', () => console.log('publisher.connected.'));

setInterval(() => {
    const message = Date.now().toString();
    client.publish('n0bisuke', message);
    console.log('publisher.publish:', message);
}, 1000);
```

`n0bisukeトピック`に毎秒情報を送信します。

## 動作

![](https://i.gyazo.com/1ac19cbe4f4d556c42e04ceb77feaa6a.gif)

こんな感じでNode.js側でPublishした情報がBrokerを経由してブラウザ側で受け取れてました。

意外と情報が無いですが、これできるとMQTTの利用の幅が広がって便利です。
各種コマンドのカラー表示出力化（alias 利用）

こんにちは
各種コマンドのカラー表示出力化のために alias を作ってみました（参考記事：[linux(CentOS)のコマンドに色付け](https://qiita.com/ironsand/items/b308b3c689d69b94bae5)）。

```console
$ alias
alias grepc='grep --color=always'
alias diffc='colordiff'
alias lessc='less -R'
alias lvc='lv -c'
alias jqc='jq -C'
alias lsc='CLICOLOR_FORCE=1 ls -G'
alias source-highlightc='source-highlight -f esc'
$ source-highlightc -i sample.py | lessc
```

#### unbuffer コマンド
なおデフォルトでカラー表示出力するコマンドは、出力をパイブラインへ渡した場合は通常はカラーは抑止する作りになっていますが、unbuffer コマンドを使えばエスケープシーケンスは抑止されません（参考記事：[less にパイプしても色が消えないようにする方法](https://qiita.com/mkasahara/items/60049ee20956e835738b)）。

```
$ brew install expect
$ which unbuffer
/usr/local/bin/unbuffer
$ unbuffer command_color_output | lessc
```
Project Euler Q75 【1通りの整数直角三角形】

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


## 問題
ある長さの鉄線を折り曲げて$3$辺の長さが整数の直角三角形を作るとき, その方法が$1$通りしかないような最短の鉄線の長さは$12$cmである. 他にも沢山の例が挙げられる.

$12 cm: (3,4,5)$
$24 cm: (6,8,10)$
$30 cm: (5,12,13)$
$36 cm: (9,12,15)$
$40 cm: (8,15,17)$
$48 cm: (12,16,20)$

それとは対照的に, ある長さの鉄線 (例えば$20cm$) は$3$辺の長さが整数の直角三角形に折り曲げることができない. また$2$つ以上の折り曲げ方があるものもある. $2$つ以上ある例としては, $120cm$の長さの鉄線を用いた場合で, $3$通りの折り曲げ方がある.

$120 cm: (30,40,50), (20,48,52), (24,45,51)$

$L$を鉄線の長さとする. 直角三角形を作るときに$1$通りの折り曲げ方しか存在しないような $L ≤ 1,500,000$ の総数を答えよ.

注: この問題は最近変更されました. あなたが正しいパラメータを使っているか確認してください.


## アプローチ
引用元：[ピタゴラス数](http://izumi-math.jp/sanae/MathTopic/py_num/py_num.htm)

$a^2+b^2=c^2$を満たすような整数$a$、$b$、$c$を考える。
もろもろの考察により下記を全て満たす整数$m$、$n$を考えればよい。

```math
0<n<m \\
(a,b,c)=(m^2-n^2,2mn,m^2+n^2) \\
gcd(m,n)=1 \\
(m-n)\%2=1
```

以上より$(a,b,c)=(3,4,5)$は求まるが$(a,b,c)=(30,40,50)$のようなある組み合わせを定数倍したものは求めることができない。
そこで、最初に基礎となる組み合わせを求め、そこに長さが$150$万を超えない範囲で定数倍をする。


## 解答

```bash
time seq 999 |
awk '{for(i=1;i<$1;i++){if(($1-i)%2==1){print $1,i}}}' |
awk '{a=$1;b=$2;r=a%b;while(r!=0){a=b;b=r;r=a%b};if(b==1){print}}' |
awk '{a=$1^2-$2^2;b=2*$1*$2;c=$1^2+$2^2;print a,b,c,a+b+c}' |
awk '{k=1;while($4*k<=1500000){print $1*k,$2*k,$3*k,$4*k;k++}}' |
sort -k4,4n |
uniq -f3 -c |
awk '$1==1' |
wc -l
161667

real    0m12.817s
user    0m15.844s
sys     0m0.532s
```

最初はもう少し緩い条件でやれば最初から全量が求まるのではと思っていたが、どうにも$(a,b,c)=(30,40,50)$のような求められない組み合わせが出てきてしまい、答えが違ってしまっていた。
そこで上記のようなやり方にシフトしたところ、すぐに解答にいきつくことができた。

## 答え合わせ
http://www.geocities.jp/oraclesqlpuzzle/csharp/csharp-euler-answers.html
Windows10でタスクマネージャを見ると常にディスク100%な件

タスクマネージャを見ると、いつもディスクのパフォーマンスが100%（よくて98%とか）で、いつもとてもとても気持ち悪かったです。
見るたび見るたび、グラフが全て緑で塗りつぶされている状態でした

今まで解決しようと色々やってきましたが、先ほどやっと解決できたので。


#解決策
色々原因はあるみたいですが、私は以下の方法で解決しました。

タスクマネージャ-サービス-DiagTrackの停止

![image.png](https://qiita-image-store.s3.amazonaws.com/0/185546/8a4c5d86-8a14-897a-106b-363e16711f34.png)


あっというまに常にMAX100%だったのが、
80・・60・・と下がってきて、ついに10%以下にまで。
こんなにジグザグしたグラフ久しぶりに見た（；＿；）感動



![image.png](https://qiita-image-store.s3.amazonaws.com/0/185546/f6357790-9af9-2d88-3766-ae8f9ca37ac4.png)



以下のサイトを参考にしました。本当にありがたいです。。
[windows10でディスク使用率がずっと100%になる不具合解消方法](https://ogatism.jp/windows10-disk100/
)

※こちらのサービスを停止した後の不都合はよく分かっていません


※後日またこの方法でしても、100%のまま。。
　困ったものです・・・・
super_mediatorを改造せずにlogstashのフィルタで@timestampの値をflows.flowStartMillisecondsにする


pcapファイルをIPfixに変換、ELKで可視化
https://qiita.com/t_umeno/items/999a9f1e76b9cffa1053
の補足です。
上記URLではsuper_mediatorを改造しましたが、
super_mediatorを改造せずに
logstashのフィルタで@timestampの値をflows.flowStartMillisecondsにする事ができます。

matchのフォーマットの部分に

```
"yyyy-MM-dd HH:mm:ss.SSS"
```
と書けば変換できます。
下記の例ではsuper_mediator改造して、ISO8601形式に変更した場合も考慮しています。
2018/02/25 追記
timezone としてUTCを指定する様にしました。timezoneを指定しないとOS
で指定したtimezoneで時刻が取り扱われてしまいます。
例:

```
filter {
    if ([type] == "ipfix") {
        grok {
            match => ["path", "(?<index>yaf.\d{8,14})\.json$" ]
        }
        date {
            locale => "en"
            match => ["[flows][flowStartMilliseconds]", "yyyy-MM-dd HH:mm:ss.SSS", "ISO8601"]
            target => "@timestamp"
            timezone => "UTC"
        }
        date {
            locale => "en"
            match => ["[flows][flowStartMilliseconds]", "yyyy-MM-dd HH:mm:ss.SSS", "ISO8601"]
            target => "[flows][flowStartMilliseconds]"
            timezone => "UTC"
        }
        date {
            locale => "en"
            match => ["[flows][flowEndMilliseconds]", "yyyy-MM-dd HH:mm:ss.SSS", "ISO8601"]
            target => "[flows][flowEndMilliseconds]"
            timezone => "UTC"
        }
    }
}
```