OmniAICreator/Qiita-1.07M huggingface dataset:
ARM64のサーバ+DockerでNextcloudを動かす

## 概要
先日[ROCK64](https://www.pine64.org/?page_id=7147)というメディアサーバに特化したシングルボードコンピュータコンピュータを購入しました。
用途は外付けHDDを繋げてメディアサーバとして用いることですが、その際にDocker使ってNextcloud立てられれば幸せだなぁと思ったのでやりました。  
ARM64のOSが動いているものならRaspberry pi3とかでも動くと思います。
NextcloudのDBはMysqlが推奨なのでMariaDBのDockerImageを使いました。

※既にデータがある状態で使用する時はバックアップを取るなど十分注意して下さい。マウント先を間違えるなどするとデータが消えます。


### →現在はOfficalでRaspberry Pi等のシングルボードコンピュータをサポートしているようです。
### https://ownyourbits.com/nextcloudpi/

## 必要なもの
- 64BitのOS (ROCK64の場合は公式のDebianでは動かないのでubuntu minimalを入れました)
- ドメイン(外部から接続する場合)
- Docker環境(docker-compose)
- git(docker-composeのリポジトリを取ってくるのに使う)

## 手順
dockerの構築は以下のリポジトリに置いてあるのでcloneしてきます。
`$git clone https://github.com/Khromium/NextCloudARM64.git`

対象リポジトリに入って`docker-compose.yml`を書き換えます。
\#の部分を主に書き換えて下さい。下の実装ではmysqlのrootアカウントをそのまま使っています。

```docker-compose.yml
version: '2'
services:
    nextcloud:
        depends_on:
            - db
        build:
            context: "./nextcloud"
            args:
                domain: "your.domain.com" #ドメイン設定
        extra_hosts:
            - "your.domain.com:172.18.0.2" #ドメイン設定
        ports:
            - "80:80"#ドメイン設定
        environment:
            MYSQL_USER: root #MYSQLのユーザ
            MYSQL_PASSWORD: foo #MYSQLのパスワード
            MYSQL_HOST: db
            MYSQL_DATABASE: nextcloud
        volumes:
            - "/mnt/usbhdd:/var/www/html/data" #データのマウント先。外付けHDDに指定しておくと便利
        links:
            - db
    db:
        build: "./maria"
        environment:
            MYSQL_ROOT_PASSWORD: foo #MYSQLのルートのパスワード
        volumes:
            - "./data/maria:/config/databases" #Mysqlのデータ保存先
```

設定し終わったら`docker-compose.yml`のあるディレクトリ上で
`$docker-compose up --build`
して一度Dockerを動かします。
問題なく起動すればサーバのipにブラウザから接続するだけでNextcloudが表示されます。初回はadminアカウントの設定があります。
上記コマンドで起動した際は`Ctrl+C`で停止できます。 

これ以降にdockerを起動させる場合は`--build`を外して`-d`を引数に付けて下さい。バックグラウンドで起動するようになります。停止の際は
`$docker-compose stop`
で止めます。

### 外部接続する場合
初回起動でadminのアカウントを設定後、dockerコンテナ内の`/var/www/html/config/config.php`にドメインを設定します。
デフォルトではnano等のエディタが無いので入れてから行う必要があります。

```
$docker exec -it  docker_nextcloud_1 /bin/bash #dockerコンテナに接続
$apt-get update; apt-get -y install nano; export TERM=xterm #nanoのインストール＆設定
$nano /var/www/html/config/config.php #編集
...
'trusted_domains' =>
  array (
    0 => '192.168.1.23',
    1 => 'your.domain.com' #ドメインを設定する
  ),
...
```

## 所感とか
ROCK64のRAMが4GBあるせいか、かなり快適でした。
HDDもUSB3.0対応していたのでダウンロードスピードは20~30MB/sぐらい出ました。
しばらく様子見で使ってみようと思っています。

2018/01/13追記
鯖が飛んだので再構築しようと思って最初からdocker-composeにhddのマウント設定を間違って書いたまま動かした。そしたら初期設定でrsyncが走っているようでHDDのマウント先のデータが消えた＼(^o^)／ｵﾜﾀ
HDDマウントする際は慎重に...


### おまけ SSL化
Nextcloudはデフォルトではapacheで動いているので設定ファイルを書き換える。

```/etc/apache2/sites-available/ssl.conf
# VirtualHost内に Let's encrypt等で作った証明書を入れる。
SSLCertificateFile      /path/to/cert.pem
SSLCertificateKeyFile   /path/to/privkey.pem
SSLCertificateChainFile /path/to/chain.pem
# を設定
```

リダイレクト設定

```/etc/apache2/sites-available/httpd.conf
# VirtualHost内
<ifModule mod_rewrite.c>
RewriteEngine On
LogLevel alert rewrite:trace3
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</ifModule>
```
設定関連を反映させる

```
$ a2enmod ssl
$ a2ensite sslconfigname
```
SublimeText3 | 現在開いているファイルのディレクトリをiTerm2で開く

## (前提) Terminal パッケージをインストールしておく

## ターミナルの設定を開く

`Preferences > Package Settings > Terminal > Settings - User`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/3530f249-9632-4468-e645-3c1c7e4d1011.png)

## ターミナルを iTerm2に設定する

例:

```
{
  "terminal": "iTerm2-v3.sh"
}
```

新しいウィンドウではなく新しいタブで開く場合は、こちらも設定。

```
"parameters": ["--open-in-tab"]
```


![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/9afc6578-a23b-8f31-dd49-aa1f36d9ad31.png)

## Command + Shift + T で実行

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/73a40eec-16c0-cdd4-bf60-c533af301b41.png)

# 環境

- Sublime Text 3.0
- iTerm 3.1.3
- Mac OS X Sierra

# 参考

