OmniAICreator/Qiita-1.07M huggingface dataset:
Django2 公式チュートリアルのPollsアプリの機能追加【pollsの削除】

##前提
- 公式チュートリアルでpollsアプリを制作した。<br>
https://docs.djangoproject.com/ja/2.0/intro/tutorial01/
- 私の前回、前々回の記事を実装した。<br>
https://qiita.com/Liverty/items/bb761908d288b517dac1<br>
https://qiita.com/Liverty/items/9d2a64b935f338eca2df

##views.pyに削除機能を追加

```polls/views.py
class DeleteView(generic.DeleteView):
    model = Question
    form_class = QuestionForm

    success_url = reverse_lazy('polls:index')

    def delete(self, request, *args, **kwargs):
        result = super().delete(request, *args, **kwargs)
        messages.success(
            self.request, '「{}」を削除しました'.format(self.object))
        return result
```

##urls.pyに削除のURLを追加

```polls/urls.py
    path('<int:pk>/delete/',views.DeleteView.as_view(), name='delete'),
```

##question_confirm_delete.htmlを追加

```templates/polls/question_confirm_delete.html
<p>{{ object }} を削除していいですか?</p>
<form method="post">
  <button>削除する</button>
  {% csrf_token %}
</form>
```

##detail.htmlに削除ボタンを追加

```templates/polls/detail.html
<a href="{% url 'polls:delete' question.id %}">削除</a>
```

これで動くと思います。
動かない場合は、当記事冒頭の前提条件を確認してください。
RHEL を クラウドで利用する場合のライセンスについて

クラウド用 RHEL のライセンス
==========================

クラウド環境へのお持ち込み(BYOS[^1])が可能なRHELのライセンスは Physical or Virtual Nodes のみです。
１サブスクリプションで仮想環境を２つまで利用可能になります。

RHEL Server Physical or Virtual Nodesには２つのサポートタイプがあります。

◆Standard・・・平日の9:00-17:00（土日祝日を除く）
◆Premium・・・24時間365日


価格表
=====

[レッドハット製品のご購入手順](https://www.redhat.com/ja/about/japan-buy)

上記URLは定価の案内となっており、見積および発注は販売会社経由での対応となります。
購入の際は下記 [レッドハットのパートナー](http://jp-redhat.com/information/partner_list/index.html) のうち、ディストリビューション・パートナーの以下3社に問合せてみてください。
・サイオス株式会社 
・ソフトバンクコマース＆サービス株式会社 
・ダイワボウ情報システム株式会社 


さいごに
=======

サブスクリプションを BYOS する際は [Cloud Access](https://www.redhat.com/ja/technologies/cloud-computing/cloud-access) の 登録が必要になりますのでお忘れなく。

[^1]: Bring Your Own Software: 個人所有ソフトの持ち込み利用
C#：イテレータメソッドを作るときはローカル関数を使った方がいい理由

C# のイテレータは遅延評価です。
イテレータメソッドに引数チェックがある場合でも、メソッド呼び出し時にはチェックが行われず、評価時に例外が発生します。

素数を返すイテレータを例に見てみます。

```csharp
class PrimeService
{
    public IEnumerable<int> Generate(int start, int end)
    {
        if (start <= 1)
            throw new ArgumentException("引数は1以上を指定してください");
        if (end < start)
            throw new ArgumentException($"{nameof(end)}には{nameof(start)}以上の値を指定して下さい");

        for(var i = start; start <= end; end++)
        {
            if (IsPrime(i))
                yield return i;
        }

    }

    private bool IsPrime(int n)
    {
         // 素数判定の中身は省略します。一番下に置いておきます。
    }
}
```

上記のイテレータメソッドは

- 開始が 1 以下
- 開始が終りより大きい

と例外が投げられるはずですが、メソッド呼び出し時に例外は発生しません。


```csharp
class Program
{
    static void Main(string[] args)
    {
        var primeService = new PrimeService();
        var primes = primeService.Generate(start: 123, end: 32); // <- 引数が不正

        Console.WriteLine("まだ例外がなげられない！");

        foreach (var prime in primes) // <- ここで例外が発生する
            Console.WriteLine(prime);
    }
}
```

今回のように例外の発生個所と実際に例外をスローするコードが近い場合には問題の発見は簡単です。
しかし、大規模なプログラムになればイテレータを作るコードと列挙を開始するコードが近くにあるとは限らないため、問題の発見が困難になる場合があります。

## イテレータの実装部をローカル関数として持とう

イテレータメソッドをローカル関数として内部に持つことでこの問題は解決します。
`Generate` が呼び出された時に引数が不正である場合、その場で例外がスローされるようになります。

```csharp
public IEnumerable<int> Generate(int start, int end)
{
    if (start <= 1)
        throw new ArgumentException("引数は1以上を指定してください");
    if (end < start)
        throw new ArgumentException($"{nameof(end)}には{nameof(start)}以上の値を指定して下さい");

    return generateImpl();

    IEnumerable<int> generateImpl()
    {
        for (var i = start; start <= end; end++)
        {
            if (IsPrime(i))
                yield return i;
        }
    }
}
```

ローカル関数として実装を持つメリットは以下が挙げられます。

- 実装メソッドへのアクセスをラッパーの `Generate` メソッド内のスコープに限定できる
    - そのためエラーチェックのない実装メソッドが直接アクセスされる危険がない
- 実装メソッドはラッパーメソッドのすべての引数とローカル変数にアクセスできるため、実装メソッドの引数として渡す必要がない



[More Effective C# 6.0/7.0](https://www.shoeisha.co.jp/book/detail/9784798153988) を参考にしました。

## 省略した `IsPrime` メソッドの中身
下記の書籍を参考にしました。
[実戦で役立つ C#プログラミングのイディオム/定石&パターン](http://gihyo.jp/book/2017/978-4-7741-8758-7)

```csharp
private bool IsPrime(int n)
{
    if (n == 1)
        return false;
    if (n == 2)
        return true;
    var boudary = (long)Math.Floor(Math.Sqrt(n));
    for (long i = 2; i <= boudary; ++i)
    {
        if (n % i == 0)
        {
            return false;
        }
    }
    return true;
}
```
Django2 公式チュートリアルのPollsアプリの機能追加【pollsの更新】

第一弾として、【Pollsの新規登録】を扱いました。
https://qiita.com/Liverty/items/bb761908d288b517dac1

今回は第二回目です。Pollsの更新を扱います。
ちなみに前回もそうなのですが、解説はあまりしていません。
公式サイトやその他のサイトで解説を探していただき、まずは動く状態を作るために本記事を利用していただければ幸いです。

##前提
- Django公式サイトで、pollsアプリを制作して、動いている。
- 前回の私の記事で、pollsの新規登録機能を実装して、動いている。

##views.pyにUpdateViewを追加

```polls/views.py
class UpdateView(generic.UpdateView):
    model = Question
    form_class = QuestionForm
    success_url = reverse_lazy('polls:index')

    def form_valid(self, form):
        result = super().form_valid(form)
        messages.success(
            self.request, '「{}」を更新しました'.format(form.instance))
        return result

```

##ulrs.pyにUpdate用のpathを追加

```polls.urls.py
    path('<int:pk>/update',views.UpdateView.as_view(), name='update'),
```

##detail.htmlに更新用ボタンを追加

```details.html
<a href="{% url 'polls:update' question.id %}">質問を修正</a>
```

以上です。
動かない場合は、当記事冒頭の前提条件を確認してください。
iOS11.3でUIWebViewがクラッシュ

iOS１１．３でまれにUIWebViewのカスタムヘッダーをセットするタイミングでクラッシュが起きるようになった。

カスタムヘッダーのセットはこちらを参考にして
https://qiita.com/hikaruna/items/ba9fd3286d7265620914

このDelegate内で行っている。

```
-(NSURLRequest*) uiWebView:(id)webView resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(id)dataSource{
```

クラッシュ箇所を調べてみると
ヘッダーを設定する setValue 時に メソッドが無い？といった理由でクラッシュしていた。
これまで willSendRequest:(NSURLRequest *)requestパラメータは参考にした情報とい同様に NSMutableURLRequestクラスのインスタンスという前提でキャストしてヘッダーをセットしていたがiOS11.3ではまれに（条件不明） NSURLRequestクラスのインスタンスになっていることが判明。

NSURLRequestをキャストしている部分は mutableCopy を使うように変更

変更前
```NSMutableURLRequest *req = (NSMutableURLRequest*)request;
```

変更後
```NSMutableURLRequest *req = [request mutableCopy];
```

シグネチャを見るとそりゃそうなのですが理解が不十分なままになってました。
これまで問題なく動作してたのが逆に不満だったり・・・それ早く言ってよ〜
とても今更なCommonMarkのあれこれ

# とても今更なCommonMarkのあれこれ

### GFMにCommonMarkの仕様が反映された
* 詳しい話はこちらの記事をご参照頂ければ [CommonMarkの現状 2017年4月版 - Islands in the byte stream](https://gfx.hatenablog.com/entry/2017/04/12/103117)
* 昔書いた記事 [CommonMarkの仕様とか - Qiita](https://qiita.com/Prof-Cheese/items/9629438b06aacc068c98) から約半年後の出来事であった
* 一年前の事を今更記事にした理由は後述

### CommonMarkの仕様が更新された
* [CommonMark Spec](http://spec.commonmark.org/)
* 2018/04/17時点での最新版はVer.0.28
* 昔書いた記事からの差分は…気になることがあったら

### Boostnoteも大幅にバージョンアップした
* UIが変わって更にオシャレに
* 機能も盛りだくさん、個人的には各ファイルへの書き出しが嬉しい
  * md、txt、htmlに書き出せる上、印刷も出来るよ
* スマートフォン版もリリースされているのでこちらも期待

### VisualStudioCode（VSCまたはVSCode）という超高等テキストエディタが自分に刺さった
* 名前から有料かと勘繰られそうだけど、現時点では無料
* 当然のように各言語のハイライト表示がされる上、補完まで効くすごいやつ
* それどころか独自コンソール＋各環境専用コンソールを内部で開ける、CUI派も安心
* ただし設定をjsonファイルで書く必要がある辺りは硬派
  * 最近はGUIで直接設定出来るのも増えたよ
* Markdownにも対応、プレビューも並列表示出来るのでMarkdown専用エディタが死に絶えそう
* でもBoostnoteは独自機能満載なので自分は併用してるよ

### CommonMarkでググると1件目が自分の記事（2018/04/17時点、日本語）
* もっと本家とか最初に紹介した記事とか有用な方を見て！！！！！！
* これがこの記事を書いた理由です…

### あとがき
* もうそろそろMarkdown＝CommonMarkという思考に世界がなってくれると嬉しい
WebRTC経由で、MQTTをpub/subしてみる

# これは何？

[前回記事](https://qiita.com/komasshu/items/f8f3497ca4ee139437a1) の続き。[SkyWay IoT SDK の MQTT relay機能](https://github.com/nttcom/skyway-iot-sdk) を使って、グローバルな MQTT ブローカーを使わずに、P2P でブラウザから宅内 MQTT に pub/sub してみる。

今回の記事は、それのおさわり

# 概要

普通、宅内のMQTTクライアントをリモートからpub/subするためには、AWS IoTなんかを使ってグローバルな MQTTブローカー over WebSocket なんかを使ってやると思うんだけど、これを WebRTC を使って、グローバルブローカー使わずに P2P でやっちゃおうというもの。これを使うと、簡単・安価に宅内MQTTをふがほげできちゃう。

アーキテクチャーとしては、`ssg` がローカルのMQTTブローカーに接続し、MQTTクライアントと、ブラウザの間のMQTTデータを WebRTC でリレー中継してくれるというもの。[^1]

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83466/c8003e52-bd9d-cf54-9a9c-f50b9d338735.png)

[^1]: IoT SDKでは [インストーラー](https://github.com/nttcom/skyway-iot-sdk/blob/master/docs/how_to_install.md#install-by-installer) を使うと、[MQTTブローカー（mosquitto）](https://mosquitto.org/)も併せてインストールされる。

# プロセスの起動

[SkyWay IoT SDKのインストール](https://qiita.com/komasshu/items/f8f3497ca4ee139437a1) 後、

```bash
$ /opt/janus/bin/janus
```

```bash
$ MQTT_URL=mqtt://localhost MQTT_TOPIC=testtopic/+ ssg start
```

として、ローカルMQTTブローカーのURLと、subscribe する MQTT の topic を環境変数指定して `ssg` を起動する。

# サンプル web appの起動

[前回記事](https://qiita.com/komasshu/items/f8f3497ca4ee139437a1) 同様、
https://nttcom.github.io/skyway-siru-client/examples/
を開く。SkyWayの APIKEY をフォームに入力して `start` をクリックして、IoT SDKと接続。

# MQTT client からのデータを受信

まずは、MQTT clientから publishされたデータを受信してみる。ここで、サンプル webapp では `testtopic/from_dev` に subscribe しているので、`mosquitto_pub` を使ってテストデータ送信してみる。

```bash
$ mosquitto_pub -t testtopic/from_dev -m 'hello'
```

すると、画面右下の **MQTT Relay via datachannel** のところに、上記 publish したメッセージが表示される。[^2]

[^2]: 16文字以上のメッセージを受信した場合は、受信データのバイト数が表示される作りになっているので注意

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83466/6c7fb240-a8c6-c564-866c-6cd160400511.png)

# MQTT client にデータを送信

次に、ブラウザからのデータ送信の番。ここでは、`testtopic/from_cli` のトピックでデータを送ることにし、`mosquitto_sub` をそのトピックで起動しておく。

```bash
$ mosquitto_sub -t testtopic/from_browser
```

その後、画面右下のフォームから、*topic* として `testtopic/from_browser` を、*message* として、適当なメッセージを入力し、`send`をクリックする。で、mosquitto_subのほうにそのメッセージが表示される。[^3]

[^3]: `message` として、数字を入力すると、そのバイト数分の `a` が送信される作りになっているので注意。例えば `4` を入力すると `aaaa` が送信される。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83466/eb00ec89-962d-7eba-b831-35d7cf6ed3c7.png)

# まとめ

SkyWay IoT SDKで、P2Pで宅内MQTTへのpub/subする方法（おさわり）を紹介した。これを使うと宅内の温度センサモニタリングとか宅内デバイス制御なんかがお手軽に実現できる。また、クラウドを経由したり、わざわざグローバルIPをゲット -> NATとかに穴を開けなくても、パブリックなメッセージングサービスを宅内 Linux からだけで実現できたりもする。楽しげ
xUnitを使わない、シンプルで小さなテストコードの作り方

昔、xUnitなどがあまりなかった頃、こうやってテストしていたなぁと思いだした。

## サンプルコード

```c:sample.c
int add(int a, int b)
{
    return a+b;
}

#ifdef TEST
#include <stdio.h>

#define ASSERT(expected, actual) ((expected==actual)?printf("OK\n"):printf("NG\n"))

int main(void)
{
    ASSERT( 3, add(1,2) );
    return 0;
}
#endif
```

```cc -DTEST sample.c```
としてコンパイルすれば、単一で実行できるようになるので、
動くコードが保証できる。
もちろん、数が増えるとこれでは破綻すると思う。
とはいえ、環境構築などの手間が省けるので、
ちょっと実行するぐらいならば今でも使えるのではないだろうかなぁ。
Amazon Echo Plus での Philips Hue ホワイトグラデーションの調光

# 明るさ
## 一気に変更する
### ONにする
- アレクサ、ライトをつけて
- アレクサ、ライトをONにして

※ 前回消した時の明るさで点灯する。点灯中は反応するが変化なし

### OFFにする
- アレクサ、ライトを消して
- アレクサ、ライトをOFFにして

## %で指定する
### 指定の%の明るさにする
- アレクサ、ライトを100%（にして）
- アレクサ、ライトを0%（にして）
- アレクサ、ライトを33%（にして）

### 指定の%分明るさを調節する
- アレクサ、リビングを10%明るくして（上げて）
- アレクサ、リビングを20%暗くして（下げて）

## 段階的に変更する
### 25%明るさを調整する
- アレクサ、ライトを明るくして（上げて）
- アレクサ、ライトを暗くして（下げて

※ 「少し明るくして（上げて）」や「少し暗くして（下げて）」などは、10%変化する時と25%変化する時があり、違いは不明

# 色合い
<img src="https://qiita-image-store.s3.amazonaws.com/0/108116/9e917f89-7261-4014-7577-746ae7a6c112.png" width=50%>
【tutorial】AWS EC2にPHP, Apache, Laravelをインストール→テストページを表示

2018/4/16に実施。

１．SSHでEC2に接続。

２．PHP, Apacheをインストール。

```
sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
sudo yum -y install --enablerepo=remi,remi-php70 php
```
３．PHPのバージョンを確認。「5.3.29」？？
　　７をいれたつもりなんだけど。。

```
php -v
```

![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/3de10bae-e30b-4f70-e25a-8c8aa52cc564.jpeg)

４．リトライ。

```
sudo yum -y install --disablerepo=* --enablerepo=remi,remi-php70 php
```

５．PHPのバージョンを確認。７になった。

```
php -v
```

![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/d560d035-e762-c7ce-e3c3-4492472db263.jpeg)

６．Composerをインストール。

```
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
```

７．Laravelのインストール。エラーが発生。

```
composer global require "laravel/installer"
```

![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/bff48a94-8fcc-c36e-2148-2ab483f2b2a4.jpeg)

８．php-zipをインストール。

```
sudo yum -y install --disablerepo=* --enablerepo=remi,remi-php70 php-zip
```

９．「７．」をリトライ。成功。

```
composer global require "laravel/installer"
```

![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/57d6165a-77fc-9148-8a88-01bb34816632.jpeg)

１０．プロジェクトを作成。今回は「/var/www/laravel/sample」に作成。エラーが発生。

```
sudo mkdir /var/www/laravel
sudo chmod 777 /var/www/laravel
composer create-project laravel/laravel /var/www/laravel/sample
```
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/5d132a2b-c829-8058-7dad-0d355b2bf5ba.jpeg)

１１．php-mbstring, php-xmlをインストール。

```
sudo yum -y install --disablerepo=* --enablerepo=remi,remi-php70 php-mbstring
sudo yum -y install --disablerepo=* --enablerepo=remi,remi-php70 php-xml
```

１２．「１０．」をリトライ。成功。

```
rm -rf /var/www/laravel/sample
composer create-project laravel/laravel /var/www/laravel/sample 
```

![6.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/8f3e74d7-958c-ab06-73ae-cf91928b566f.jpeg)

１３．権限を変更。

```
sudo chown -R apache:apache /var/www/laravel/sample
```

１４．httpd.confの設定を変更。

```
vim /etc/httpd/conf/httpd.conf 
```

```
DocumentRoot "/var/www/html"
↓
DocumentRoot "/var/www/laravel/sample/public"
```

１５．Apacheを再起動。

```
sudo service httpd restart
```

１６．「セキュリティグループ」→「インバウンドルール」にHTTPを追加。
https://qiita.com/d778980/items/fa5daeef8cc5e0af768c

１７．ブラウザでテストページを表示。
http://(パブリックDNS)
![7.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/3fb31ff7-5c98-0580-a3c7-9149971f1ce1.jpeg)

終わり。
Rvest(とstringr)で自衛隊日報を一括ダウンロードしてみる

面白いと評判？の自衛隊日報をダウンロードするためのやっつけコードです、動かなかったらすいません
普段RばっかつかってるのでなんでRやねんってとこは勘弁してください

```r

#########必要なパッケージをロードする########
#インストールされてなかったら
#install.packages(c("rvest","stringr")) 
#を実行

library(rvest)
library(stringr)

#リンクの取得(朝日新聞サイトを利用)
links <- read_html("https://www.asahi.com/articles/ASL4J669JL4JUEHF016.html") %>% 
  html_nodes("a") %>% html_attr("href") %>% str_subset(".pdf") %>% unique()

#ファイル名(リンクのうしろ10文字で"日付.pdf")
filenames <- links %>% str_sub(-10)

#保存するディレクトリをつくる
dir.create("nippo")

#ダウンロード繰り返し
for(i in 1:length(links)){
download.file(url = links[i], 
              destfile =  str_c("nippo/", filenames[i]), 
              method = "libcurl"
              ) #method指定いらないかも
Sys.sleep(1) #1秒あける
}
```

楽しく読みましょう
Chrome ヘッドレスでファイルダウンロード[Golang + chromedp]

# やったこと
- Chrome Devtools Protocolを用いて、HeadlessChromeでファイルダウンロードをする。

# 実際のコード
- 例としてMoneyForwardにログインして、家計簿のcsvをダウンロードするコードを書いてみる。

```go
package main

import (
	"context"
	"log"
	"time"
	"os"

	"github.com/chromedp/chromedp"
	"github.com/chromedp/chromedp/runner"
	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/cdproto/page"
)

func main() {
	var err error

	// create context
	ctxt, cancel := context.WithCancel(context.Background())
	defer cancel()

	// create chrome instance with headless mode
	chrome := "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
	c, err := chromedp.New(ctxt, chromedp.WithRunnerOptions(runner.HeadlessPathPort(chrome, 9992)))
	if err != nil {
		log.Fatal(err)
	}

	host := "https://moneyforward.com"
	user := os.Getenv("MF_USER")
	pass := os.Getenv("MF_PASS")

	// run task
	err = c.Run(ctxt, doScrape(host, user, pass))
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Scrape Done.")

	// shutdown chrome
	err = c.Shutdown(ctxt)
	if err != nil {
		log.Println("down-err")
		log.Fatal(err)
	}
	log.Println("Chrome Shutdown.")
}

func doScrape(host, user, pass string) chromedp.Tasks {
	return chromedp.Tasks{
		// configure to download behavior
		chromedp.ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
			err := page.SetDownloadBehavior("allow").WithDownloadPath("/tmp").Do(ctxt, h)
			if err != nil {
				return err
			}
			return nil
		}),
		chromedp.Navigate(host + "/users/sign_in"),
		chromedp.SendKeys("//input[@id='sign_in_session_service_email']", user),
		chromedp.SendKeys("//input[@id='sign_in_session_service_password']", pass),
		chromedp.Click("//input[@id='login-btn-sumit']"),
		// login
		chromedp.WaitVisible(".logo-image", chromedp.ByQuery),
		// move to cashflow page
		chromedp.Navigate(host + "/cf"),
		// download file
		chromedp.Click("//*[@id='js-dl-area']"),
		chromedp.Click("//*[@id='js-csv-dl']"),
	}
}

```

# モチベーション
- URIを持たないファイルリソースや認証の先にあるダウンロードリンクからファイルを取得したかった。
- Golangにした理由はコマンドラインツールにしたかったため。
  - 取得したファイルを標準出力にはけば、あとはパイプでつないで編集→別ツールにインポート、みたいなワークフローを想定。

# 所感
- Chrome Devtools Protocolおもしろい！ブラウザで出来ることのAPIが豊富に用意されているので、Golangとの組み合わせはブラウザ操作をガシガシ自動化していくよいツールに思えた。
- chromedpとcdprotoの設計がかなり抽象レイヤを挟んでいて、読んでいて面白い反面、少々冗長に思えた。私が読み切れていないだけかもしれない。

# 参照リンク
- [Headless Chromeでファイルをダウンロードする](https://www.sambaiz.net/article/131/)
  - 「chrome headless ファイルダウンロード」でtopでヒットする情報。こちらでdownloadBehaviorの存在を知ることができました。ありがとうございます。
- [chromedp](https://github.com/chromedp/chromedp)
  - golangでchrome devtool protocolを扱うためのフロント
- [cdproto](https://github.com/chromedp/cdproto)
  - chromedpから参照されるライブラリ群
starman にPLACK_ENVを渡さないと、PLACK_ENV=depoymentになる

タイトルそのままです。

`starman` コマンドのデフォルトのPLACK_ENVはdepoyment になるようです。

久しぶりに触ったので小一時間悩んだ。。。

```perl
starman  -e 'sub { [q{200}, [ qw(Content-Type text/html) ], [ $ENV{PLACK_ENV} ] ];}'
```

curlで叩いてみる

```sh
$ curl http://localhost:5000
deployment
```

plackupから叩くと `development` になります。

```shell_session
plackup -s Starman  -e 'sub { [q{200}, [ qw(Content-Type text/html) ], [ $ENV{PLACK_ENV} ] ];}'
```


```sh
$ curl http://localhost:5000
development
```
Docker コンテナでの sshd 起動まとめ w/o init

#はじめに
いくつかのディストリビューションにおいて sshd を起動するミニマムと思しき手順をまとめます。
今回想定しているのは init を使わないで直接 sshd を起動するケースです。

対象ディストリビューション：

- CentOS 6
- CentOS 7
- Ubuntu 16.04 LTS (Xenial Xerus)
- Ubuntu 18.04 LTS (Bionic Beaver)

#ポイント
ポイントは鍵の作成です。

#具体的な手順

##CentOS 6

###sshd インストール

```
# yum install -y openssh-server
```

###sshd 起動

CentOS 6 では鍵ファイルは起動スクリプトが必要に応じて作成してくれます。

```
# service sshd start
```

##CentOS 7

###sshd インストール

```
# yum install -y openssh-server
```

###sshd 準備

CentOS 7 では鍵ファイルは起動スクリプトとは別のスクリプトが作成しています。systemd の Unit ファイルも別に存在し、sshd.service に依存関係が設定されています。
ExecStartPre ではないところがミソ。

```
# /usr/sbin/sshd-keygen
```

###sshd 起動

CentOS 7 では鍵ファイルが存在しないと sshd が起動しません。

```
# /usr/sbin/sshd
```

##Xenial Xerus

###sshd インストール

```
# apt -y install openssh-server
```

###sshd 準備

Xenial では .deb パッケージの postinst スクリプトが鍵ファイルを作成しています。opsenssh-server をインストールしたイメージを使いまわすと鍵が共通になります。
再作成するには下記を実行します。
※イメージ作成段階で消しておくのが安全かと思います。

```
# rm /etc/ssh/ssh_host_*key*
# dpkg-reconfigure openssh-server
```

###sshd 起動

Xenial では鍵ファイルが存在しなくても sshd は起動に失敗しませんが、その状態では ssh クライアントの接続は失敗します。

```
# /etc/init.d/ssh start
```

##Bionic Beaver

Bionic は Xenial と同じです。

#systemd について
systemd を使うのであれば下記で普通に systemctl が使えると思います。

```
$ docker run --privileged <image_name> /sbin/init
```

ただし、sshd が systemd で管理されているディストリビューションは、今回対象とした中では CentOS 7 のみです。（Ubuntu にも systemd の unit file が存在しますが、systemd が動いていなくても ssh daemon を制御できます。）
「システムコンテナとして利用するのに init は必須ではない」、とも言えます。

#まとめ
Docker コンテナをマルチプロセス・マルチユーザーで利用するのは不適切かもしれませんが、かといって、マルチプロセスやマルチユーザーが必要なケースで別の仮想化を使うというのも、面倒じゃないでしょうか。

ということで、ssh でマルチユーザーが便利になりましたとさ。
WordPressにMarkdown記法で投稿できるようにしたい

# WordPressにMarkdown記法で投稿できるようにしたい

私事ですが、実は昨日WordPressで[ブログ](https://spadeloves.cf/blog/wp_spadeloves/ "忘れっぽいログ – 忘れっぽいエンジニアのための備忘録。")を開設いたしました。
祝開設！みたいな気分で**毎日投稿する**とか書いちゃってます。どうしよう・・・
QiitaにはMarkdownで気軽に投稿できるのに、ブログ（HTML）となるとなんだか気が重い・・・
ぼく「そうだ！Markdownで記事を書けるようにすればやる気出るかも説！！」

ということでWordPressにMarkdownで投稿出来るようにしたいと思います。

## Markdownってなんぞ？
Wikipedia先生曰く、
>Markdown（マークダウン）は、文書を記述するための軽量マークアップ言語のひとつである。本来はプレーンテキスト形式で手軽に書いた文書からHTMLを生成するために開発されたものである。しかし、現在ではHTMLのほかパワーポイント形式やLaTeX形式のファイルへ変換するソフトウェア（コンバータ）も開発されている。各コンバータの開発者によって多様な拡張が施されるため、各種の方言が存在する。

だって。
簡単に言うと、
「**きれいな文書**を、**簡単な書き方**で、**わかりやすく書ける**ようにしたもの、だよ！」
ということです。

例として、HTMLで見出しを作ろうとすると、

```HTML
<h1>私が見出しだ</h1>
```

このHTMLはMarkdownで書くと

```markdown
# 私が見出しですわよ
```

こうなる。めっちゃ簡単ですやんね。
というわけでここQiitaだの、Githubだの、Trelloだの、様々なWebサービスで使われる、エンジニアなら覚えて損はない記法なのである。（というか知っとくべきと思う）

## WordPressにプラグインを入れる。

ここからが本編。と言っても公式のプラグインを入れるだけだけど。

1. プラグイン＞新規追加からプラグインを検索
markdownとかで検索すればOKです。

2. 「Markdown Editer」をみつけてインストール
比較的、更新日時が近かったのと、最新のWPに互換性ありとのことなのでこいつに決定
[Markdown Editor — WordPress プラグイン](https://ja.wordpress.org/plugins/markdown-editor/ "Markdown Editor — WordPress プラグイン")

3. インストールが完了したら有効化を忘れずに。

これでおしまいです。

## 早速動作確認！
詳細を調べずにプラグインを入れたのでドキドキしながらいざ動作確認です！

![WP_MDプラグイン.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/182837/15c47e2b-7677-a589-138d-2ea45d53d45d.gif)
なかなかいい感じ・・・*（録画してると緊張してタイプミスしまくり）*
見出しについては記述に直接文字サイズが当たるみたいですね！

そして作成された記事がこんな感じ
<img width="600" alt="スクリーンショット 2018-04-17 1.19.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/182837/03dd4741-24d5-dd81-8700-e3acda260352.png">
ふむふむ悪くない悪くない

そして、このQiita記事用のMarkdownをそのまま貼り付けてどうなるかやってみました！
それが[こちら](https://spadeloves.cf/blog/wp_spadeloves/index.php/2018/04/17/wp_md/ "WordPressにMarkdown記法で投稿できるようにした – 忘れっぽいログ")になります（３分クッキング風）
ちょっと見出しが大きすぎる・・・でもこれはテーマとの相性の問題でもありますね！

一旦このプラグインを使ってみることにします！

もし、Markdownならこのプラグインいいよ！　みたいなのがあったら教えてください。
更新したいと思います。
スクロール禁止が overflow:hidden や preventDefault(); でできないときの対処法

検索すると overflow:hidden や preventDefault(); を使うとスクロールを無効化することができるといった情報が出てきますが、iOS や Chrome 54 以降では動作しなくなっています。

# preventDefault(); が動作しない理由
Chrome 54 から動作しなくなったようです：

<img width="761" alt="SS 2018-04-17 at 0.49.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/155587/2ff16c09-3652-b53a-f9ca-0ebd6f2e2a4c.png">

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive.
https://www.chromestatus.com/features/5093566007214080
https://developers.google.com/web/updates/2017/01/scrolling-intervention

ブラウザはスクロール時に起こるイベント (`touchmove` など) が起こるとき、`addEventListener` などによって処理が登録されていると、その処理に `preventDefault();` (スクロールをキャンセルする関数)が含まれているかどうか確認します。この確認している間はスクロールは行われません。そのため、時間がかかる処理がある場合は、スクロール速度が低下して動作がカクカクになってしまうという問題がありました。

そこで `passive` というオプションが追加されました。
このオプションを `true` にすると、「この処理に `preventDefault();` は含まれていないのでスクロールを行っていいですよ」とブラウザに明示することができます。
これによりブラウザは処理を行う前にスクロールをすることができるので、スクロール速度を改善することができます。

比較動画はこちら (左が従来のもの、右が `{passive: true}` を指定したものです)：
> Side by side: passive event listeners
> https://youtu.be/65VMej8n23A
> <a href="https://youtu.be/65VMej8n23A" target="_blank"><img width="500" src="https://qiita-image-store.s3.amazonaws.com/0/155587/6a938b7f-5b66-6432-6814-95ceced437e5.png"></a>


Chrome 54 以降ではデフォルトでこの `passive` が `true` となっており、`preventDefault();` を使用する場合には `{passive: false}` を指定しなくてはなりません。

# 対処法
`addEventListener` の第3引数として `{passive: false}` を指定する。

```js:JavaScript
document.addEventListener('touchmove', function(e) {e.preventDefault();}, {passive: false});
```
これはモバイルでしか動作しないため、デスクトップ用に `overflow: hidden` も必要です。

# まとめ
```css:CSS
html, body{
  overflow: hidden;
}
```
```js:JavaScript
document.addEventListener('touchmove', function(e) {e.preventDefault();}, {passive: false});
```

## おまけ
`touch-action` というすべてのタッチ操作を無効化する CSS プロパティもあります。
今後はこちらを使っていくことが推奨されていますが、Safari はまだ対応していません。

```css:CSS
touch-action: none;
```
> iOS Safari only supports `auto` and `manipulation`.
> https://caniuse.com/#feat=css-touch-action

## 参考
Passive Event Listeners によるスクロールの改善
https://blog.jxck.io/entries/2016-06-09/passive-event-listeners.html

iOSはoverflow:hidden;でスクロールを無効にできない - Qiita
https://qiita.com/mimoe/items/f5f668cebb697d073553
RPAExpressを使って漫画自炊の効率化を行った話

# きっかけ
１年ほど前から漫画の自炊を嗜んでおり、如何に効率的に作業を行うかを毎晩考えておりました。
去年(2017年冬)にRPAExpressというRPA製品の無償版がリリースされ、これを機に我が自炊業務にも適用することに致しました。

# 漫画自炊の業務フロー
1.漫画の切断
　まずは、漫画の切断から行います。
　自作の切断キットでがんばります。
　（一冊あたりの工数＠ 0.5 min）
　※ 回数を重ねることで疲労が溜まります。

2.スキャン準備
　スキャン前に所定のフォルダの作成を行います。
　Excel計算式にて、Powershellのコマンドを生成
　（一冊あたりの工数＠ 0.2 min）

3.スキャン
　私が使用しているスキャナは「EPSON DS-530」です。
　一度にスキャンできる枚数は、50ページ位なので、途中途中で追加します。
　（一冊あたりの工数＠ 4 min）

4.スキャン後の処理
　スキャン後、所定のフォルダへ保存先を設定し、一番最初にスキャンした表紙を横回転します。
　（一冊あたりの工数＠ 1 min）

5.表紙作成
　表紙は裁断していないので、ちょうどいい感じに画像加工を行います。
　フリーソフト「Ralpha」を使用して、一括で座標指定の画像を生成します。
　具体的には、表紙としてスキャンした「img_001.jpg」を「Ralpha」で「img_000.jpg」を生成します。
　（一冊あたりの工数＠ 0.2 min）

6.事後処理
　スキャンした画像を全てzipにします。
　Excel計算式にて、Powershellのコマンドを生成
　その後、自宅のNASへコピーして終了
　（一冊あたりの工数＠ 0.2 min）

# RPAExpressの適用
今回効率化したのは、「4.スキャン後の処理」です。
いろいろ苦労しましたが、結果的に工数が（1 min）→（0 min）になりました。


# RPAExpressの記録
![image.png](https://qiita-image-store.s3.amazonaws.com/0/249830/937a74a2-4f0d-f742-0c25-e6b4733add53.png)

[replace with new recording]をクリックし、スキャン後の処理を記録していきます。
出来るは出来るのですが、繰り返すとエラーになってしまう・・・。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/249830/1694cf09-310d-1223-0b41-7cf15c95f685.png)
[Window]系は、結構エラーが多いようなので、使いません。。。

仕方がないので、C#を使って、AppActiveコマンド（入力したアプリケーション名をアクティブにする）を実行するアプリケーションを作成し、代用することにしました。
多分RPAExpressでも同じコマンドを使ってるのだと思うので、うまいやり方はあるはず！
また、一度デスクトップ画面を表示したほうが安定したため、最初に[Win+D]を使用しております。

実際のコマンドは、全てキーボードでのコマンド操作を記録することにしました。
このほうが圧倒的に安定します。

[Tab][Sft+Tab][Enter][Space]を駆使して、キー操作を記録します。
結果は動画を御覧ください。


# RPAExpressでの効率化（動画）
https://youtu.be/p3ZrCNBGCCM



# RPAExpressの感想
・ノンプログラミングで操作を一通り行えるのは、非常に良い。
・レコーディングし、同じことを繰り返そうとすると、大概エラーになる。
→ [Window]が安定しない感じだが、キー操作中心でなんとかなる。
・キー操作だと、waitをうまく使わないとたまに失敗する。
・確実に行わなければならない業務を任せるのはまだ早い。



# 今後の課題
漫画の自炊では、一旦完結。
他に使えそうなものがあれば、また追記します。





でわでわ
xibを利用したカスタムViewを作る時に便利な方法

# はじめに

基本Androidをやっていますが、 最近iOSのアプリも作り始めました。

`storyboard`でレイアウトを組む時にカスタムビューを使うとスッキリするので割と多用するのですが、`xib`ファイルの読み込みを綺麗に共通化したくて調べていたら、良い[サイト][1]が見つかったのでご紹介します。

`xib`の作り方は他の記事でも紹介されているので省略させていただきます。

# 方法

参考サイトにある通り、`UIView`を継承したクラスで`xib`を読み込む処理を実装しておき、`init`で`addSubview`まで行ってしまうという方法です。

# 実装

下記の通りに`NibView`クラスを実装して、通常通りにカスタムビューを作ったら、`NibView`を継承するだけです。
ただし、`xib`ファイルのファイル名はクラス名と同じにする必要があります。

コードは参考サイトの内容そのままです。

```swift
import UIKit

class NibView: UIView {
    var view: UIView!
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        // Setup view from .xib file
        xibSetup()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        // Setup view from .xib file
        xibSetup()
    }
}

private extension NibView {
    
    func xibSetup() {
        backgroundColor = UIColor.clear
        view = loadNib()
        // use bounds not frame or it'll be offset
        view.frame = bounds
        // Adding custom subview on top of our view
        addSubview(view)
        
        view.translatesAutoresizingMaskIntoConstraints = false
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[childView]|",
                                                      options: [],
                                                      metrics: nil,
                                                      views: ["childView": view]))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[childView]|",
                                                      options: [],
                                                      metrics: nil,
                                                      views: ["childView": view]))
    }
}

extension UIView {
    /** Loads instance from nib with the same name. */
    func loadNib() -> UIView {
        let bundle = Bundle(for: type(of: self))
        let nibName = type(of: self).description().components(separatedBy: ".").last!
        let nib = UINib(nibName: nibName, bundle: bundle)
        return nib.instantiate(withOwner: self, options: nil).first as! UIView
    }
}
```

```swift
class CustomView: NibView {
}
```

これで`xib`を開いて、`File's Owner`の`Custom Class`に`CustomView`を設定すればOKです。
もちろんコードからでも使えます。

```swift
let customView = CustomView().loadNib() as! CustomView
customView.frame = /* add your frame */
view.addSubview(customView)
```

カスタムビューを多用するときは、これを使うとスッキリすると思います。
ご参考になれば幸いです。

# 参考

https://medium.com/theappspace/swift-custom-uiview-with-xib-file-211bb8bbd6eb

[1]:https://medium.com/theappspace/swift-custom-uiview-with-xib-file-211bb8bbd6eb
MacにPythonの環境構築

# MacにPythonの環境構築をする
Macにpython環境（jupyterまで）を構築する。

## 環境構築の流れ
brewを使いpyenvインストール
pyenvでanacondaインストール
condaで仮想環境構築


## pyenvインストール
・homebrewをアップデートしてpyenvをインストール

```
$ brew update
$ brew upgrade
$ brew install pyenv
# pyenvのバージョン確認
$ pyenv --version
```

pyenvにパスを通す。

```
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
```

## anacondaのインストールとpyenvによる切り替え
・pyenvでanacondaをインストール

```
#　インストール可能なanacondaのバージョンを確認
$ pyenv install -l | grep anaconda
# 3系の最新版をダウンロード
$ pyenv install anaconda3-5.1.0
# ダウンロードしたanacondaを確認
$ pyenv versions
```

この段階ではanacondaはまだ使えない。
`pyenv versions`や`python -V`で今の環境を把握しながら進める。

・anacondaを使えるようにする
`pyenv global x.x.x`か`pyenv local x.x.x`でバージョンを選択する。
`global`とすると全体に、`local`にするとそのカレントディレクトリに反映される。

```
$ pyenv global anaconda3-5.1.0 
```

## condaで仮想環境を作成して、jupyterを起動
anacondaを後ろに付けると、anacondaのライブラリが使えるようになる。

```
$ conda create --name py python=3.6 anaconda
```

作成した仮想環境を適用させる。

```
$ pyenv local anaconda3-5.1.0/envs/py
```

これで無事に起動できればOK!

```
$ jupyter notebook
```
ディ◯ニーランドの待ち時間をJSで取得する「themeparks」

みなさん、ディ◯ニーランド好きですよね、僕も好きです。ディ◯ニーランドにいるとき、アトラクションの待ち時間が気になりますよね。でも例えば、すぐにスマホを取り出せない状況だったらどうしますか？待ち時間チェックアプリが開けません。そこで[themeparks](https://github.com/cubehouse/themeparks/)というライブラリを使えばJavascriptで待ち時間を取得できるので、いちいちスマホを取り出す必要はありません。

## インストール
いつもどおり`npm install`で`themeparks`をインストールできます。

```
npm install --save themeparks
```

## 使ってみる
```Javascript
// ライブラリをrequireします。
var Themeparks = require("themeparks");

// 取得可能なテーマパークの一覧を表示します。
for (var park in Themeparks.Parks) {
    console.log("* " + new Themeparks.Parks[park]().Name + " (DisneyAPI." + park + ")");
}

// 特定のパークにアクセスします。この例では東京ディ◯ニーシー。
var disneySea = new Themeparks.Parks.TokyoDisneyResortDisneySea();

// Promiseを使ってディ◯ニーシーの待ち時間を取得します。
disneySea.GetWaitTimes().then(function(rides) {
    // print each wait time
    for(var i=0, ride; ride=rides[i++];) {
        console.log(ride.name + ": " + ride.waitTime + " minutes wait");
    }
}, console.error);

// オープニング時間を取得します。
disneySea.GetOpeningTimes().then(function(times) {
    for(var i=0, time; time=times[i++];) {
        if (time.type == "Operating") {
            console.log("[" + time.date + "] Open from " + time.openingTime + " until " + time.closingTime);
        }
    }
}, console.error);
```

## 感想
これは結構楽しいですね。ライブラリのソースコードを読んで初めて知ったんですが、ディ◯ニーって公にしてるのかどうかはわかりませんが、待ち時間のためのWebAPIを提供しているみたいですね。
Unity「Tanks tutorial」メモ

# はじめに
これは、Unity公式のチュートリアル「Tanks tutorial」を利用して、Unityの学習を行おうとした際に発生した問題等を書き留めておくメモです。
もっといい方法があるかもしれないです的備忘録。

# 環境
- windows 10 Pro
- Unity 2017.4.0f1

# 腕前
- unityの初心者用の本と実践に近い本を一通り呼んだ程度。このチュートリアル完了後、一本簡単なゲームを作る予定だった(すでに作成作業しているので過去形)

# サンプルを開く前に
プロジェクトを開く際のLearnのタブでサンプルアセットをダウンロードして開くと、
自分の環境の場合だとwindowsのテンポラリーディレクトリに開いてしまい、
プロジェクトの保存ができなくなってしまったので、
いったん空のプロジェクトを作成し、
そこにアセットストア経由でサンプルアセットをインポートするとうまくいきました。

# バージョン違いによる差分吸収メモ
バージョンによっては該当する項目の名称が変わったりする場合があるので、ページごとにメモ
## Baked GIの削除(チュートリアル動画 シーン設定 4:40あたり)
Mixed Lightingの「Baked Global Illumination」のチェックを外すことにより、使用しないようにすることが可能のようです。
## Precomputed Realtime GIの設定(チュートリアル動画 シーン設定 4:50あたり)
雰囲気、lightmapの設定に統合されている模様。
このチュートリアルでは低ポリゴン向けのために設定しているため、
Lightmapping Settings ＞ LightmapParametors
を、「Default-LowResolution」に変更して様子を見ることで暫定対応しました。
## ambient colorの設定(チュートリアル動画 シーン設定 6:20あたり)
ライティング設定でambient colorを設定しようとすると、
HDR Colorのカラーピッカーを使用するようになるようで、
説明通りの値を設定すると別の色になってしまう。
HEXの値(#483E71)で設定。通常のカラーピッカーを使用する設定はどこだろう。
## ライティングのbaked実行(チュートリアル動画 シーン設定 7:00あたり)
名前が変わっただけ。「Generate Lighting」をクリック。
## Emissionの設定(チュートリアル動画 タンクの作成と制御 17:20あたり)
雰囲気設定方法が変わっただけかと思ったら、直進の時のみパーティクルをださない状態になる。
「Rate over Distance」のみに値を設定し、
RightDustTrail ＞ Emitter Velocity
を、「Rigidbody」から「Transform」に設定することで直進カーブ両方とも動くようになる。
あくまでrigidbodyを使用しているのは親のタンクオブジェクトのみであり、
rigidbody不使用のパーティクルオブジェクトは、親の移動による単なる位置の移動だから動かなかったと思われる。
## パーティクル削除(チュートリアル動画 砲弾の作成 22:37あたり)
unityのバージョンアップにより、
m_ExplosionParticles.duration によるパーティクル終了時間の取得が非推奨になりました。
ParticleSystem.main.durationという形で取得することになる。
(_Complete-Assetsディレクトリ以下の完成ソースは修正済み。完成するまで気が付きにくい。)
参考：http://cycling.hateblo.jp/entry/2017/03/17/110939

## Sceneの呼び出しが動画と違う点について(チュートリアル動画 ゲームマネージャー 35:36あたり)
unityのバージョンアップにより、
GameManagerクラスで使用しているApplication.LoadLevelでの呼び出しが非推奨になったため、書き換えた模様。
また、それに伴い、UnityEngine.SceneManagementが必要になるため、GameManager.csの三行目のコメントアウトを外さなくてはいけない。
このチュートリアルの下部にある日本語によるソース説明は修正前のソースのため注意。
(_Complete-Assetsディレクトリ以下の完成ソースも修正済み)
参考：http://ninagreen.hatenablog.com/entry/2016/01/13/033413

## 他、自分用メモ(本で触れなかったようなことについて調べたり、これメモしておこうと思ったことへのメモ)
- コンポーネント経由でそのコンポーネントが付与されているオブジェクトに対してgetComponentが使用できる。
- サウンドミキサーコンポーネントの、Duck Volumeおよびsendエフェクトについて。
 - Duck Volume：sendにより指定されているサウンドのグループの音が出ている間、閾値の音量まで下がる
 - send:音がなっている情報をsendにて指定したグループのエフェクトに送信する。今回の場合は、sendが設定されているグループの音が鳴っている間、指定したグループのDuck Volumeにより指定したグループの音量を下げている。

# 完走してから
初心者向けの本を読んで理解しただけのわりには、中級と指定されているこのチュートリアルも理解できたので、もうちょっと上級のチュートリアルとか進めてもいいのかもしれない。
最近kotlin化してて地雷踏んだところ(加筆中)

最近弊社Androidアプリをkotlin化してます。
ファイル数がありすぎる + 機能追加を並行して行っているのでかなりのんびり目で進めていますが、それでも地雷を踏みまくってユーザーに不便をかけてしまっているので、同じ轍を踏まないためにメモを残します。

kotlinのNullSafeな世界を守るために

# Convert java to kotlinして気をつけること
## onRestoreInstanceState()の復帰objectはすべてnullable対応しておく
- なんかしらnullになるときがある(もっとちゃんとコード読めば解決する問題のような)
- これに限らず `Bundle` にsetData()とかしてるとこは全部チェックしたほうがいいかもしれない

```kotlin
    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        super.onRestoreInstanceState(savedInstanceState)

        this.object = savedInstanceState.getSerializable(KEY_DATA_OBJECT) as? DataObject
}
```

## override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent)はそのままだと駄目

- `data :Intent` がnullのcaseがあって落ちた。

```kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
}
```

- `?` を付けましょう。

```kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
}
```


## javaのメソッドを使っているところはnullable対応しておけば間違いない
- 自動でNonNullに変換されたが、javaなので平気でnullを突っ込んでくる
	- java側のコードをちゃんとチェックすればいいが、そうもいかないときもある
- onItemClick()などの引数がnullのときがある。
- もう大概のものに `?` つける(落ちるよりはマシだけどよろしくない)

## ・ onActivityResult()のIntent.getSerializableExtra()
- Castするときは必ず `as?` でやりましょう

```kotlin
val data = intent.getSerializableExtra(KEY_DATA) as? HogeData
```


## RxJava1.xだとつらい
- `SingleSubscriber<Void>` だと落ちる `<Void?>` にしよう

```kotlin
hogeSingle.subscribe(object : SingleSubscriber<Void?>() {
                    override fun onSuccess(response: Void?) {
                    })
```

- RxJava2ならVoidなんて渡さなくていい。。Completableとか使いたい



# おまけ
## ConstraintLayoutへの置き換え
- ConstraintLayoutをAPI Levelの低い端末で見る時は上下の制約をつけておかないとレイアウトが壊れる
- (計測中)おそらく単純にConstraintLayoutにしても駄目で、階層構造をフラットにすることによって高速化を実現できるとかそんな話な気がする

## Databindingへの移行
ついでにDatabindingに移行しているときに気づいたこと

- branch切替時にcleanしないとDatabindingに移行したLayoutがビルドエラーになる

- 自動生成されるファイルが残っているためだと思われる
SpringBoot で Hello World

#SpringBoot で Hello World

SpringBoot + ThymeleafでHello Worldを表示する

開発環境:
OS:windows10 home
Eclipse：pleiades-4.7.2

Eclipseの「ファイル」→「新規」→「その他」→　「Spring スターター・プロジェクト」
を選択して、新規プロジェクトを作成します。

1.構成

```
sample-hello
 └─src
    └─main
        ├─java
        │  └─com
        │      └─example
        │          └─demo
        │                  HeloController.java
        │                  SampleHelloApplication.java
        └─resources
            │  application.properties
            │  
            ├─static
            └─templates
                    index.html
```

2.html
htmlを作成します。

```　html:index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Hello</title>
    <meta charset="utf-8" />
  </head>
  <body>
    <h1>Springboot Hello Sample</h1>
    <p>
      <span th:text="${message}"></span>!!!
    </p>
  </body>
</html>
```
3.Controller
Controllerは以下のように作成する。indexというStringを返すようにすると、
resources/templatesの下のindex.htmlを返します。

```
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HeloController {
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index(Model model) {
        model.addAttribute("message", "Hello Springboot");
        return "index";
    }
}
```

4.実行してみます。
プロジェクトを右クリック→「実行」→「Spring boot アプリケーション」を選択します。
http://localhost:8080/にアクセスすると、以下のような画面が表示されます。

![helloworld.png](https://qiita-image-store.s3.amazonaws.com/0/246741/6ff2520e-3814-589a-1d18-787e3ab9b659.png)
【SQL】テーブル結合

#テーブル結合

■内部結合
→結合するデータのみを出力する。結合しないデータは、出力されない。
（NULLとNULLは等しくないので含まれない）
・join

■外部結合
→メインとするテーブルの全行を出力する。（NULL含む）
・left join（左外部結合）
・right join（右外部結合）
・full join（完全外部結合）

##内部結合
###join
↓基本の形

```sql
select 出力するカラム名
from テーブルA
join テーブルB
on 両テーブルの結合する条件
```

↓イメージ

```sql
select A.name, B.name
from bookstore as A
join author as B
on bookstore.authorid = author.id
```

##外部結合
###left join
メインテーブルとの結合相手が見当たらなくても、NULLであっても、必ずメインテーブルの全行を出力する。
↓基本の形

```sql
select 出力するカラム名
from　テーブルA
left join テーブルB
on 両テーブルの結合する条件
```

↓イメージ

```sql
select A.name, B.name
from bookstore as A
left join author as B
on bookstore.authorid = author.id
```

###right join
メインテーブルとの結合相手が見当たらなくても、NULLであっても、必ず結合テーブルの全行を出力する。
↓基本の形

```sql
select 出力するカラム名
from　テーブルA
right join テーブルB
on 両テーブルの結合する条件
```

↓イメージ

```sql
select A.name, B.name
from bookstore as A
right join author as B
on bookstore.authorid = author.id
```

###full join
メインテーブルとの結合相手が見当たらなくても、NULLであっても、必ずメインテーブルと結合テーブルの全行を出力する。
↓基本の形

```sql
select 出力するカラム名
from　テーブルA
full join テーブルB
on 両テーブルの結合する条件
```

↓イメージ

```sql
select A.name, B.name
from bookstore as A
full join author as B
on bookstore.authorid = author.id
```
Ionic3に入門してみる～その3 Angular4チュートリアル①～

# Ionicには実際にアプリケーションを作成してみるチュートリアルがない！
(少なくとも公式には)無い。無かった。
なので、Angular4のチュートリアルを読んでIonicで実行してみる。
チュートリアルページはこちら。
https://angular.jp/tutorial
日本語化されてるので(久しぶりに)日本語で読めるぞ！
前提として、ionicのblankプロジェクトを作成しておいてください。

# チュートリアル: ツアー・オブ・ヒーローズ
>ツアー・オブ・ヒーローズ チュートリアルはAngularの基礎をカバーしています。 
>このチュートリアルでは人材派遣会社がヒーローの集合を管理するためのアプリケーションを開発します。
なるほど。それにしても用意されてるヒーローがアメコミ過ぎてあんまりピンとこない。

チュートリアルでは下記を扱うらしい。

 * 要素を表示・隠蔽する、そしてヒーローデータのリストを表示するための組み込みAngularディレクティブを使う。
 * ヒーローの詳細やヒーローのリストを表示するためのAngularコンポーネントを作成する。
 * 読み取り専用データのための単方向データバインディングを使用する。
 * 双方向データバインディングを用いて、モデルを更新するための編集可能なフィールドを設置する。
 * キー入力やクリックといったユーザーのイベントに対しコンポーネントがもつメソッドをバインドする。
 * ユーザーがマスターリストからヒーローを選択し、詳細画面でそのヒーローを編集できるようにする。
 * パイプによりデータを整形する。
 * ヒーローを組み立てるための共有サービスを作成する。
 * さまざまなビューとそれらのコンポーネント間を遷移可能にするためにルーティングを使用する。

チュートリアルページには実際の動作イメージのアニメーションがありますのでぜひ見てみることをおすすめする。

# アプリケーションシェル
ionicのチュートリアルでそこはやったので、AngularCLIの利用の仕方はパス。

## アプリケーションのタイトルを変更する

ファイル名が違います。(まずionicのスタートプロジェクトとAngularのスタートプロジェクトが違うと思うので…)

app.component.ts → app.component.ts : TypeScriptで書かれたコンポーネントクラスのコードです。
app.component.html → app.html : HTMLで書かれたコンポーネントのテンプレートです。
app.component.css → app.scss : このコンポーネント専用のCSS(scss)です。
よく見るとcssからscssに変わっているので、全く同じではないです。が、今のところはあまり気にしないでください。

>コンポーネントクラスファイル(app.component.ts)を開き、titleプロパティの値をTour of Heroesに変更してください。
ionicのblankプロジェクトでは、なんやかんや色々書いていますが、ここでは
下記のように変えます。
ionic由来のものも全て消して完全にAngularチュートリアルに従ってみましょう。


```app.component.ts
import { Component } from '@angular/core';
@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  title = "Tour of Heroes";
}

```
```app.html
<h1>{{title}}</h1>
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/196422/d1aae46c-3cdc-f572-019e-deba613c9959.png)
だいぶ物寂しくなりました。

## アプリケーションのスタイルを追加する
チュートリアルにあるcssのコードを、そのままapp.scssに貼り付けてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/196422/94eb7cf7-90b2-a809-d8b6-74c3b0ec753d.png)

ほんのちょっとだけ豪華になりました。
Nuxt.jsのSPAモードでビルドしたアプリケーションをリロードすると404エラーになってしまう



先日、[FireKPT](http://firekpt.jacoyutorius.com)というKPTツールを公開してみました。
これはNuxt.js + Firebaseで構築していて、SPAモードでビルドしてS3でホスティングする、という構成になっています。

公開してみたところ、開発環境では発生しない不可解なバグが1つ見つかって、しばらく放置していたのですがいい加減と思って腰を上げて調べてみた次第です。

---


原因はよくよく考えてみれば単純で、
SPAモードでビルドすると全てのページの静的なHTMLを生成するので、_id.vueのような動的にルーティングしているページは生成されないのでした。だから404なんですねー。
公式のリファレンスにもしっかり書いてありました。


```
警告: generate コマンドでは 動的なルーティング は無視されます。
```

[Nuxt - ルーティング](https://ja.nuxtjs.org/guide/routing/)


ということで、ルーティングの構成を少し変えました。
動的ルーティングをやめ、データ抽出用のkeyはqueryパラメータに含めるように変更しました。


```js
this.$router.push({path: "/boards/" + key });
```

```bash
pages
├── boards
│   └── _key.vue
└── index.vue
```

↓

```js
this.$router.push({path: "/board", query: {id: key } });
```

```bash
pages
├── board.vue
└── index.vue
```


結果、URLは以下のように変わりました。

```
http://localhost:3000/boards/-L3a7FrVv5IK6PgjEKCG
↓
http://localhost:3000/board?id=-L9o_BQpgfASLhHd2pwR
```


データベースのkeyがそのままパラメータに含まれているのはREST的ではなくて落ち着かないですが、
問題はとりあえず解決できたので良しとしておきましょう。
ソースコードはこちらです。

https://github.com/jacoyutorius/nuxt_firebase_kpt
SmokePingでネットワーク遅延を可視化する

# SmokePingとは
- ネットワーク遅延をグラフで可視化するツール
- Webサーバ上で動作し、Webブラウザで確認する

# ゴール
DebianにSmokePingをインストールし、Webブラウザでネットワーク遅延データのグラフを確認する

# 導入準備
## 必ずインストールするパッケージ
- RRDtoolのインストール  
条件：1.2.x or later
`# apt install rrdtool librrds-perl` 
 
note: このコマンドを入力すると環境によっては、
「CD必要」のエラーがでる。解決策は/etc/apt/sources.listの
`# deb cdrom:[Debian GNU/Linux 9.4.0 _Stretch_ - Official amd64 DVD Binary-1 20180310-11:21]/ stretch contrib main`
をコメントアウトする。注)もちろん設定ファイルの編集前にcpで必ずバックアップをとろう    
  
- Webserver（今回はapache2）のインストール  
`# apt install apache2`
 - CGI、FastCGIを有効化する  
 # a2enmod cgi
 (Debianではデフォルトで有効化されている)
 - Apacheの起動  
 `# systemctl start apache2`

note:
aptコマンドでApacheをインストールした後、/etc/apache2/apache2.confを確認してみよう。 
また、`# apachectl -M`でApacheのモジュールを確認できる

note:
CGIの無効化は
`a2dismod cgi`

- Perl  
Perl 5.10.1 or later
DebianではPerlはデフォルトでインストールされています。  

## オプションでインストールするパッケージ
- FPing
`# apt install fping`

- EchoPing
- Curl
- dig
- SSH 

# SmokePingのインストール
`# apt install smokeping`
- SmokePingデーモンの起動
`# systemctl start smoke`
- この時点で一度http://自分のアドレス/smokeping/smokeping.cgiへアクセスし、
Webブラウザで起動の確認をする

# 設定ファイルの編集
- /etc/smokeping/config

# Webブラウザでネットワーク遅延のグラフの確認

# 参考資料
- SmokePingドキュメント About SmokePing (https://oss.oetiker.ch/smokeping/)
- smokeping_installドキュメント (https://oss.oetiker.ch/smokeping/doc/smokeping_install.en.html)
-  Network Management & Monitoring - Smokeping - Part I (https://nsrc.org/workshops/2016/rwnog-nmm/netmgmt/en/smokeping/exercises-smokeping-part1.htm)
- Smokeping - ArchWiki (https://wiki.archlinux.jp/index.php/Smokeping#smokeping_.E3.81.AE.E8.A8.AD.E5.AE.9A.E3.83.95.E3.82.A1.E3.82.A4.E3.83.AB.E3.81.AE.E6.A7.8B.E6.96.87)
Jetson TX1をモバイル化してみた（１）

# 背景
Jetson TX1の開発キットはただの小さいPCなので、いまいちメリットが伝わらない、応用の発想が広がらない（ように見える）。ということで、モジュールを取り出してモバイル化するための検討をしてみました。

# モバイル化
## バッテリー
キャリアボードは高価なため後回しにして、まずはバッテリー化を検討しました。モジュール単体は12Vで動作しますが、評価ボードは19Vみたいなので、なかなか対応製品がありませんが、世の中、ノートPCのためのモバイルバッテリーを持ち歩くという強者もいるらしく、下記の製品を見つけました。

[aceyoon ノートパソコン バッテリ 20000mAh](https://www.amazon.co.jp/gp/product/B06Y5BBDMS/ref=oh_aui_search_detailpage?ie=UTF8&psc=1)

繋いでみるとあっさり起動。5V〜24Vまで対応していて、変換アダプタも豊富なのでこれはすごい。サイズは、、、個人的にはセーフ。モジュールのみ平均10Wとすると24時間動作する⁈もっと小さいモバイルバッテリーとDC-DCコンバータで工作したいところですが、2.4A出力のモバイルバッテリーしか知らないので、評価ボードは無理そうです。キャリアボードを購入したら工作してみます。

![IMG_8280.JPG](https://qiita-image-store.s3.amazonaws.com/0/109483/6e43bd3d-2395-8ff1-3499-207262eff6a9.jpeg)

## モニタ
モニタは稼働を始めれば不要なケースが多そうですが、デバッグ目的に以下をチョイスしました。1,920x1,080に対応して3,000円程度とはすごいですね（ほとんど字が見えないので実際は640x480で運用）。

[Kuman 3.5インチ Raspberry Pi用 HDMI LCD](https://www.amazon.co.jp/gp/product/B071ZS3PQ8/ref=oh_aui_detailpage_o01_s00?ie=UTF8&th=1)

![IMG_3279.JPG](https://qiita-image-store.s3.amazonaws.com/0/109483/d08734a8-cda4-57d3-eb60-6f4749bc695b.jpeg)


## キャリアボード
下記を購入予定ですが、予算の都合によりペンディング中。誰かください。

[Orbitty Carrier for NVIDIA® Jetson™ TX2 & Jetson™ TX1](http://connecttech.com/product/orbitty-carrier-for-nvidia-jetson-tx2-tx1/)
ネットワークのフロー情報をELK6で可視化するVMをVagrantとAnsibleで生成した

ネットワークのフロー情報をELK6で可視化するVMをVagrantとAnsibleで生成しました。
インタフェースで受信したパケットをYAFでIPfixに変換し、IPfixの情報をsuper_mediatorでJSONに変換し、
ELK6で処理しています。

リポジトリはgithubにあります。
https://github.com/t-umeno/visualize_network_traffic

使用方法などは下記URLを参照してください。
https://github.com/t-umeno/visualize_network_traffic/blob/master/README.ja.md

2018/06/16のセキュリティマイスター道場(SecDojo) ~夏場所~ のLT枠で何か話します。
https://sec-dojo.connpass.com/event/89402/

2018/06/16のセキュリティマイスター道場(SecDojo) ~夏場所~ のLT枠の発表資料を公開しました。
https://www.slideshare.net/TakashiUmeno/visualize-network-traffic20180616

上記資料を更新しました。
https://www.slideshare.net/TakashiUmeno/visualizenetworktraffic-20181108-122136601
preg_replaceとmb_ereg_replace

[preg_replace](http://php.net/manual/ja/function.preg-replace.php)と[mb_ereg_replace](http://php.net/manual/ja/function.mb-ereg-replace.php)どっちを使うか。

後方参照を使いたいならpreg_replace
使う必要がないなら好きな方で。

# [preg_replace](http://php.net/manual/ja/function.preg-replace.php)

* 置換パターンは文字列もしくは配列
* 置換対象は文字列もしくは文字列の配列
* 返り値
 * 結果の文字列(マッチするものがなければそのまま)
 * エラー時に`NULL`を返す
 * 引数が配列の場合は配列
* 後方参照が使える `${0}${1}`

`${99}`までは存在しない場合は空文字として認識される（エラーは出ない）
`${99} → ''`
`${100} → '${100}'`
`$100 → '0'`　`${10}`と`'0'`に認識される `${10}`が存在しなければ`'0'`に認識される

# [mb_ereg_replace](http://php.net/manual/ja/function.mb-ereg-replace.php)

* 置換パターンは文字列
* 置換対象は文字列
* 返り値
 * 結果の文字列(マッチするものがなければそのまま)
 * エラー時に`FALSE`を返す
* パターン修飾子を設定する部分(`//u`)が不要
* 後方参照が出来なかった

# preg_replaceの動作例

```php
preg_replace('/b(c)/u', '${0}${1}', 'abcdef1');

// string(8) "abccdef1"
```

```php
preg_replace('/b/u', '', 'abcdef1');

// string(6) "acdef1"
```

```php
preg_replace('/b/u', '', ['abcdef1', 'abcdef2']);

/*
array(2) {
  [0]=>
  string(6) "acdef1"
  [1]=>
  string(6) "acdef2"
}
*/
```

```php
preg_replace(['/b/u', '/d/u'], ['B', 'D'], ['abcdef1', 'abcdef2']);

/*
array(2) {
  [0]=>
  string(7) "aBcDef1"
  [1]=>
  string(7) "aBcDef2"
}
*/
```

```php
preg_replace(['/b/u', '/d/u'], ['B'], ['abcdef1', 'abcdef2']);

/*
array(2) {
  [0]=>
  string(6) "aBcef1"
  [1]=>
  string(6) "aBcef2"
}
*/
```

```php
preg_replace(['/b/u'], ['B', 'D'], ['abcdef1', 'abcdef2']);

/*
array(2) {
  [0]=>
  string(7) "aBcdef1"
  [1]=>
  string(7) "aBcdef2"
}
*/
```

```php
preg_replace(['/b/u', '/d/u'], '', ['abcdef1', 'abcdef2']);

/*
array(2) {
  [0]=>
  string(5) "acef1"
  [1]=>
  string(5) "acef2"
}
*/
```
ServiceNowでデータ整理バッチ処理を作成する

# 概要

日々の業務によりトランザクションテーブルにデータを追加していったときに、保持期限が切れたら自動的に削除する仕組みをバッチ処理で作成する場合がある。
今回はServiceNowのScheduled script executionをこの仕組みを作成する。

## 仕様
整理対象のテーブルとデータの保持期限、データの保持期限を判定するための対象テーブルの列名を保持するテーブル「DataReductionSettings」テーブルを作成しておく。
Schedule script executionで作成された処理が起動すると、「DataReductionSettings」テーブルから整理対象のテーブル名、日付保持の列名、保持期間（日数）を取得する。
取得した情報を元に、GlideRecordのdeleteMultipleで条件に一致するレコードを一括削除する。

## 環境

ServiceNow:KINSGTONE

# 手順

## DataReductionSettingsテーブルを作成

下記の項目を持つテーブルを作成する。
なお、Table NameはLabelから自動生成されるが、今回の私の環境では「x_211750_angular_a_datareductionsettings」になっている。
これは後でスクリプトで利用するので、各自の環境に合わせて変更が必要だ。

|Column Name | Type |解説|
|---|---|---|
| tablename|String(Full UTF-8)|整理対象テーブル名|
| periodcolumnname|String(Full UTF-8)|日付判定用の列名|
| period|Integer|保持日数|

## Schedule script executionを作成

studiioのCreate Application FileでServer DevelopmentカテゴリーのSchedule script executionを選択してCreateをクリック。Nameや、実行間隔などは適当に設定する。またActiveのチェックは一旦はずして保存する。

![データ整理バッチ.png](https://qiita-image-store.s3.amazonaws.com/0/197947/f3f56ead-36a2-8c8e-4562-86f49ca7068f.png)


下記のスクリプトをRun this scriptに入力する。

```javascript

// 整理対象設定テーブルからレコードを読み込む
var reductionSettingsRecord = new GlideRecord('x_211750_angular_a_datareductionsettings');	
reductionSettingsRecord.query();

	
while (reductionSettingsRecord.next()) {
	// 整理対象テーブル名
	var tableName = reductionSettingsRecord.getValue('tablename');
	// 整理対象日付判定用の列名
	var periodColumnName = reductionSettingsRecord.getValue('periodcolumnname');
	// 保持期限（日数）
	var period = reductionSettingsRecord.getValue('period');
	
	gs.info('target table = ' + tableName);
	gs.info('periodColumnName = ' + periodColumnName);
	gs.info('period = ' + period);
	
        // 整理対象日付を「本日日付 - 保持期限（日数）」で算出
	var expiredDate = new GlideDateTime();
	expiredDate.addDaysLocalTime(Number(period * -1));
	
	gs.info('expiredDate = ' + expiredDate.getLocalDate());
	
	var reductionRecord = new GlideRecord(tableName);
        // 整理対象テーブルを「判定用の列名 <= 整理対象日付」で抽出 
	reductionRecord.addQuery(periodColumnName, '<=', expiredDate);
	reductionRecord.query();
	// 処理対象件数をあらかじめ取得しておく
	var targetCount = reductionRecord.getRowCount();
	
	gs.info('targetCount = ' + targetCount);
	// 一括削除実行
	reductionRecord.deleteMultiple();
	
}
```

スクリプトの説明はスクリプトコメントに記載しているため割愛する。

## 実行

Activeのチェックは外しているので定期実行はされないが設定画面の「Execute Now」をクリックすれば即時実行される。


# 最後に

少しだけ迷った事がある。日付の演算処理で、GlideDateTimeにsubtract(減算）があったので、subtractDayみたいなのを探してしまったが無かった。
少し考えて「addDaysLocalTime」で引数に負数を渡せば良い事に気づいた。

また、少しはまったことがある。

日付の演算結果を代入しようと最初は下記のようなコードを書いてしまっていた。

```javascript
var today = new GlideDateTime();
var expiredDate = today.addDaysLocalTime(Number(period * -1));
```

最近は、Javaでオブジェクトは基本的にイミュータブルで作る事に慣れているし、各種フレームワークなどもそのように設計されているものが多いため上記のコードを自然に書いてしまっていた。javascriptは基本的にミュータブルオブジェクトですね。

ちょっと困った事
deleteMultipleで処理対象となった件数を戻り値で返してくれない。
EffectCountのようなメソッドも無い。
今回は、実行直前に同じ検索条件で件数を取得しているが、これで良いのか他に良い書き方が無いのか探している。