- [Edit "SublimeText3 | 現在開いているファイルをiTerm2で開く" - Qiita](https://qiita.com/drafts/dbef9d9a09b5498968d3/edit)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
[javascript]ルーレットのロジック

# ルーレットのロジック

## 仕様

- javascriptでルーレットを作る
- 操作はstart,stop,resetの3ボタンのみ
- startを押すとルーレットが周り(class=selected)、stopを押すと止まり確定(class=confirm)
- resetを押すと初期状態（起動時も実行する）

## ソース

### HTML

```HTML:test_2.htm
<html>
<head>
<link rel="stylesheet" type="text/css" href="test_2.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="test_2.js"></script>
<title>test_2:ルーレット</title>
</head>
<body>
<table id="t1">
<tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
<tr><td>5</td><td>6</td><td>7</td><td>8</td></tr>
<tr><td>9</td><td>10</td><td>11</td><td>12</td></tr>
<tr><td>13</td><td>14</td><td>15</td><td>16</td></tr>
</table>
<input type="button" value="start" id="start">
<input type="button" value="stop" id="stop">
<input type="button" value="reset" id="reset">
<div id="div"></div>
</body>
</html>

```
### css

```CSS:test_2.css
.confirm{background-Color:aqua;}
.selected{background-Color:red;}
```

### javascript
```javascript:test_2.js
$(function(){
  var stock,num,idx,time,timerId,swap;
  $('#start').on('click',function(){
    timerId=setInterval(function(){
      idx=Math.floor(Math.random()*num);
      $('#t1 td').removeClass("selected").eq(stock[idx]).addClass("selected");
    },time);
    $('#start,#reset').prop('disabled',true);
    $('#stop').prop('disabled',false);
  });
  $('#stop').on('click',function(){
    clearInterval(timerId);
    $('#t1 td').eq(stock[idx]).addClass("confirm");
    num--;
    swap=stock[num];
    stock[num]=stock[idx];
    stock[idx]=swap;
    $('#start').prop('disabled',num<=1);
    $('#stop').prop('disabled',true);
    $('#reset').prop('disabled',false);
    console.log(stock);
  });
  $('#reset').on('click',function(){

    stock=[];//ストックリスト
    for(var i=0;i<16;i++) stock.push(i);
    num=16;//残りマス
    time=10;//timerスピード
    idx=null;//現在位置
    $('#t1 td').removeClass("confirm").removeClass("selected");
    $('#start').prop('disabled',false);
    $('#stop').prop('disabled',true);
  }).trigger('click');
});
```



## ロジック

### データ管理

- データを配列stockに1から16までの数字として保持する
- startを押すとnumの初期値16を受けて、0~15までの数値を得る
- stopを押すとnumをデクリメント(初期値でいうと16→15)し、選択された番号idxとstockのnum番のデータを入れ替える

### 例

stockの初期値

```javascript
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
```

に対して、仮にidx=8であれば

```javascript
[0,1,2,3,4,5,6,7,15,9,10,11,12,13,14,8]
```

となる。次のstart時にはnumは15になっているのでstockの一番うしろを除くデータから抽出される。仮にidx=3であれば

```javascript
[0,1,2,14,4,5,6,7,15,9,10,11,12,13,3,8]
```
となる。ようは選ばれた数値が後ろから順番に埋まっていく感じ。
常に0~numの範囲で、選ばれていない数値が保持されている。
最終的にnumが1になった時点でそれ以上選択できないので終了。

### メリット

テーブルのセル状態を見る必要はなく、常にstockデータだけチェックするだけなので構造が単純にできる
CentOS 7でmod_auth_mysqlをインストールする方法

※sudoを一部入れ忘れたので、加筆しました（2017-10-15）
※apxsを実行してもLoadModuleが入らない場合があるため加筆いたします。

今回初めて記事を投下していきます伍希(いつき)と申します。

さて、過去の記事を参考にPostfixとかそのあたりを構築していく際にPostfixadminのところで躓いたのでメモ
見る方、ツッコミ所満載ですがお許しください。

#この記事を記載した理由
まぁ、適当です（大嘘）
調べたんですが、なんか記事が見つからないんですよね（笑）

#mod_auth_mysqlってなんぞや
Apacheに実装されているBASIC認証は.htpasswdファイルを使用して認証しているのですが、これだと大規模になったとき面倒なので、MySQLのデータベースに認証情報を保存する目的で用意されたApacheのプラグイン(mod)です。
（間違ってるかもしれないですが・・・）

#分かったところで材料です(某料理番組風)
- CentOS 7 (ちなみに私の時は7.4.1708です)
- ネットワーク接続(WAN)(まぁ・・・当たり前ですね）

あとは、順を追って説明していきます。

この下のことをやられる方
**何が起こっても責任は負えません。要は自己責任です**

#modを入れるまでの手順
##1. 必要なパッケージを入れていきます
あ、そうそうMySQLですが、CentOS7ではmariaDBになってますのでご注意を

```sh:コマンド
$ sudo yum install httpd httpd-devel mariadb mariadb-libs mariadb-devel subversion mod_dav_svn mod_ssl patch wget
```

##2. mod_auth_mysqlとpatchをダウンロードします
一応、作業用フォルダを作ってその中にダウンロードします

```sh:コマンド
$ mkdir ~/tmp && cd ~/tmp
$ wget https://downloads.sourceforge.net/project/modauthmysql/modauthmysql/3.0.0/mod_auth_mysql-3.0.0.tar.gz
$ wget https://sourceforge.net/p/modauthmysql/patches/_discuss/thread/efda3a06/c5a7/attachment/apache22.diff
```

##3. mod_auth_mysqlを作っていくよー
さて、ここまで来たら、次はmod_auth_mysqlを作っていきます。
まずは解凍します

```sh:コマンド
$ tar zxf mod_auth_mysql-3.0.0.tar.gz
$ cd mod_auth_mysql-3.0.0
```
次に、パッチを当てていきます

```sh:コマンド
$ patch -p0 < ../apache22.diff
```
さて、このままビルト・・・
**ちょっと待った！！！**

まだ、これで完了じゃないんです。
実は、このままだとエラーが出るのでまだ手直ししていかないとダメなんです。

てことで、コードを直します。

```sh:コマンド
$ sed -i 's#return r->connection->remote_ip;#return r->connection->client_ip;#g' mod_auth_mysql.c
$ sed -i 's#ap_requires(r)#apr_table_elts(r->headers_in)#g' mod_auth_mysql.c
```

上記は、mod_auth_mysql.cの908行目と1273行目のコードを修正しています。

908行目は```return r-> connection-> remote_ip;```から```return r-> connection-> client_ip;```に変更
1273行目は```const apr_array_header_t *reqs_arr = ap_requires(r);```から```const apr_array_header_t *reqs_arr = apr_table_elts(r->headers_in);```へ変更しています。

さて、次はコンパイルしていきます

```sh:コマンド
$ sodo apxs -c -L/usr/lib64/mysql -I/usr/include/mysql -lmysqlclient -lm -lz mod_auth_mysql.c
```
上記は64bit用ですので、もし32bitに方がいれば```/usr/lib/mysql```に修正してください。

さて、warning出てますが無視で大丈夫...かな？
※今回は無視します。

##4.入れていきます。
さて以下のコマンドを実行します

```sh:コマンド
$ sudo apxs -i mod_auth_mysql.la
```

これで完了となります
お疲れさまでした！！！！
もし、入ってるかわからない場合は
```httpd -M | grep mysql```をするといいかもしれません。

##Ex.ちょっとまて。入ってないぞ！！！
お怒りのことと思いますが、私に怒らないでください...
モジュールがインストールされているかを確認したいときは、

```sh:コマンド
$ httpd -M | grep mysql
mysql_auth_module (shared)
```

このようにすれは、上のように反応が返ってきます。
しかし、これがないときは編集をしないといけません。

```sh:コマンド
$ nano /etc/httpd/conf.modules.d/00-base.conf
```
を実行して(nanoのところはviでもvimでもいいですよ）

```sh:追加内容
LoadModule mysql_auth_module modules/mod_auth_mysql.so
```
を追記して保存して下さい。
あとは

```sh:コマンド
$ service httpd reload
か
$ systemctl reload httpd
```
を実行してください
HTML5のフォームバリデーションを使い倒す

HTML5になってフォームバリデーションも強化されていますが、さらにJavaScriptやCSSなどから使うこともできます。

# ご注意

ブラウザサイドのバリデーションは「ブラウザごとに対応・非対応がありうる」ということや「ユーザーレベルで書き換えが可能」ということもあるので、あくまで「サーバ送信せずにエラーをユーザーに伝えられる」、**入力補助**の機能と考えてください。サーバサイドのバリデーションに代わるものではありません。

# HTMLサイド
## 制約のかかる`<input type>`
HTML5では指定できる`<input>`の`type`も増えましたが、ものによっては指定できる値が決まっている（さらには、専用の入力フォームが用意される）ものがあります。

* `color`…`#abcdef`形式での色指定
* `date`…日付
* `datetime-local`…日時
* `email`…メールアドレス
* `month`…年月
* `number`…数値
* `range`…スライダーで目分量指定する値
* `time`…時間
* `url`…URL
* `week`…週

専用のフォームが出てくるタイプではバリデーション以前に不適当な値の入力すらできませんが、`email`や`url`はフリー入力なので不適当な入力も可能となってしまいます。

## バリデーション属性
`text`を筆頭として、入力フォームに特定の値を入力させるためのバリデーションをかけることができます。

* `required`…入力を必須にする
* `pattern`…入力パターンの指定（`text`など自由に入力できる系のみ）
* `maxlength`…最長の長さの指定（自由に入力できる系のみ）
* `minlength`…最短の長さの指定（自由に入力できる系のみ）
* `max`…最大値（数値や日付系のみ）
* `min`…最小値（数値や日付系のみ）
* `step`…値の刻み（数値や日付系のみ）

これらのバリデーションに引っかかった場合、フォームの`submit`は失敗します。ただし、iOS 10.2以下では、バリデーション自体は働くものの、**送信が止まらない**ので要注意です。

# CSS
バリデーションと関連したCSSセレクタが4つあります。

* `:required`…入力必須の入力要素にかかる
* `:optional`…入力必須でない入力要素にかかる
* `:valid`…バリデーションをクリアした入力要素にかかる
* `:invalid`…バリデーションに失敗した入力要素にかかる

これらを使うことで、入力状況によってスタイルを変えることができます。

# JavaScript
## セレクタ

上で書いたCSSセレクタを、JavaScriptからも使って、たとえば`:invalid`なフォーム要素をかき集める、というようなことができます。ただし、このセレクタは**jQueryでは正式サポートしていない**ので要注意です。ネイティブな`querySelectorAll`などを使いましょう。

## メソッド
`<input>`や`<form>`にある`.checkValidity()`を呼び出すと、手動でバリデーションを回すことができます。また、`setCustomValidity`で、JavaScriptからフォームを`invalid`にしてしまうことができます。

## イベント
バリデーションに失敗した入力フォームは、`invalid`イベントを起こします。ただ、このイベントは**バブリングしない**ので、「フォームでまとめて取りたい」ような場合には、キャプチャを使う（`formElement.addEventListener('invalid', function(){...}, true);`と第3引数に`true`を入れる）必要があります。
iTerm2 | Command+クリックで開くエディタを変更する

(エディタに限らない話だが)

Mac側での関連付けを変更すれば良いようだ。
たとえば `.txt` ファイルを Sublimetext で開くように設定してあれば、iTerm2 でも Sublimetext でリンク先を開くことが出来る。

## Mac側でファイルを開くアプリケーションを変更

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/61c58f59-5ba5-224f-f98a-ee2f24218a44.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/508a9db4-0b8a-0dd2-51e2-74ee28a12df5.png)

## iTerm2で、Command+クリックする

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/d703d7f9-43d7-55fa-c880-9b505fa0d094.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/0f365bb1-9fc1-3ffd-cc0a-7bebeecfc013.png)


# 環境

- iTerm2 3.1.3
- Mac OS X Sierra

# 参考

- [macos - iTerm command click to open with Atom - Super User](https://superuser.com/questions/987259/iterm-command-click-to-open-with-atom)









<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
PowerShellでFizzBuzzクイズ


# ネタ元

* [「FizzBuzzクイズ」クイズ－Ruby編](https://qiita.com/sumim/items/f26902f2b813c075a619)


# 実装

```FizzBuzzQuiz.ps1
function FizzBuzzQuiz ([string] $ConvertTo, [scriptblock] $ScriptBlock, [string] $Property = '#From')
{
    New-Module -ReturnResult -ArgumentList ($ConvertTo, $ScriptBlock, $Property) -ScriptBlock {
        Param ([string] $ConvertTo, [scriptblock] $ScriptBlock, [string] $Property)

        {Process {convert $_}}

        function convert ($x)
        {
            $n, $str = get $x
        
            if ($n | ForEach-Object $ScriptBlock)
                {$str | Add-Member -PassThru -MemberType NoteProperty $Property $n}
            else
                {$x}
        }

        function get ($x)
        {
            if ($x -is [int])
                {return $x, "${ConvertTo}"}

            if (converted $x)
                {return $x.$Property, "${x}${ConvertTo}"}

            throw "入力「${x}」は、整数および変換済文字列ではありません。"
        }

        function converted ($x)
        {
            $x -is [string] -and
            ($x | Get-Member -MemberType NoteProperty $Property) -ne $null
        }
    }
}

$function:fizz = FizzBuzzQuiz Fizz {$_ % 3 -eq 0}
$function:buzz = FizzBuzzQuiz Buzz {$_ % 5 -eq 0}
$function:pezz = FizzBuzzQuiz Pezz {$_ % 7 -eq 0}
$function:hozz = FizzBuzzQuiz Aho  {"${_}".Contains('3')}
```

# 実行例

```FizzBuzzQuiz_test.ps1
 1 | fizz        #=> 1
 3 | fizz        #=> Fizz
 1 | buzz        #=> 1
 5 | buzz        #=> Buzz
 1 | fizz | buzz #=> 1
 3 | fizz | buzz #=> Fizz
 5 | fizz | buzz #=> Buzz
15 | fizz | buzz #=> FizzBuzz
15 | buzz | fizz #=> BuzzFizz


  7 | fizz | buzz | pezz #=> Pezz
 21 | fizz | buzz | pezz #=> FizzPezz
 35 | fizz | buzz | pezz #=> BuzzPezz
105 | fizz | buzz | pezz #=> FizzBuzzPezz
105 | fizz | pezz | buzz #=> FizzPezzBuzz
105 | pezz | buzz | fizz #=> PezzBuzzFizz

  1 | fizz | buzz | pezz #=> 1
  3 | fizz | buzz | pezz #=> Fizz
  5 | fizz | buzz | pezz #=> Buzz
 15 | fizz | buzz | pezz #=> FizzBuzz
 15 | buzz | fizz | pezz #=> BuzzFizz
104 | fizz | buzz | pezz #=> 104


13 | fizz | buzz | hozz #=> Aho
 3 | fizz | buzz | hozz #=> FizzAho
35 | fizz | buzz | hozz #=> BuzzAho
30 | fizz | buzz | hozz #=> FizzBuzzAho
30 | hozz | buzz | fizz #=> AhoBuzzFizz


10..20 | fizz | buzz
# Buzz
# 11
# Fizz
# 13
# 14
# FizzBuzz
# 16
# 17
# Fizz
# 19
# Buzz
```
POST送信したいのに301リダイレクトされちゃう

あるページにpostで遷移したいのになぜか301リダイレクトされてpostの中身が消えた。

調べると流石ウィキペディア先生。

> 例としては、ファイルではなくディレクトリに対応するURLの末尾に/を書かずにアクセスした場合に返される
[wikipedia](https://ja.wikipedia.org/wiki/HTTP%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89)

意外と知らなかったのでメモ。
geometry > link > CUBEMAP TEXEL SOLID ANGLE by Rory (2012) > 球面上から平面へのprojection

参考: Reeger et al., Numerical Quadrature over the Surface of a Sphere, STUDIES IN APPLIED MATHEMATICS, 137:174-188, 2016.
http://onlinelibrary.wiley.com/doi/10.1111/sapm.12106/abstract

p177

```math
\sum_{K=1}^{K}\int\int{f(x,y,z)}dS
```

上記の式が以下となる。

```math
\sum_{K=1}^{K}\int_{t_k}\int{f(x_k',y_k')\frac{\rho^3}{(\rho^2 + (x_k')^2+(y_k')^2)^{\frac{3}{2}}}}dx'_kdy_k'
```

ここで、x,y,zは球面上の座標。
x', y'は球面に接する平面上の座標。


2つ目の積分に近い式は以下で見つけた。
http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/

まだ式変形はよく分からないが、(3/2)が出てくる理由は理解した。
macOS Sierra 10.12.6 のアップデート障害対策

# macOS Sierra 10.12.6のアップデート不良
2017年７月に<b>macOS 10.12.6のアップデート</b>が来たので，いつも通りアップデートのために再起動したところ，<b>起動画面のアップルマークのダイアログ</b>が右一杯に達して，その後login画面にならないという障害に陥った．

ネットの調査や，試行錯誤を経て，障害対策できたので，対処方法についての個人的なメモを残す．

# 障害回避方法　（いきなり結論)
私のMacの場合は<b>10.12.5</b>では問題なかったが，<b>10.12.6</b>に対応していないドライバが原因だった様なので，関係がありそうな拡張機能，ドライバを削除し，正常起動することを確認した．

障害内容としては，

* アップデート起動時の<b>アップルマーク</b>のプログレスバーが最後まで行っても先に進まない(login画面が出ない)

心あたりとしては，

* <b>キャノンのプリンタ</b>とかUSBがらみのドライバーをインストールしたことがある
* これまでのアップデートでは障害は発生しなかった
という感じ．

やったこととしては，

- リモートでフリーズしているMacにloginする
- 怪しそうな拡張機能，ドライバを削除
- 再起動 (強制電源断＆再電源導入)

以下，コマンド例．

```
$ ssh username@ip_address  # 別のマシンから対象macにssh loginする

# 怪しそうなファイルがCanon printer Driverとのことなので，拡張機能から退避
$ sudo mv /Library/Extensions/CIJUSBLoad.kext/ ~/tmp/ 

# ついでに昔使っていたDisplayLinkのUSBディスプレイのドライバも退避
$ sudo mv /Library/Extensions/DisplayLinkDriver.kext/ ~/tmp/
$ sudo mv /Library/Extensions/DisplayLinkEthernetDriver.kext/ ~/tmp/
```
強制電源断後，再起動．

　　　→これで，正常稼動．

なお，試してはいないが，リモードで操作できなくても，<b>Command-R</b>で起動して，macOSの復元ユーティリティを表示させ，メニューバーのユーティリティーメニューから，ターミナルを起動させ，上記のコマンドで操作するというのも1つの方法の様だ．

# 障害原因
結果オーライで，最終的な原因究明までは至っていないが，

- CanonのUSBプリンタドライバ（バージョン不明) →[参照リンク](https://discussions.apple.com/thread/8019574?start=0&tstart=0)
- DisplayLinkのドライバ

のいずれかが，マイナーチェンジのmacOSに対応していなく，起動障害を引き起こしたのだろうと予想している．
Canonのプリンタドライバは，2016年12月に購入した，TS8030設定時に入れたモノ．


# アップデートの際の事前準備
もし，macOSを10.12.6にアップデートをしようと考えているのなら，事前に(OS復旧可能な)<b>バックアップ</b>，<b>不要ドライバの削除</b>，<b>外部アクセスできるような設定</b>をしておくのが望ましい．

## バックアップ
とにかく，日々Macを使っている場合は，バックアップは必須．
TimeMachineでのバックアップで充分．アップデートの回避方法が見つからなかった時は，2回ほどTimeMachineで10.12.5に戻して，通常環境を維持した．

障害対処できない場合，前の状態に戻れる可能性があることは，心強い．
但し，復旧時間が2〜3時間以上かかるので，時間的に余裕のあるときにアップデートするべきだろう．

## 不要ドライバの削除 
使っていない周辺機器のドライバは，その後のトラブル回避の為に，積極的に削除した方がいい.
下記のフォルダは，時々眺めていて，知らない拡張機能は削除するようにした方が良いだろう．
もちろん，正当派としては，正式なアンインストーラーで消すのがいいだろうが，最終手段としてコマンドで削除(または移動)させる．

/Library/Extentions/
/Library/LaunchDaemons/
/Library/Preferences/

## sshログインできるようにしておく
外部からloginして操作できると，何かと便利．但しsshとかわからない人は，手を出さないか，勉強するか，知っている人にお願いするのがいい．
参考：MacにSSHログインする方法 - リモートログインの設定　→[リンク](https://pc-karuma.net/mac-ssh-login/)

## 誤解
今回の障害対策で時間がかった原因の1つとして，障害原因をセキュリティソフトの<b>ESET</b>にあるのではないかと思い込んだことが大きかった．<b>ESET</b>をアンインストールしてからアップデートに挑んだ訳だが，ESETには今回は非がなかった．


## 参考 (今回削除した拡張機能)
結局，障害の主原因は不明のままだが，今回の作業で削除した項目を（怪しい順に)列挙しておく．

- Canon Printer Driver - CIJUSBLoad.kext (バージョン 16.0.10, 変更日 2016/2/16)
- DisplayLink - com.displaylink.displaylinkmanager.plist
- DisplayLink Driver - DisplayLinkDriver.kext (バージョン 2.5 (68993), 変更日 2016/3/10)
- DisplayLink Ethernet Driver - DisplayLinkEthernetDriver.kext (バージョン 1.11.0, 変更日 2016/3/10)
- m2TVEnabler - com.makie.m2TVEnabler.plist
- OneTVBooster - com.makie.OneTVBooster.plist
- Fitbit - com.fitbit.galileod.plist
Android: ListViewの使い方

Android studio 2.3.3 でListViewを使おうとしたときに様々な情報に混乱したので、今後迷わないようにメモ書きを残しておきます。
ListViewを使うときにはリソースファイルで文字列リストを定義しておいて、IDで参照するということだったのですが、次のようにすると失敗しました…。

### 失敗例
```xml:string.xml
<resources>
    <string-array name="spice">
        <item>田中</item>
        <item>山崎</item>
        <item>佐藤</item>
    </string-array>
</resources>
```
リソースファイルとしてstring.xmlから参照してもだめなようでした。
別にarray用のファイルを用意するとうまくいきました。
### 成功例
```xml:array.xml
<resources>
    <string-array name="namae">
        <item>田中</item>
        <item>山崎</item>
        <item>佐藤</item>
    </string-array>
</resources>
```
```xml:activity_main.xml
<ListView
        android:layout_width="0dp"
        android:layout_height="495dp"
        android:entries="namae"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        tools:layout_editor_absoluteY="8dp" />
```
これでうまくいくはず。
jquery validationでelement undefinedエラー

jquery validationでelementがundefinedであるとのエラーが発生した。
原因特定に非常に時間を要したので同じ問題にあった人のために詳細と対策を公開する。

エラー発生ポイントは、jquery.validation.min.jsを整形した状態で23行目の

```js
b = c.element(this) && b;
```

という行。cがundefinedになっていた。
当該行の前後は下記の通り

```js
valid: function () {
            var b, c;
            return a(this[0]).is("form") ? b = this.validate().form() : (b = !0, c = a(this[0].form).validate(), this.each(function () {
                b = c.element(this) && b;
            })), b;
        }
```

発生状況は次の通り。
1. あるformタグ内のjquery dialogで利用するためのdivを設置。
2. jquery dialogでdiv要素をdialog化。
3. formに対しvalidateをかける。
4. dialog内の`<input type="file">`でファイルを選択。
5. そのフォーカスがinputからはずれた瞬間にjquery validationがエラーを投げた。

原因の可能性としては、もともとform内にあったinput要素がdialog化することでformブロックの外に再定義され、jquery validationがinputのformを見失ったことが問題となったと考えられる。
対策として、dialogに使用するdiv要素を最初からformの外で定義したところ、エラーは発生しなくなった。
CSS3 で縦長・横長をうまくトリミングする

# (A) 
通常のトリミング指定だとこのようになる。

```
img {
  width: 480px;
  height: 200px;
  object-fit: cover;
}
```


# (B)
画像の縦横比率がバラバラの場合、比率が異なることに起因して、中央にズームされすぎる場合がある。
そういう時はmin/max指定で幅を設けると、どちらかに合わさった上でトリミングされる。

```
img {
  min-width: 200px;
  max-width: 480px;
  height: 200px;
  object-fit: cover;
}
```


# (C)
例えば、200x338の縦長の画像は、 （A）の指定だと上下が見切れすぎてしまい、何が写っているが分からない。そこで高さを指定しつつも横幅はmax-width指定にすると、横幅が広がらない。高さにフィットするので全体が見えるようになる。

```
img {
  max-width: 480px;
  height: 200px;
  object-fit: cover;
}
```

ただ、max-width指定だけだと横幅が小さくなりすぎる。200x338の縦長の画像を height 200 まで縮めると、 width 118 になる。 （縦横比率を保ったまま、縦の長さに合わさってしまうため、横幅が小さくなる。）

本来 width 480 指定したい所に横幅 118 が混ざるのは避けたいと考えた時には、(B)のように、 min-width も同時に指定する。
min-width200 にまで縮んだ上で、はみ出た縦サイズ部分が object-fit: cover によって見切れる。
VisualStudioのプロジェクトリソースを使いやすく列挙する

VisualStudioのプロジェクトで
![スクリーンショット (63).png](https://qiita-image-store.s3.amazonaws.com/0/199750/fb6ec4db-7b9e-2f0f-601b-1fd360b07da8.png)

こういうPropertiesから設定できるリソースにアクセスする場合、

```C#:test.cs
var bitmap = Properties.Resources.add_user ;
```

とできるようなアクセスクラスが作成されてるのでどのプロパティを使えばいいかわかっている場合は非常に簡単になった。

ところが、これらをまとめて扱いたい場合はやっぱりLinqが使えたほうがありがたいのでどうしたもんかと。

## リフレクション使ってぶん回す

```C#
    //リフレクションを使ってBitmap型のリソースを取得
var t = typeof(Properties.Resources);
foreach (var p in t.GetProperties(BindingFlags.Public | BindingFlags.NonPublic |BindingFlags.Static)) {
    if (p.PropertyType == typeof(Bitmap)) {
        //いろいろする
    }
}
```

これでも動作はするんだけど自前で定義済みのリストをリフレクション経由で読み込むとかクソダサい。

## ResourceSetを使う

```C#
foreach (var b in Properties.Resources.ResourceManager
    .GetResourceSet(System.Threading.Thread.CurrentThread.CurrentCulture,true,true)
    .OfType<DictionaryEntry>()
    .Where(e=>e.Value is Bitmap)) {
    //いろいろする
}
```

リフレクションよりマシだけど結局取れたのが`DictionaryEntry `で `(string)b.Key`みたいにキャスト不可避なのがダサい。

## 無理やり最適化

```C#:ResourceManagerExtender.cs

public static class ResourceManagerExtender {
    public static IEnumerable<KeyValuePair<string,T>> getEntries<T>(this ResourceManager rman) {
        return rman.GetResourceSet(System.Threading.Thread.CurrentThread.CurrentCulture, true, true)
            .OfType<DictionaryEntry>()
            .Where(e => e.Value is T)
            .Select(e => new KeyValuePair<string, T>((string)e.Key, (T)e.Value));
  
    }
}

```
こうして

```C#
foreach (var b in Properties.Resources.ResourceManager.getEntries<Bitmap>()) {
    list.Images.Add(b.Key, b.Value);
}
```
こうじゃ。

## 結局
スマートじゃない。
リソース周りってあんまりブラッシュアップされてない雰囲気ある。

##参考
[ResourceManager クラス \(System\.Resources\)](https://msdn.microsoft.com/ja-jp/library/system.resources.resourcemanager)
[Survey] Kaggle - The Nature Conservancy Fisheries Monitoring 10位解法まとめ

Kaggle - The Nature Conservancy Fisheries Monitoring[^1]の10位解法[^2]の調査記事です

Name: Krzysztof Dziedzic
Kaggle Discussion: https://www.kaggle.com/c/the-nature-conservancy-fisheries-monitoring/discussion/31538

- 物体検出のためにVGG初期化でのFaster RCNNのregion proposal networkの実装．
- 分類にはResNet 50を利用．
- 物体検出の訓練にはデータセットのみ利用(分類ではフォーラムに投稿されたデータセットも利用)
- 7つのモデルの平均で予測

## References

[^1]: Kaggle, [The Nature Conservancy Fisheries Monitoring](https://www.kaggle.com/c/the-nature-conservancy-fisheries-monitoring)
[^2]: Krzysztof Dziedzic, [Solution Sharing and Congratulations](https://www.kaggle.com/c/the-nature-conservancy-fisheries-monitoring/discussion/31538)
Rails備忘録

メモがわり。そのうちまとめるかも

# thinでサーバ起動

`rbenv exec thin start`

# ローカルにgemインストール

Gemfileを書き換えて

`rbenv exec bundle install`




# Model

## scaffold

`rails g scaffold モデル名 カラム名1:データ型1 カラム名2:データ型`

### 対応するデータ型

|シンボル|説明|対応するMySQLの型|
|---|---|---|
|:string|文字列|varchar(255)|
|:text|長い文字列|text|
|:integer|整数|int(11)|
|:float|浮動小数|float|
|:decimal|厳密な精度の少数|decimal|
|:datetime|日時|datetime|
|:timestamp|より細かい日時|datetime|
|:time|時間|time|
|:date|日付|date|
|:binary|バイナリデータ|blob|
|:boolean|真偽型|tinyint(1)|

### application.rbを書き換えてもscaffoldに反映されない

`spring stop`

## DB変更migrationファイル作成

`rails g migration ***ChangeSomething***`

### add_column

```ruby
add_column :table_name, :column_name, :data_type, null: true
```

## DBつくりなおし
`rake db:migrate:reset`

## varcharの文字数指定、null指定、コメント指定、デフォルト値設定

```ruby:ruby

t.string :name, :limit => 300, null: false, comment:"はぴはぴするにぃ", default: 0

```

## インデックスをつける

```ruby:ruby
t.string :name, index: true
```

## ユニークキーをつける

### 単一フィールド
```ruby:ruby
add_index :target_table, :name, unique: true, name: 'index_name'
```
### 複数フィールド
```ruby:ruby
add_index :target_table, [:name, :date], unique: true, name: 'index_name'
```

## cron

`gem 'whenever'`

### wheneverを使う

`bundle exec wheneverize .`


# View

## jsの読み込み

```slim:slim
= javascript_include_tag 'target.js'

```

## slim

### テンプレートエンジンのデフォルトをslimに変更

```ruby:application.rb
  class Application < Rails::Application
    config.generators.template_engine = :slim 
  end
```

### erbをslimに置き換え

`for file in app/views/**/*.erb; do rbenv exec erb2slim $file ${file%erb}slim && rm $file; done`

### テンプレートの出力結果を文字列として変数に格納(Model内で)

「TargetController」は該当のコントローラ。
`local`はviewで使う変数

```ruby:ruby

renderer = ApplicationController.renderer.new TargetController.renderer.defaults
p renderer.render template: 'path/to', locals: { }

```

# デバッグ

## pry

### Viewの途中でbreak(slim)

`- binding.pry`

## ログ

`tail -f log/development.log`
Unity で ml-agents を使う時のベストプラクティス

## 前書き
　前回、[ML-Agents のインストール方法](https://qiita.com/dora-gt/items/bacce436de2a3cdb1ef4)について書きました。実際に自分で環境を作るところまでは書けなかったのですが、今回は実際に使う時のベストプラクティスについて翻訳の記事を書きたいと思います。

　自分自身まだ修行中なので、より俯瞰した「使い方はこれです！」みたいなものは書けないのですが、自分で環境を作る際の[ベストプラクティス](https://github.com/Unity-Technologies/ml-agents/blob/master/docs/best-practices.md)が Unity から公開されていますので、これはとりあえず皆んな知っておいた方がいいだろう、という訳で書いてみます。

## Unity で ml-agents を使う時のベストプラクティス

### 全般
- 一般的に、エージェントが学習できる様に最初はごくシンプルな問題から開始し、徐々に複雑な問題にしていくのがよいでしょう。
    - ※おそらくカリキュラム学習の事を言っているのではないかと思うが、それを行うには ppo.py を起動する際に `--load` オプションを利用すれば、前回の学習結果を引き継げる。また、ResetParameter をうまく利用すれば、リセット時に環境の難易度を変更する事ができる。Python 側に手を入れる場合は、`UnityEnvironment.reset` 時に `config=` でハッシュを与える事で ResetParameter を与える事ができる。
- 可能であれば、Player Brain を使ってエージェントをコントロールしてタスクを達成できる事を確認しておくとよいでしょう。

### 報酬（Reward）
- より安定した学習をさせるためには、基本的には報酬は 1.0 よりも小さく設定されていた方がよいでしょう。
- 一般的に、目標とする振る舞いを形成するためにはマイナスの報酬（罰）よりも、プラスの報酬の方がより効果的でしょう。
- 歩行する様なタスクの場合、前方への移動に対して微小な報酬（+0.1）を与えるという手法が一般的に使われます。
- もしより早くタスクを完了して欲しい場合、ステップ毎に微小な罰（-0.1）を与えるとよいでしょう。

### 状態（State）
- 各状態の変数の値はおよそ 1.0 に正規化すべきでしょう。
- エージェントがより適切な状況判断をして行動するために必要な全ての変数を状態に含むようにすべきでしょう。
- オブジェクトのタイプ（剣、盾、弓）といったカテゴリの分類を行う様な変数は [one-hot な表現](http://www.weblio.jp/content/One-hot)にすべきでしょう（例：3 -> 0, 0, 1）。

### アクション（Action）
- 連続的な制御を行う場合、アクションの値は適切な範囲にクリップするとよいでしょう。
Dockerのデータ永続化関連について

どうも、かちおです。Dockerのデータ永続化について色々とややこしかったのでまとめました。

# データ永続化とは

Dockerは、Dockerイメージと呼ばれるアプリケーションのバイナリがはいったデータを元にコンテナと呼ばれる小型の隔離マシンを立ち上げます。そしてそのコンテナのライフサイクルが簡単に作成・破棄できるように考えられているのですが、サーバーを立ち上げている途中で変化したデータは残しておきたいため、コンテナの特定のデータだけを「永続化」することができます。

# 方法

1. ボリューム(ホストと同期)
2. ボリューム(隔離した保存領域)
3. 他のコンテナをマウント

# 1.ボリューム(ホストと同期)

これは、ホストマシンの特定のディレクトリと、コンテナの中の特定のディレクトリとリアルタイムで同期するものです。コンテナが破棄されてもホストのディレクトリの内容は残るので、また新しく立てたコンテナと同期することができます。また、ディレクトリではなく単一のファイルを指定することもできます。
また、セキュリティのためリードオンリー(コンテナ側からは変更不可)を指定することもできます。

## 使い方

```bash
$ docker run -v /host/path:/container/path image-name
# ホストの/host/pathとコンテナ内の/container/pathを同期してimage-nameを起動

$ docker run -v /host/path:/container/path:ro image-name
# ホストの/host/pathとコンテナ内の/container/pathをリードオンリーで同期してimage-nameを起動。コンテナ側からはファイルの変更ができない。
```

>例:
>
```bash
$ docker run -v ./public:/usr/share/nginx/html:ro nginx
```
この場合、dockerコマンドを打ち込んだディレクトリ内のpublic/とコンテナ内の/usr/share/nginx/html/が同期されます。ホスト側でファイルに変更を加えると同時にコンテナ内にも反映されます。コンテナ側の変更は無視されます。

# 2. ボリューム(隔離した保存領域)

さきほどのものは、あくまでホストの内容を同期orコピーしたい場合のものでした。そうではなく、ただコンテナの特定のディレクトリを残しておきたいときに使うのがこれです。
手順としては、保存領域のの作成→コンテナに領域を追加しつつ起動となります。

## 保存領域の作成

```bash
$ docker volume create volume-name
# volume-nameという名前で保存領域を作成します。
```

> 例
>
```bash
$ docker volume create database-data
```
この場合、database-dataという名前で隔離領域が作られます。

## コンテナに保存領域を追加しつつ起動

```bash
$ docker run -v volume-data:/container/path image
# コンテナ内の/container/pathディレクトリがvolume-dataと同期される用になります。

$ docker run -v volume-data:/container/path:ro image
# コンテナ内の/container/pathディレクトリがリードオンリーでvolume-dataに保管される用になります。
```

>例
>
```bash
$ docker run -v database-data:/var/lib/mysql mysql
```
この場合、mysqlのコンテナの中の/var//lib/mysqlがdatabase-dataという保存領域と同期されます。コンテナを破棄しても、ふたたび生成するときに同じ用に起動すればmysqlのデータが復活します。


以上が隔離した保存領域です。はっきり言えば、1のホストと同期する場合の、同期するパス指定しなくていいイメージです。というか内部的にはそうなっています。ホストの任意のディレクトリと同期しなくていい場合は1よりもこちらのほうが簡単で便利というわけですね。

追記: __今更ですが、ボリュームを作成しなくても使えるみたいです。__

# 3.他のコンテナをマウント(データボリュームコンテナ)

以上は、特定のコンテナの任意のパスを永続化するものでした。ですが、同じボリュームを共有するコンテナを起動するたびに毎回指定するのは面倒です。ということで、データボリュームコンテナというのを作ることができます。
1つ、適当なコンテナを起動し、そこのボリュームを他のコンテナからオプション1つで同じようにマウントできます。

```bash
$ docker -v /path/to/directory:/path/to/directory --name data-volume image /bin/true
# これで、data-volumeという名前で、ホストとコンテナ内を同期するコンテナを起動できます。

$ docker --volumes-from data-volume image
# これで、data-volumeがマウントしているボリュームを同じようにマウントします。つまり`v /path/to/directory:/path/to/directory`を指定したことになります。
```

これが使えると、一個データボリュームコンテナを作ってそこに任意のボリュームをどんどんマウントしていけば、data-fromオプションをつけるだけで全く同じマウントをしたコンテナを作ることができます。

# ちなみに : sshfというのが

```bash
$ docker volume create --driver vieux/sshfs -o sshcmd=user@host.com:/path/to/directory -o password=password sshvolume
```

とかやると、ssh接続できる別のマシンの任意のディレクトリをつかってボリュームを作成できます。
ASP.NET Web API で Utf8Json を使ってみる

最速を体験したくてやってみました！
[Utf8Json](https://github.com/neuecc/Utf8Json)

参考：[ASP.NET Web API で Jil JSON Serializer を使ってみる](http://gooner.hateblo.jp/entry/2014/12/02/jil-json-serializer/ "ASP.NET Web API で Jil JSON Serializer を使ってみる")

軽量APIではデフォルト(Json.NET)との違いが見いだせず・・・
※実装理解していないので使い方が間違っているかも？？

##サンプルコード
```csharp:Utf8JsonMediaTypeFormatter.cs
public class Utf8JsonMediaTypeFormatter : MediaTypeFormatter
{
    public Utf8JsonMediaTypeFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));

        SupportedEncodings.Add(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true));
        SupportedEncodings.Add(new UnicodeEncoding(bigEndian: false, byteOrderMark: true, throwOnInvalidBytes: true));
    }

    public override bool CanReadType(Type type)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }
        return true;
    }

    public override bool CanWriteType(Type type)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }
        return true;
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
    {
        return Task.FromResult(JsonSerializer.NonGeneric.Deserialize(type, readStream));
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
    {
        JsonSerializer.NonGeneric.Serialize(type, writeStream, value);
        return Task.FromResult(writeStream);
    }
}
```

```csharp:WebApiConfig.cs
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Formatters.RemoveAt(0);
        config.Formatters.Insert(0, new Utf8JsonMediaTypeFormatter());
 
        config.MapHttpAttributeRoutes();
 
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}
```
Pythonで世界のナベアツ問題を解いてみた。

## 前書き
Pythonの練習がてら、FizzBuzzよりもほんのちょっと手の込んだモノを作ろうと思った。

世界のナベアツの「3のつく数字と3の倍数だけアホになる」は、文字操作系もちょっぴりあるから、FizzBuzzの1歩先としてはちょうどいいかなー、と。

## 工夫など
ちゃんとアホになって数字を叫んで欲しかったので、「アホ」を返すのではなくて、「サァーン！」とか叫んでくれるようにした。10000まで対応。（それ以降は焼き増しコードなので・・・）

Python3から入ったらしいType Hints使ってみた。Obj-C好きっ子としては是非使いたかった。
参考: [Pythonではじまる、型のある世界 - Qiita](https://qiita.com/icoxfog417/items/c17eb042f4735b7924a3)

アホになる判断よりも、ナベアツワード（？）を生成するほうがめんどかった。もっと上手い方法あると思う。

## コード

```py3:nabeatsu.py

# アホ数字か否か
def is_aho(i: int)-> bool:
    # Is string 3 in the number?
    if '3' in str(i):
        return True

    # Is the number dividable by 3?
    if i % 3 == 0:
        return True

    return False


# 3の倍数と3のつく数字の時だけアホになる。
def say_nabeatsu(i: int) -> str:
    limit = 10000
    is_nabeatsu = is_aho(i)

    ####
    if not is_nabeatsu:
        return str(i) + ''

    if i > limit:
        return 'アホ'

    # To generate Nabeatsu word
    nabeatsu_dic = {
        1: '',
        2: 'ニ',
        3: 'サァーン',
        4: 'ヨーン',
        5: 'ゴー',
        6: 'ローク',
        7: 'ナーナ',
        8: 'ハーチ',
        9: 'キュー',
        0: ''
    }

    nabeatsu_ten_dic = {
        1: 'ジュー',
        2: 'ニージュ',
        3: 'サァーンジュ',
        4: 'ヨーンジュ',
        5: 'ゴージュ',
        6: 'ロークジュ',
        7: 'ナーナジュ',
        8: 'ハーチジュ',
        9: 'キュージュ',
        0: ''
    }

    nabeatsu_end_dic = {
        1: 'イーチ',
        2: 'ニーッ',
        3: 'サァーン',
        4: 'シーッ',
        5: 'ゴーッ',
        6: 'ローク',
        7: 'シーチ',
        8: 'ハーチ',
        9: 'キュ-ッ',
        0: ''
    }
    nabeatsu_str = ''
    if i >= 1000:
        nabeatsu_str += nabeatsu_dic[int(i / 1000)] + 'セェーン'
    if i >= 100:
        tmp_i = i - (int(i / 1000) * 1000)
        nabeatsu_str += nabeatsu_dic[int(tmp_i / 100)] + 'ヒャク'
    if i >= 10:
        tmp_i = i - (int(i / 100) * 100)
        nabeatsu_str += nabeatsu_ten_dic[int(tmp_i / 10)]

    nabeatsu_str += nabeatsu_end_dic[i % 10] + '!'
    return nabeatsu_str


def main():
    end_num = 10000
    for x in range(1, end_num + 1):
        print(say_nabeatsu(x))


if __name__ == "__main__":
    main()
```

```bash:出力
1
2
サァーン!
4
5
ローク!
7
8
キュ-ッ!
10
11
ジューニーッ!
ジューサァーン!
14
ジューゴーッ!
16
17
ジューハーチ!
19
20
ニージュイーチ!
22
ニージュサァーン!
ニージュシーッ!
25
26
ニージュシーチ!
28
29
サァーンジュ!
サァーンジュイーチ!
サァーンジュニーッ!
サァーンジュサァーン!
サァーンジュシーッ!
サァーンジュゴーッ!
サァーンジュローク!
サァーンジュシーチ!
サァーンジュハーチ!
サァーンジュキュ-ッ!
40
...
...
...
9989
キューセェーンキューヒャクキュージュ!
9991
9992
キューセェーンキューヒャクキュージュサァーン!
9994
9995
キューセェーンキューヒャクキュージュローク!
9997
9998
キューセェーンキューヒャクキュージュキュ-ッ!
10000
```

## あとがき
Pepperあたりに組み込んで喋らせたい。

多分、こちらの記事の方が賢い。
[Pythonでナベアツしてみた | ハックノート](https://hacknote.jp/archives/18068/)

## 更新履歴
2017-10-13: `str_i.find('3') >= 0:` → `'3' in str(i)`（コメントを受けて。）
> PHP、Obj-C民にこの発想はなかったなー。
話題のAmazon Alexa について調べた

# Amazon Alexa とは

__Alexa__ とはAmazonが提供する、クラウドベースの音声認識サービスである。  
Alexaに対応したデバイスが認識した音声はクラウドサービスに送信される。クラウドサービスは音声をテキスト変換し、そのテキストを処理し、処理結果をデバイスに返して音声として再生される。

## Alexa が持っている2つのフレームワーク

- Alexa Voice Service(AVS)  
    音声認識や自然言語解釈等を行う。  
    具体的にはデバイス側の制御プログラムを作成するためのSDKで、音声認識とAlexaへの送信を実装する。サードパーティが自社のデバイスにAVSでの実装を組み込むことで、Alexa対応ができる。
- Alexa Skill Kit(ASK)  
    様々な別の機能をSkillという形でパッケージングしてAlexa Serviceとつなげる。  
    具体的にはSkill(Lambda Function)を作成するためのSDKで、Alexaへ送信されて音声から変換したテキストの処理と処理結果のデバイスへの返信をLambda Functionで実装する。

## Alexa Skill Kit(ASK) で何ができるか

- どのような音声に反応するか
- どのような単語をパラメータにしてどんな機能を実行するのか
- 機能を実行した結果をどのようにAlexaに戻すのか

これらを定義したパッケージ、API群をAlexa Skill Kitと呼び、そのうち実際に実行される機能の部分をSkillと言う。

## Alexa Skill Kit(ASK) の種類

公式サイト[^1] に記載があったのが5種類

- Custom Skills
- Smart Home Skills
- Flash Briefing Skills
- Video Skills
- List Skills

### Custom Skills

開発者が自由にスキルを定義できる。
Amazonの審査を通した場合、パブリックなAlexaサービス群に配置される。[^2]

### Smart Home Skills

スマートホームを制御するスキルを構築する。 これにより、ユーザーの操作を制御しにくくなるが、音声ユーザーインターフェイスを自分で作成する必要がないため、開発が簡単になる。 スキルは、呼び出し元の名前を覚える必要がなく、「Alexa、リビングルームの照明をオンにして」などの要求を行うことができるため、エンド・ユーザーが呼び出すことも容易。

### Flash Briefing Skills

ニュースの配信サービス用のSkill。
URLエンドポイントを指定して配信することができる。
利用できるフォーマットは `JSON`, `RSS` でエンコードがUTF-8のもの。

### Video Skills

テレビ番組や映画などのビデオコンテンツを提供できる。

### List Skills

`list skill` は、 `list events` [^3] の使用を簡単にできる。 スキルは、Alexaのトップレベルの発話から、リストに起こった変更を理解して対応することができる。[^4]

`list skill` は、[ASK CLI (Alexa Skills Kit Command Line Interface)](https://developer.amazon.com/ja/docs/smapi/ask-cli-intro.html) を通じて作成できる。

## Alexa対応デバイスについて

- Amazon Echo
- Echo Dot
- 他...

どちらも Amazonがリリースしているもの。

Amazonがリリースしていないものでも、マイク、スピーカー、インターネット接続機能が搭載されているデバイスにAVSでコードが実装されれば、Alexaと繋がることが出来る。
`Raspberry Pi + AVS` で作成し Alexa と繋げるという記事もチラホラ。

## Alexa の対応言語

英語とドイツ語。そろそろ日本語も来そうだねーという記事もチラホラ。[^5]

# まとめ

`Amazon echo` にまつわるキーワード `Alexa`, `Alexa Voice Service`, `Alexa Skill Kit` あたりの関係性を少し理解できたなーと。

siri や google asistant でも VUI(Voice User Interface) として色々発展していると思うが、 `Alexa` については 開発者がこのInterfaceを通してSkill(アプリケーション) の開発ができ、且つパブリックに公開ができるのが魅力的だと感じた。
次回は `Custom Skills` について掘り下げて調べてみるかな。

# 最後に

本日の Friday I/O でした。
[株式会社ワムウ](http://wamw.jp/)では、毎週金曜日は 興味がある事柄に取り組み、その成果を何らかの形でアウトプットする日としています。ありがとうございました。

---

[^1]: https://developer.amazon.com/ja/docs/ask-overviews/understanding-the-different-types-of-skills.html
[^2]: 2017-07-05 時点で 15,000 のSkillが登録されているらしい [原文](http://www.businessinsider.com/amazon-alexa-how-many-skills-chart-2017-7)
[^3]: https://developer.amazon.com/ja/docs/smapi/list-events-in-alexa-skills.html
[^4]: TodoList のようなリストを扱うようなものを、登録したり読み出したりすることに対応できるっぽい。
[^5]: https://amazon-press.jp/Top-Navi/Press-releases/Presselist/Press-release/amazon/jp/Devices/2017/Amazon-Alexa-1002/
【ATOMの操作】記述中のHTMLをリアルタイムプレビューする

先日導入したATOMですが、現在HTMLとJavascriptについてイチから学習中です。その途中で「これ実際の表示はどうなっちょるのかしら？」ということが気になってきました。

そこで実際に表示される部分をプレビューする機能について調べていたんですが、ATOMは標準で記述中のコードをリアルタイムにプレビューする機能が搭載されているっぽい。

![2017y10m13d_200113132.jpg](https://qiita-image-store.s3.amazonaws.com/0/205951/fedce35a-6bb7-f5a4-0c34-3877079101cd.jpeg)

　こちらがATOMに標準搭載されているMarkdownプレビュー[control] + [shift] + [M]という機能です。これでHTMLもプレビューできるみたいなんですが、実際の表示とは若干異なるということなので、HTML専用のプレビュー機能を追加するパッケージを導入してみました。

参考ページこちら
[Atom で HTML をリアルタイムプレビューしながら編集できるパッケージ atom-html-preview](https://loumo.jp/wp/archive/20160317120010/)

![2017y10m13d_193208861.jpg](https://qiita-image-store.s3.amazonaws.com/0/205951/fab20fdd-7233-7fbb-a525-c6b53df4a68a.jpeg)

　パッケージ検索欄に「html　preview」と検索すると出てきます。
インストール後、HTMLプレビュー画面を表示するには[control] + [shift] + [H]。

![2017y10m13d_195400472.jpg](https://qiita-image-store.s3.amazonaws.com/0/205951/793226c0-c565-00e6-c15e-adba0a5c5aef.jpeg)

　Markdownプレビューの場合はATOMで設定した背景色を反映したプレビュー画面でしたが、HTMLだとデフォルトで白になるっぽい。まあCSSを利用するならデフォルト背景色は関係ないかもしれませんが、この画像の場合は改行が気になりますね。

　標準のMarkdownプレビューではデフォルトで半角スペース2回で改行扱いになるようなんですが、僕の場合はそれでは使いづらそうだなと思って通常改行機能をONに設定しました。Qiita記事と同じようにMarkdown記法で書き進めていくならこの設定で良いかなと思うんですが、HTML記述をプレビューしようと思うとその改行も反映されてしまうっぽいということが分かりました。

　今後はHTMLを記述する際はHTMLプレビューを使っていきたいと思いますが、これ以外にも再現性に影響が出るならHTML専用プレビューのほうがよさげですね。今後はこれを使ってHTMLやJavascriptについて学習を始めていこうかと思います。
Git管理したレポジトリの昔のReadme.mdを2回コマンドを叩くだけで見る方法

Readme.mdは色々書き直すことが多いですが、ふと昔のreadme.mdを確認したいときが誰しもあると思います。そんなとき役に立つのが以下のコマンドです。

下の `--until="YYYY-MM-DD 00:00"` の部分を確認したい日の日付にすると、Gitのハッシュが得られます。

`git log --until="YYYY-MM-DD 00:00" --oneline --pretty=format:'%h [%cd] %d %s <%an>' --date=format:'%Y/%m/%d %H:%M:%S' -n 1 | cut -d' ' -f1`

ここで得られたGitのハッシュで下記のxxxxxxxxを置き換えると、レポジトリ直下のreadme.mdを読むことができます。

`git cat-file -p % xxxxxxxxx:readme.md`

本当に便利ですね :smile:
Laravel(v.5.5) - Admin Page & Eloquent: Getting Started & Database: Seeding

# 今回やったこと
* Adminページ作成
* モデル作成
* Seedデータ挿入

# Adminページ作成

## 参考資料
[laravel-adminで管理画面を速攻で構築する。](https://qiita.com/pikonori/items/a04066010e7380b3ee38)

## パッケージ選定
最近更新されている、新しいものにしようということでLaravel-adminを選定。
[Github](https://github.com/z-song/laravel-admin)
[Document](http://laravel-admin.org/docs/#/)

## インストール
composer.jsonに記述を追加。
バージョンは1.5.*。
で、下記を実行。

```
php composer require
php artisan vendor:publish --provider="Encore\Admin\AdminServiceProvider"
php artisan admin:install
```
app/Adminが増えてたり色々増える。

```
php artisan serve
```
でローカルサーバー立てて、localhost:8000/adminにアクセスするとログインページ表示されるはず。

## CRUD処理設定
公式DocのQuick Start見ながら進める。

## 謎にadmin消えてユーザー0になって困った時

```
php artisan db:seed --class=Encore\\Admin\\Auth\\Database\\AdminTablesSeeder
```

# モデル作成

## 参考資料
[Eloquent: Getting Started](https://laravel.com/docs/5.5/eloquent)

## モデルファイル作成

```
php artisan make:model User
```
みたいな感じでモデルファイルを作成。
このコマンドだとapp/User.phpが出来る。
このファイルにカラムの設定とかは要らないっぽい。
モデルの扱い方はまた今度。

# Seedデータ挿入
幾つか書き方あるっぽいが、たくさん作るのに便利そうなFactoryファイルを用いることにする。

## 参考資料
[Database: Seeding](https://laravel.com/docs/5.5/seeding)
[Database Testing - Write Factory](https://laravel.com/docs/5.5/database-testing#writing-factories)

## Factoryファイル作成
例によってartisanコマンドでファイル生成。

```
php artisan make:factory PostFactory　--model=Post
```
これだとdatabase/factories内にPostFactory.phpが生成。
最初からあるModelFactory.phpはこんな感じだよっていうサンプル。
で、Doc通りにFactory雛形（？）を作成。
Fakerでダミーのデータを入れれるので使う時は下を参考に欲しいものを使う。
[Faker](https://github.com/fzaninotto/Faker)

## Seedファイルを生成

```
php artisan make:seeder UsersTableSeeder
```
でSeedファイルを生成。

```php
<?php

use Illuminate\Database\Seeder;

class CategoriesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(App\Category::class, 50)->create();
    }
}
```
こんな感じに書いた。これだと50個のダミーデータ。

## Seeding

```
php artisan db:seed
```
でシートデータ挿入。
ミスった時はデバッグしてから

```
php artisan migrate:refresh --seed
```
で元通り。
ansibleでnginxをinstallしてみる

# 概要
ansibleを使ってnginxをinstallしてみました。

# 環境
ansible 2.4.0.0
CentOS release 6.9 

# ansibleの設定
ansible.cfgの一部の設定を変更しました。

```/etc/ansible/ansible.cfg
inventory = /etc/ansible/hosts
remote_user = user_name
```

/etc/ansible/hosts
install先のserverを定義します。

```
[webserver]
web1
```

## おすすめdirectoryを作る

```
ansible-galaxy init nginx
```


### directoryの構造
```
.
├── nginx.yml
└── roles
    ├── common
    └── nginx
        ├── README.md
        ├── defaults
        │   └── main.yml
        ├── files
        ├── handlers
        │   └── main.yml
        ├── meta
        │   └── main.yml
        ├── tasks
        │   └── main.yml
        ├── templates
        ├── tests
        │   ├── inventory
        │   └── test.yml
        └── vars
            └── main.yml
```

## mainとなるnginx.yml

```nginx.yml
- name: nginx
  become: yes
  hosts: web1
  roles:
    - { role: nginx }
```

## nginxを操作するtask
--extra-vars "op=xxxx"として引数で実行するtaskを変更する。
もっとよい方法はあるのだろうか。

```roles/nginx/tasks/main.yml
---
# tasks file for nginx
- name: Install nginx
  yum: name=nginx
  when: op == "install"

- name: Start nginx
  service: name=nginx enabled=yes state=started
  when: op == "start"

- name: Stop nginx
  service: name=nginx state=stopped
  when: op == "stop"

- name: Restart nginx
  service: name=nginx state=restarted
  when: op == "restart"

- name: Reload nginx
  service: name=nginx state=reloaded
  when: op == "reload"
```

## ansible-playbookの実行

```
ansible-playbook nginx.yml --extra-vars "op=start"
```



server側のsudoはpassword不要にしておきました。
MacOSで今通信してるローカルアドレス(IPv4)を取得するコマンド

皆さんMacで自分のローカルアドレスを取得するときはどうしてますか?
多分 `ifconfig`を使ってるんじゃないでしょうか? 
でも ifconfigって不要な情報がおおいですよね。
俺は `192.168.0.X` ってだけの情報が欲しいんだって思うことが誰しもあると思います。
そんな状況を解決するコマンドを探していたところ、 
近くに座っていたスーパープログラマーに聞いたら、5分ほどしてこのコマンドを教えて貰いました。

これです。

`netstat -rn | grep /32 | grep -F -v '.1/32' | grep -v -E '^f|255' | cut -d/ -f1`

このコマンドで `192.168.0.X` て形のローカルアドレスを得られます。
本当に便利ですね:smile:
VagrantでホストOSからゲストOSへ直接コマンドを実行する方法

Vagrant便利ですよね。
`vagrant ssh` してコマンドラインを叩くことはよくあると思います。
でもそうすると、いつも使っているホストOS側のシェルでゴニョゴニョできなくて不便だったりすることがあります。
そんなときに役に立つのが以下のコマンドです。

`vagrant ssh -c "<COMMAND>"`

上の `<COMMAND>`のところにゲストOSで実行させたいコマンドを渡してあげれば、ホストOSから直接ゲストOSのコマンドを叩くことが出来ます:smile:

本当に便利ですね!
WebSocketの接続

# 概要
RFCの[The WebSocket Protocol section1-1](https://tools.ietf.org/html/rfc6455#section-1)には以下のように書かれています。
＊RFCとは、[IETF](https://ja.wikipedia.org/wiki/Internet_Engineering_Task_Force)が管理している、通信の相互接続性を維持するために共通化された仕様書集です。

> WebSocketプロトコルは、既存のHTTPをトランスポートとして使用する双方向通信技術です。

つまり、サーバー/クライアント間で、オーバーヘッドの小さい双方向通信を実現するプロトコルです。
HTTPと違ってステートフルな通信であるため、送信先の情報は持ちません。HTTP通信でいう、bodyのみ送信しているようなイメージです。

# 接続


## リクエスト

最初にクライアントから以下のようなリクエストが送信されます。
＊RFCの[The WebSocket Protocol section1-2](https://tools.ietf.org/html/rfc6455#section-1.2)より引用

```txt:リクエスト
 GET /chat HTTP/1.1
 Host: server.example.com
 Upgrade: websocket
 Connection: Upgrade
 Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
 Origin: http://example.com
 Sec-WebSocket-Protocol: chat, superchat
 Sec-WebSocket-Version: 13
```

### ヘッダーの意味

特徴的なヘッダーの意味を説明します。
Upgrade:
指定のプロトコルにアップグレードすることを意味する。
ここでは、HTTPからWebSocketにスイッチすることを意味している。

Sec-WebSocket-Key:
ランダムな文字列からBASE64エンコードした文字列。
サーバーとの通信確立を検証するためのkey

Sec-WebSocket-Protocol:
サブプロトコルを指定する。
WebSocketはソケット通信機能だけを提供するため、どのような形式を使うかはアプリケーションで決める必要がある。

Sec-WebSocket-Version:
WebSocketのバージョンを指定する。
2017/10/13現在はVer13で固定

## レスポンス

以下のようなレスポンスが返ってきます。
＊RFCの[The WebSocket Protocol section1-2](https://tools.ietf.org/html/rfc6455#section-1.2)より引用

```
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
```

### ヘッダーの意味

Sec-WebSocket-Accept:
リクエストヘッダに記載されていたSec-WebSocket-Keyを、決まったルールで変換した文字列。
これによってクライアント/サーバ間の通信確立を検証出来る。

Sec-WebSocket-Protocol:
クライアントがSec-WebSocket-Protocolヘッダにて指定していたサププロトコルの中の一つを選択して返す。

## 双方向通信の開始

クライアントがSec-WebSocket-Protocolヘッダにて指定したサブプロトコルがサーバーから返ってきたら、双方向通信を開始します。
bash > printf > "00001"という書式での標準出力

参考: [【bash】 echoとprintfの違い](http://blog.goo.ne.jp/01_mai/e/fd8968994cd997594c368001fcf103e4) by 01_maiさん

https://ideone.com/a1XTQh

```bash
#!/bin/bash

for idx in $(seq 1 3);do
	printf "%05d\n" $idx
done
```

```txt:run
Success	#stdin #stdout 0s 19632KB
00001
00002
00003
```
C++17 の構造化束縛を range-based for で使う

[ブログ記事](http://secret-garden.hatenablog.com/entry/2017/10/12/214044)からの転載です。

C++17 では構造化束縛という言語機能が追加されました。  
これは `std::tie` のように `std::tuple` などを個別に変数で受け取る事が出来る機能です。

```cpp
auto homu = std::make_tuple(1, "homu", 14);

// std::tuple の要素を個別に受け取る
auto [id, name, age] = homu;
```

`std::tie` とは違い変数定義で使用する事が出来ます。


## range-based for で使う

これだけでも便利なのですが、range-based for と組み合わせることで更に便利になります。

```cpp
#include <tuple>
#include <vector>
#include <string>
#include <iostream>

int
main(){
	std::vector<std::tuple<int, std::string, int>> vc = {
		{ 1, "homu", 14 },
		{ 2, "mami", 15 },
		{ 3, "mado", 14 }
	};
	for(auto&& [id, name, age] : vc){
		std::cout << "id:" << id << ", name:" << name << ", age:" << age << std::endl;
	}

	return 0;
}
/*
output:
id:1, name:homu, age:14
id:2, name:mami, age:15
id:3, name:mado, age:14
*/
```

https://wandbox.org/permlink/HwbLhRyBDCdQDsT8


こんな感じに range-based for の変数定義でも構造化束縛を使うことが出来ます。  
ますます `std::tuple` が便利になりますね。
ファイルのタイムスタンプを読み取ってYYYYMMDDフォルダ配下に退避するバッチファイル

#概要
対象ファイルのタイムスタンプを読み取って、対象フォルダ配下にYYYYMMDDの形式でフォルダを作成し、
その中に対象ファイルを退避します。

#修正するところ
+ TARGETFILE　=>　退避元のファイル名or拡張子に*をつけて記述
+ TARGETDIR　 =>　退避元のフォルダをフルパスで記述
+ TARGETDIR2　=>　退避先のフォルダをフルパスで記述

#処理内容
```:バッチファイル
@echo off
SET TARGETDIR = "C:\work"
SET TARGETDIR2 = "C:\workk"
SET TARGETFILE = "*.log"

SETLOCAL ENABLEDELAYEDEXPANSION
for %%i in ( %TARGETDIR%\%TARGETFILE% ) do (
　　SET fdate=%%~ti
　　SET fdate=!fdate:~0,10!
　　SET ffdate=!fdate:/=!
　　IF NOT EXIST %TARGETDIR2%\!ffdate! (
　　　　MKDIR %TARGETDIR2%\!ffdate! > nul
　　　　MOVE "%%i" %TARGETDIR2%\!ffdate! > nul
　　) ELSE (
　　　　MOVE "%%i" %TARGETDIR2%\!ffdate! > nul
　　)
)
ECHO 最終ファイルまで処理が完了しました
PAUSE
```
[iOS]NavigationControllerをmainスレッドでコールしクラッシュする場合の対処法

## 概要

navigationControllerをpresentViewControllerするとクラッシュする不具合でハマッたため自身用にメモ。

## 対処法

```fix_crash_code.m
            dispatch_async(
                           dispatch_get_main_queue(),
                           ^{
                               [self presentViewController:navigationController animated:YES completion:NULL];
                           }
                           );
```

## 抜粋
Which appears to be crashing at
because presentViewController is being called outside of the main thread.

## 参考文献
https://github.com/WhisperSystems/Signal-iOS/issues/1002
Airflow - タスク登録時に、start_date に過去の日付を指定した場合でも、過去日付分の job が実行されないようにする

例えばこんなタスクを書いたとして、

```python
from airflow import DAG
from datetime import datetime
from airflow.operators import BashOperator

dag = DAG('schedule_test', start_date=datetime(2017, 9, 10, 12, 0, 0), schedule_interval='*/5 * * * *')

task = BashOperator(task_id='date', bash_command='echo "time: $(/bin/date)" >> /tmp/output.log ', dag=dag)
```

これを、`start_date` に指定した時刻より**後**に Airflow に登録すると、`start_date` から現在時刻までの、過去の日付に実行されるはずだった job がすべて登録され、その場で実行されてしまいます。
たとえば、2017/9/11 12:00:00に登録した場合、2017/9/10 12:00:00からの24時間の間に実行されるはずだった288個(24*60/5で288)の job がその場で実行されてしまいます。

これを避けるためには、DAG のプロパティで`catchup=False`を指定します。こうすると、登録時点以前に実行されるはずだった job のキャッチアップを行わないようになり、登録した時点以降から job がスケジューリングされるようになります。

```python
from airflow import DAG
from datetime import datetime
from airflow.operators import BashOperator

dag = DAG('schedule_test', start_date=datetime(2017, 9, 10, 12, 0, 0), schedule_interval='*/5 * * * *', catchup=False)

task = BashOperator(task_id='date', bash_command='echo "time: $(/bin/date)" >> /tmp/output.log ', dag=dag)
```

あるいは、`airflow.cfg`で`catchup_by_default=False`と設定すると、いちいちタスクの DAG で指定しなくても、デフォルトで`catchup`がFalseに設定されます。
この場合、逆に過去の job を実行したい場合は、DAG のプロパティで明示的に`catchup=True`とすればOKです。