OmniAICreator/Qiita-1.07M huggingface dataset:
Djangoで日本語名ファイルがあるZIPファイルの解凍

Django:1.10

Djangoで日本語名のファイルが含まれているZIPファイルを解凍した時に、なぜか日本語名ファイルだけが解凍できていない問題が発生しました。
一緒に含まれている英名ファイルはしっかり解凍できているのに。

Pythonのライブラリの問題かと思い、Linux(ubuntu)のunzipやunarを使ってみたけど、それでも上手くいかない。

ここで、Djangoからではなく、Python単体で実行した場合は解凍に成功していることに気づきました。

・WindowsのDjango(Django内製サーバ)では成功する
・LinuxのPython単体実行では成功する
・LinuxのDjangoでは失敗する ⇒ Apache+mod_wsgiで動作している

というわけで、Apache+mod_wsgiで調べてみると以下記事を発見。

http://blog.dscpl.com.au/2014/09/setting-lang-and-lcall-when-using.html

```
WSGIDaemonProcess my-django-site lang='en_US.UTF-8' locale='en_US.UTF-8'
```

日本語なので、apacheの設定に記載したWSGIDaemonProcessに以下パラメータを追加。

```
WSGIDaemonProcess my-django-site lang='ja_JP.UTF-8' locale='ja_JP.UTF-8' ...他のパラメータ
```

必要に応じて、language-pack-jaのインストール。

```
$ sudo apt-get install language-pack-ja
```

これで、日本語名ファイルも正常に解凍できるようになりました。

ちなみに、日本語のログ出力もできるようになるみたいです。
NOOBSでRaspbianをインストールするとディスクイメージでのバックアップができない

理解している人にとっては当たり前のことのような感じがするが、NOOBSでSDカードにRaspbianをインストールすると、Win32 Disk Imagerを使ってread/writeしても元通りにならない。
Raspbianをディスクイメージからインストールすると期待通りread/writeできる。
NOOBS使用時のパーティションの切り方が関係しているような気がするのだけれど、理由がちゃんと分かったらここに追記する。

2017/08/17 追記
以下のサイトをちゃんと読めば分かる気がする。
そして恐らくバックアップできないのではなくて、やり方が正しくない。
https://www.raspberrypi.org/forums/viewtopic.php?f=91&t=97003
https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=75994
Laravelで複数のテストで共通で使うデータを一つのファイルにまとめて管理する方法

例えば複数のテスト以下のようなテスト用リクエストデータを使っていたとする。

```php
	return [
            'name' => 'Yori',
            'email' => 'zeanagg@gmail.com',
            'sex' => 'male',
            'introduction' => '宜しくです！',
            'year' => '1922',
            'month' => '12',
            'day' => '10',
        ];

```

複数のテストメソッドでこのような記述をしているとコード量も多くなるし見づらくなる。

こういったデータを一つの共通ファイルに関数でまとめて、各テストからはその関数を呼び出すだけで使えるようにする方法。

###(1)testsフォルダ内に関数をまとめる用のファイルを作成
今回は、

```
tests/utilities/functions.php
```
というファイルを作成

###(2)functions.php内にテスト用データを返すだけの関数を定義

```php
<?php

function makeUserRequest()
{
	return [
            'name' => 'Yori',
            'email' => 'zeanagg@gmail.com',
            'sex' => 'male',
            'introduction' => '宜しくです！',
            'year' => '1922',
            'month' => '12',
            'day' => '10',
        ];
}

?>
```

###(3)オートドーロに登録
composer.jsonに以下のように記述

```json
"autoload-dev": {
    "psr-4": {
        "Tests\\": "tests/"
    },
    "files": ["tests/utilities/functions.php"]
}
```
こちらのコマンドを実行

```
composer dump-autoload
```

これでページが読み込まれる際にオートロードしてくれる。

###(4)テストメソッドから関数を呼び出す

```php
//リクエストデータ準備
$request = makeUserRequest();
```

これで```$request```にリクエストデータが代入された。

以上。
[fish]コマンドラインのコマンドをクリップボードにコピーする

ターミナルを使っていてコマンドをコピペしたいという場面は非常に多いと思います。
特にfishは補完が優秀で、historyからコピーするよりもコマンドラインからコピーする
ということが非常に多いです。

そこでショートカットキーですぐにコピーできるように fish function を書いてみました

```sh:commnadline_copy.fish
function commandline_copy
  if type -q pbcopy
    echo (commandline) | pbcopy
  end
end
```

あとは上記functionをキーバインドに指定するだけです

```
# Key bindings
function fish_user_key_bindings
  bind \cxc commandline_copy
end
```

fishermanでインスールできるように[github](https://github.com/tamanugi/fish_commandline_copy)にもあげていますので
よければ使ってみてください

```
$ fisher tamanugi/fish_commandline_copy
```
プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則読んでみた

# 概要
先輩から勧められた![プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則](https://www.amazon.co.jp/%E3%83%97%E3%83%AA%E3%83%B3%E3%82%B7%E3%83%97%E3%83%AB-%E3%82%AA%E3%83%96-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B03%E5%B9%B4%E7%9B%AE%E3%81%BE%E3%81%A7%E3%81%AB%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%91%E3%81%9F%E3%81%84%E4%B8%80%E7%94%9F%E5%BD%B9%E7%AB%8B%E3%81%A4101%E3%81%AE%E5%8E%9F%E7%90%86%E5%8E%9F%E5%89%87-%E4%B8%8A%E7%94%B0-%E5%8B%B2/dp/4798046140)を読んでみた。せっかくなのでシステムエンジニア歴2年弱の私がほほぉと思ったところを自分なりに抜粋。  

# ほほぉな部分（抜粋）
基本的には「KISS」「DRY」「OCP」的な考えを意識し複雑にせずシンプルにシンプルに！という風に読めたが、以下個人的にほほぉな部分を記載
## 7つの設計原理（Seven design Principles）
コードに対する革新的な7つの価値観。コードレビューなどではコレをもとにぶれないレビューを行う！
### 安全原理（Safty Principle）
状況として起こり得なくともDefaultやelseの処理を記載する！自動消火機能のように大事故を防ぐ！！
## UNIX思想
UNIXにおける17の思想のうち以下抜粋
### 表現性の原則（Rule of Representation）
情報はロジックではなくデータに寄せることでより簡単に表現しよう！
### 経済性の原則（Rulr of Economy）
積極的にプログラマに投資しよう！プログラマの時間を浪費させ無いことで生産性が高まる！！
### 生成の原則（Rule of Generation）
コードを生成するコードを作ろう！そのほうがとっても高品質！！
### 最適化の原則（Rulr of Optimization）
速いコードより正しいコード！正しいコードを作成してから速さを考える。
## UNIX哲学（UNIX Philosophy）
### 速攻プロトタイプ（Build a Prototype as soon as possible）
出来る限り早くプロトタイプを作成しよう！試行錯誤無くして最適解は導かれない！！
### 効率性より移植性（Choose portability over efficiency）
時間がかかったとしてもハードウェアに依存しない移植性の高いコードを書こう！！
### レバレッジソフトウェア（Use software levarage to your advantage）
ソフトウェアのテコを用いて大きな力を生む！とくに手作業の自動化には有効！！
### シェルスクリプト活用（Use shell scripts to increase levarage and portability）
シェルスクリプトをグルー言語（ノリ的なくっつける言語）として利用しレバレッジ（テコ）の力を増長！！
個人的にシェルスクリプトをどこまで活用するか悩んでいたが、グルー言語として意識しすれば積極的に使っていけそう！！
### 対話インターフェース回避（Avoid captive user interface）
ユーザーインターフェースを過度に入れることをやめる！人間がボトルネックになったり、「大は美なり」的なアプローチを生み出しやすい
## 手法
### ラバーダッキング（Rubber ducking）
説明するというデバッグ！話してるうちに自己解決した的なことよくあるけどラバーダッキングっていうんだ！というほほぉ
## 法則
### ジョシュアツリーの法則（Joshua Tree Principle）
名前を知った途端それが見えるようになること！！これまで見えてなかったけどデザインパターンで名前を勉強して改めて見ると、あ〜それかということある！
# まとめ
そう言われればそうだなぁということがたくさん書いてあった。どこかのタイミングで振り返ってまた読んでみたい。
Docker使ってナンバーズの当選データをスクレイピングしてくる

- ナンバーズの過去データからあたり番号を予測できないか色々試すのに過去データが欲しい
- 自PCの開発環境は汚したくない

## Docker 使う
- Docker for Windows か Docker for Macをインストールする

## スクレイピングするコードはここを参考に作った
- [ナンバーズ4の当選確率を2倍以上にする方法](http://qiita.com/hitoribucho/items/2fcfde45e1863bb3bad4)
- [今回作ったコード GitHub](https://github.com/DotaKobayashi/scraping-numbers)

## Dockerfile書くのも面倒なのでDocker HubにあるPythonのイメージを使う
```
docker pull python
```

## コンテナ起動して中に入ってパイソンのコードを実行する
```
# -v でマウントする場所はpythonコードを格納したフォルダをマウントする
docker run -it -v [localのフォルダ]:/tmp python:latest /bin/bash

# get_numbers.pyで必要なライブラリをインストール
pip install beautifulsoup4
pip install html5lib

# get_numbers.pyを実行
python get_numbers3.py
python get_numbers4.py
```

上手く動くとマウントしたフォルダにnumbers3_data.csvとnumbers4_data.csvができる
express4でファイルアップロード、画像リサイズ、MySQLへ保存まで

[express4 でファイルアップロード](http://qiita.com/bohebohechan/items/d10ee5da0cd6a68b1d04)
の続編です。

ファイルを受け取れたので、そのファイルをリサイズしてMySQLまで保存したいと思います。

## Version

- node v8.2.1
- express 4.15.0


## 今回使うnode.jsのライブラリ

- [Knex\.js \- A SQL Query Builder for Javascript](http://knexjs.org/)
MySQLとお話しする部分に使います。

- [aheckmann/gm: GraphicsMagick for node](https://github.com/aheckmann/gm)
画像のリサイズなどに使います。

事前に、graphicsmagickをインストールする必要があります。

```bash

apt-get install graphicsmagick

```


## アップロード画像をリサイズしてそのまま保存

リサイズとか、品質の変更とか、プロファイルデータを削除して別名で保存

```js

const multer = require('multer');
const upload = multer({
  dest: 'uploads/tmp'
})

router.post('/user_photo', upload.any(), (req, res, next) => {

  gm(req.files[0].path)
    .resize(300)
    .quality(70)
    .noProfile()
    .write('uploads/reformat.png', function (err) {
      if (err) {
        logger.debug(err);
      } else {
        logger.debug('done');
      }
    });
  res.status(200).end('ok');
});
```


## アップロード画像をMySQLに保存

- toBufferを使うのがコツ
- イメージファイルが大きいと、blobでは入らないので、mediumblobかlongblobにすること

```js

const multer = require('multer');
const upload = multer({
  dest: 'uploads/tmp'
})
const gm = require('gm');
const fs = require('fs');


router.post('/user_photo', upload.any(), (req, res, next) => {

  gm(req.files[0].path)
    .resize(300)
    .toBuffer( (err, buffer) => {
      if(err){
        logger.debug(err);
      }
      knex('image').insert({
        image: buffer,
        fileType: "png"
      }).then(function(){
        logger.debug('ok');
      }).catch(function(err){
        logger.debug(err);
      });
    });
  res.status(200).end('ok');
});

```

```sql
create table image (image longblob, filetype char(10));
```
文字のバイナリデータを見る方法

# Visual Studio のバイナリエディタを利用する方法
1. メイン メニューの [ファイル | 新規作成 | ファイル] を選択
2. 編集するファイルを選択し、[開く] の横のドロップダウン矢印をクリックし、[ファイルを開くアプリケーションの選択 | バイナリ エディター] をクリックする

# Bash on Windows のコマンドを利用する方法
```bash
echo "abcdefghijklmnopabcdefghijklmnopqrstu" | xxd -g 1
```

# ひとこと
Windows 10 の bash のおかげで開発効率が上がっている気がする。

# 参考サイト
[Visual Studio で Binary Editor](https://msdn.microsoft.com/ja-jp/library/cb4x6esf.aspx)
[技術/UNIX/od, hexdump, xxd : 16進数 or 2進数ダンプ](https://www.glamenv-septzen.net/view/1224)
(翻訳,要約) 全てのWidgetの境界を可視化する方法

著者: Roberto Ulloa
著者のBlog: [that doesn't make any sense…](http://robertour.com/)
原文: [Easy way of debugging Kivy interfaces](http://robertour.com/2013/10/02/easy-way-debugging-kivy-interfaces/)

# 訳

*layoutしようとしているwidgetが何処かへ行ってしまってびっくりしたことはありませんか？*

　効率の為、Kivyのwidget達は可能な限り簡素になっています。境界線や背景色を持たないwidgetがあるのもその為です。ただそのせいでlayoutがうまくいかなかった時の対処を難しくしているのも事実です。

　そういった時に[Inspector](http://qiita.com/gotta_dive_into_python/items/caa3e0f41ddfaedcdb95)を使うのはありですが、それではlayout全体の把握は簡単ではありません。なので私がいい方法を紹介します。以下のcodeを見て下さい。

```python:main.py
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout

class Widgets(FloatLayout):
    pass

class WidgetsApp(App):
    def build(self):
        return Widgets()

WidgetsApp().run()
```

```yaml:widgets.kv
<Widgets>:
    AnchorLayout:
        anchor_x: 'right'
        anchor_y: 'bottom'
        GridLayout:
            cols: 3
            size_hint: .6,.6
            Label:
            StackLayout:
                orientation: 'lr-tb'
                Widget:
                    size_hint: .2,.2
                Button:
                    size_hint: .3,.3
                    text: "how?"
            Widget:
            Widget:
```

実行すると

![screenshot](http://robertour.com/wp-content/uploads/2013/10/Screenshot-from-2013-10-02-181554.png)

ここで疑問が湧きます。このbuttonは一体どのようにしてこの位置に定まったのでしょうか？そんな時はwidgets.kvに以下の行を加えてください。

```yaml:widgets.kv
<Widget>:
    canvas.after:
        Color:
            rgba: 1, 1, 1, 1
        Line:
            rectangle: self.x+1,self.y+1,self.width-1,self.height-1
            dash_offset: 5
            dash_length: 3
```

すると

![screenshot2](http://robertour.com/wp-content/uploads/2013/10/Screenshot-from-2013-10-02-181323.png)

なかなかイケてると思いませんか？これは私のアイディア・オブ・ザ・イヤーです。

# 追記

### 2018/10/22

`kivy.modules`に新しく`showborder`という物が加えられたのですが、これを使えば上記に書いた作業を行わずとも簡単に境界を可視化できます。詳しくは[この記事](https://qiita.com/gotta_dive_into_python/items/caa3e0f41ddfaedcdb95#showborder)を見てください。
KubernetesのTutorial


Mac Pcを使います。Minikubeのインストール

###minikubeをinstallして、一連の動作を確認

```:bash
brew cask install minikube
```

```:bash
minikube start
```

```:bash
kubectl run hello-minikube --image=gcr.io/google_containers/echoserver:1.4 --port=8080
```

```shell-session
deployment "hello-minikube" created
```

```:bash
kubectl expose deployment hello-minikube --type=NodePort
```

```shell-session
service "hello-minikube" exposed
```


```:bash
kubectl get pod
```


```shell-session
NAME                             READY     STATUS              RESTARTS   AGE
hello-minikube-180744149-dm5rp   0/1       ContainerCreating   0          14s
```

```:bash
curl $(minikube service hello-minikube --url)
```

```shell-session
CLIENT VALUES:
client_address=172.17.0.1
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://192.168.99.100:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=*/*
host=192.168.99.100:32530
user-agent=curl/7.43.0
BODY:
-no body in request-%  
```

```:bash
minikube stop
```

```shell-session
Stopping local Kubernetes cluster...
Machine stopped.
```

###dashboardにアクセスする

```:bash
minikube dashboard
```

![スクリーンショット 2017-08-16 18.59.39.png](https://qiita-image-store.s3.amazonaws.com/0/39073/d3367e81-c6a7-f582-d03e-ad9d98d0c263.png "スクリーンショット 2017-08-16 18.59.39.png")
Python : lambdaの中でも再帰できた

参考にした記事:[Fizz Buzz問題で副作用と代入を抑えてみる【JavaScript、VB.Net、Python3、CommonLisp、Clojure、HSP、R言語】のコメント](http://qiita.com/yosgspec/items/543eed9386103ec9c58c#comment-7f730579d0e5e1267525)
[Pythonでのワンライナー:再帰
Yコンビネータなんて複雑なものを作らなくても、関数に自分自身を受け取る引数があればいいのです。](http://qiita.com/gyu-don/items/1c200d4e9fc6e22d3c7b#再帰)

lambdaの中に再帰は書けない(特別なことをしない限り)と思ってたんですけど、できるんですね。知らんかった。
いや、以前は読んでも理解できなくて脳内スルーしてたんだと思う。

記事を参考に自分でも階乗を書いてみました。

```Python3
do = pack_to_tuple = lambda *x : x
case = unpack_and_evaluate_in_order_then_return_last = lambda x : x[-1]
otherwise = True

f = ( lambda x :
        case(     x == 0   and do( 1 )
              or otherwise and do( x * f( x - 1 ) )
             )
    )

f2 = ( lambda x :
       ( lambda f : f( f,  x ) ) ( lambda f, x :
                                     case(     x == 0   and do( 1 )
                                           or otherwise and do( x * f(f,  x - 1 ) )
                                         )
                                 )
     )

print(f(10), f2(10))
```

```python:
# 結果
3628800 3628800
```
※ 最初の三行は、Haskellっぽくガードっぽい条件分岐をするためのものです。
できた!

上の関数``` f ```と下の関数``` f2 ```と同じ事をしています。
上の方は普通に再帰してます。こっちは普段やってるし理解できる。
下の方は?ちょっと難しい...
無名再帰で階乗を返す関数を作って、f2という名前をつけている、って感じでしょうか?

+ x と f を引数とし f(f,x) を返り値とする無名関数の引数 f に、
+ f と x を引数とし、x の値によって 1 または x*f(f,x-1) を返す無名関数を渡す
+ x を引数とする無名関数

何となくわかるようなわからないような...でも、上から下に機械的に変換することはできるので、必要になったときにはなんとかなりそうです。

違うよ、とか、こういうことだよ、とかあればコメントお願いします。
## 追記 これでいいのか
参考記事：[【Python】lambdaで再帰](https://qiita.com/kzm4269/items/94ba1dfa2de2cf4bc78f#_reference-79543fe33852e41d871d)

キーワード引数を使うと...

```Python:
f3 = ( lambda x, f =  lambda f, x : case(     x == 0   and do( 1 )
                                		or otherwise and do( x * f(f,  x - 1 ) )
                            		)
       : f( f,  x ) 
     )
```

すっきり。何となく意味もわかりやすいような。勉強になりました。
yumパッケージの存在確認

ansibleでサーバの設定をモクモクとやってます。
そんな中、yumパッケージがあったら(なかったら)〜を行うような事があったけど
なかなかいいやり方がなかったので調べてみたところ、以下のやり方に落ち着いたのでメモ。

```
# {{ package }}はパッケージ名
# mariadb-libs.x86_64とか

- name: check if "{{ package }}" is installed
  yum:
    list="{{ package }}"
  register: pkg

- name: install "{{ package }}" if exist
  yum:
    name: "{{ package }}"
    state: latest
  when: pkg.results|selectattr("yumstate", "match", "installed")|list|length != 0
```

## 参考
https://gist.github.com/goldyfruit/f4f274be3144e6afca69
swift4の文字列操作（Substring）メモ

文字列のString.substringがSwift4からSubstringになったので使い方についての覚書。
他にも書き方はあると思いますが。

Swift3の記事はこちら
[swift3の文字列操作（String.substring）メモ](http://qiita.com/MTattin/items/bf32562cd7d03c49026f)

```swift
///
/// 対象文字列
///
let str: String = "1234567890"
///
/// 先頭１文字 - 1
///
print("先頭１文字: \(String(str.prefix(1)))")
///
/// 先頭１文字以外 - 234567890
///
print("先頭１文字以外: \(String(str[str.index(after: str.startIndex)..<str.endIndex]))")
print("先頭１文字以外: \(String(str.suffix(str.characters.count - 1)))")
///
/// 末尾１文字 - 0
///
print("末尾１文字: \(String(str.suffix(1)))")
///
/// 末尾１文字以外 - 123456789
///
print("末尾１文字以外: \(String(str[str.startIndex..<str.index(before: str.endIndex)]))")
print("末尾１文字以外: \(String(str.prefix(str.characters.count - 1)))")
///
/// 先頭から？文字 - 12345
///
print("先頭から？文字: \(String(str.prefix(5)))")
///
/// 末尾から？文字 - 67890
///
print("末尾から？文字: \(String(str.suffix(5)))")
///
/// 先頭？文字以外 - 67890
///
print("先頭？文字以外: \(String(str[str.index(of: "6")!..<str.endIndex]))")
print("先頭？文字以外: \(String(str.suffix(str.characters.count - 5)))")
///
/// 末尾？文字以外 - 12345
///
print("末尾？文字以外: \(String(str[str.startIndex..<str.index(of: "6")!]))")
print("末尾？文字以外: \(String(str.prefix(str.characters.count - 5)))")
///
/// ？から？文字 - 34567
///
print("？から？文字: \(String(str[str.index(of: "3")!..<str.index(of: "8")!]))")
print("？から？文字: \(String(str[str.index(of: "3")!...str.index(of: "7")!]))")
```
MacOSX で No rule to make target `webkit_server_.gch/c++' のようなエラーで capybara-webkit のインストールに失敗する時の対応

# 事象

MAcOSX で Rails アプリケーションを実装しようとした時に、 capybara-webkit のインストールで失敗してしまう。その時のエラーメッセージには

```
No rule to make target `webkit_server_.gch/c++'
```

なんて書かれている。

# 結論

qt のバージョンが新しすぎます。
capybara-webkit は qt のバージョン5.5以下で動きます。

```shell-session
% brew install qt@5.5
```

もし、5.9 等をインストールしていたら、先に削除してしまいましょう。
5.9 でないと困る場面はおそらく無いと思います。特にwebアプリケーションを実装するような場合。

# 参考
**Installing Qt and compiling capybara webkit**
https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkit#macos-sierra-1012-el-capitan-1011-and-yosemite-1010
EMRにてcustom jarを使ったhadoop job stepでs3+ORC+KMSを利用する

要件のニッチさがすごい気はするけどドハマりしたので。
EMRのhadoopのバージョン(正確にはjets3tのバージョン)があがれば特に苦労せん気もするけどね。

ただ、apache的にはs3://は非推奨で、EMR的にはs3://推奨というおっぺけぺーな状態ではあるので今後どうするべきかはまた別個の話になるかねえ。

というわけで本題。

「s3上でkmsにてserver side encryptionされているorcファイルを入力としてmapreduceを動かし、同じくkmsでs3に吐き出す」

細かい部分はぐぐれば出てくるので、重要な部分だけを。

・EMRのcore-site

```
  {
    "classification":"core-site",
    "properties":{
      "fs.s3.awsAccessKeyId":"access key",
      "fs.s3.impl":"com.amazon.ws.emr.hadoop.fs.EmrFileSystem",
      "fs.s3.awsSecretAccessKey":"secret key"
    },
    "configurations":[]
  }
```

アクセスキーとシークレットキーのほかにfs.s3.implを設定する。
custom jar側のconfに設定してもいけるみたいだけど未検証。

・java側
よく見かけるアレ、

```
conf.set("fs.s3n.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem");
conf.set("fs.s3n.awsAccessKeyId", "access key");
conf.set("fs.s3n.awsSecretAccessKey", "secret key");
```

こいつを

```
//conf.set("fs.s3n.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem");
conf.set("fs.s3.awsAccessKeyId", "access key");
conf.set("fs.s3.awsSecretAccessKey", "secret key");
```

こうする。要するに、impl設定を外して、s3nになってたらs3にする。
もちろんコメントアウトでなくて削除でも問題なし。
addInputPathとかsetOutputPathに渡すPathも、

```
FileInputFormat.addInputPath(jobConf, new Path("s3://bucket/key"));
```

みたいにs3nでなくs3にする。

これでいけました。
Emrでのhadoop実行がどのように実施されているか、をちゃんと知っていればハマらなかったのかもしれない。
さくらのクラウド上で Scientific Linux 6.6でサーバー立ててみた （OSインストールからの作業が必要な例）


### さくらのクラウドでサーバーを建てようとしたがOSとしてそもそも選択肢がない
過去バージョンのOS上での動作検証などに必要になったので。
CentOSやUbuntuなどを利用する場合以外の基本的には用意されていないOSの場合の対応方法。

##### さくらのクラウド上での以下操作

* 新規ディスクを作成から、ブランク（空のディスク）を選択
* ISOイメージを使うから該当のOSを選択
* 好みのISOイメージが無い場合は ストレージのISOイメージからISOイメージ追加ができる（インストール完了したら削除しておけば月額費用抑えられる）
* ISOイメージ追加する場合FTPアカウントが発行されるのでFTPでイメージをアップロードする
* 複数枚のイメージが必要な場合、１枚ごとアップが必要。（複数枚分の課金）

####SL6系バージョンごとダウンロード一覧
https://www.scientificlinux.org/downloads/sl-versions/sl6/



### コンソールタブからGUIでインストールをすすめる

超便利！ただし問題があって、一度切断後にコンソールに再接続すると画面がバグっててすすめづらくなる。。いつか解決してるとは思う。
※ VNCでもできるようなので手間掛けてもよければそれもいいかも。

![Kobito.7svLXS.png](https://qiita-image-store.s3.amazonaws.com/0/10268/9a489fa8-d008-b1d6-a51f-1e0bb64d6e76.png "Kobito.7svLXS.png")



### ネットワークの設定
初期からあるアーカイブからと違って、管理画面のコンソールから対応が必要な点。ここを設定すればターミナル等からsshできる。
※ minimum 構成でのインストールだからかもしれない


```
vi /etc/sysconfig/network-scripts/ifcfg-eth0
```

```ifcfg-eth0
# 変更
ONBOOT=yes
# 実際のMACアドレスに変更NICから詳細確認
HWADDR=xx:xx:xx:xx:xx:xx

# 追記
NETMASK=255.255.255.0
IPADDR=[サーバーのIP NICにあるIP]
DNS1=[NICに推奨ネームサーバー記載あり]

```

サポート対象外のアーカイブからサーバーを作成した場合、PCI deviceが追記されているので修正が必要。
ATTR{address} はNICから詳細を開き実際のMACアドレスを記載する。
※ 多分必要ない


```
vi /etc/udev/rules.d/70-persistent-net.rules
```

```70-persistent-net.rules
# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.

# 削除
# PCI device 0x1af4:0x1000 (virtio-pci)
#SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="xx:xx:xx:xx:xx:xx", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

# 削除
# PCI device 0x1af4:0x1000 (virtio-pci)
#SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="xx:xx:xx:xx:xx:xx", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

#追記
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="xx:xx:xx:xx:xx:xx", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
```

 

```
/etc/init.d/network restart 
```


※ すでにIPが使用中のメッセージが出た場合、
 /etc/sysconfig/network-scripts/ifcfg-eth0 に下記行を追記する
```ARPCHECK=no
```

あとは構築後にISOイメージを保存しておくよりかは、
色々インストールする前に初期状態でディスクをアーカイブしておくと再構築するよりショートカットできていいかも。
初心者がSpring tutorialをやってみる　第１回　事前準備

ほぼプログラムミングをやったことない初心者が、Springを利用してWEBサイトを作成してみる。忘れないためのメモ。

やってみるチュートリアルサイトはここ
[Spring Tutorial for Beginners](http://o7planning.org/en/10127/spring-tutorial-for-beginners#a7981)


今回はあまりにも知識がないため、下記のページを読んだ。
そして、重要そうな用語を自分なりの解釈で記載。
[Quick Learning Java for beginners](http://o7planning.org/en/10161/quick-learning-java-for-beginners)

Class・・・あるもの型。ドメインみたいなものか？フィールド、関数をもつ。型（Class）から具体的なもの（インスタンス）を生成する。
Constructor・・・インスタンスを生成する際に、実行される関数。インスタンス固有の特性を設定するのに利用される。
Instance・・・型（クラス）から生み出される具体的なもの。フィールド、関数をもつ。
Normal field・・・（クラス内で宣言された場合）クラスから生成されるインスタンス独自のフィールドである。
static Field・・・（クラス内で宣言された場合）クラス内で共通に保持するフィールドである。
final Field・・・Normal fieldのうち、一番初めの宣言以降、値を変更することができないフィールドである。
static final Field・・・static Fieldのうち、一番初めの宣言以降、値を変更することができないフィールドである。
Method・・・与えられた条件（パラメータ）に沿って、データの加工を行う処理である。加工結果を返す場合と返さない場合がある。
static Method・・・Methodのうちクラスに保持するものである。インスタンス経由でなく、クラス経由で呼び出した方がよい。
final Method・・・Methodのうちインスタンスに保持するものである。
parent class・・・parent classはsub classによって継承元となるクラスである。
sub class・・・継承対象となるクラス（parent class)をもとに、作成したクラスである。親クラスから、フィールドと値、関数を継承する。
Override method・・・親クラスから継承した、Methodの内容を破棄して、新しくデータの加工処理内容を定義すること。

以上

チュートリアルをサラッと見てみて、重要そうな単語、わからなかった単語を書き出した。
Maven 
IoC Container
DAO, ORM, AOP, WEB
implement
Group Id
Artifact Id
package
pom.xml
Spring BEAN
packages
ApplicationContext
VagrantBox を作るときの注意

公式の[Creating a Base Box](https://www.vagrantup.com/docs/boxes/base.html)を読んだ時の自分用メモなので、割と雑

## ベースボックスの構成
Base box は最小限の構成にするべきで例えば
Linux のbox なら以下のものだけを含める

- Package manager
- SSH
- SSH user so Vagrant can connect
- Perhaps Chef, Puppet, etc. but not strictly required.
- プロバイダーによっては追加のソフトウェア例えばVirtualBoxならVirtual guest additions

## ディスクスペース
可変で大きめのサイズ

## メモリーサイズ
多くのプロバイダーではVagrantfileで変更できるのでデフォルトサイズは512MBとか小さい方が良い

## オーディオやUSB コントローラ
不必要なハードウェアはオフにしておくべき。
多くの場合Vagrantfileで簡単に追加できる

# デフォルトユーザーセッティング
パブリッシュするならばユーザー"vagrant"の作成、Root パスワード"vagrant"、password-less sudo、SSH-Tweaksの設定が必要。
だけど、個人的に使う分にはセキュリティリスクを上げるだけなので、これらの設定はむしろしないことが推奨。

# Windows Box
vagrant がゲストOSとして公式にサポートしているWindowsOSは 
> - Windows 7 
> - Windows 8 
> - Windows Server 2008
> - Windows Server 2008 R2
> - Windows Server 2012
> - Windows Server 2012 R2

## 設定
> - Turn off UAC
> - Disable complex passwords
> - Disable "Shutdown Tracker"
> - Disable "Server Manager" starting at login (for non-Core)
UACはコントロールパネルで無効にした後レジストリでもOFFにしないといけない
Windowsのバージョンが変わるとやり方も変わる可能性がある。
Windows8/8.1なら

```
reg add HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /d 0 /t REG_DWORD /f /reg:64
```


## Base WinRM Configuration
```
winrm quickconfig -q
winrm set winrm/config/winrs @{MaxMemoryPerShellMB="512"}
winrm set winrm/config @{MaxTimeoutms="1800000"}
winrm set winrm/config/service @{AllowUnencrypted="true"}
winrm set winrm/config/service/auth @{Basic="true"}
sc config WinRM start= auto
```


# VirtualBox でBoxをつくる時の注意
VirtualBox Guest Additionsは必須
guest additions をインストールする前にlinux kernel headerとbasic developer tools が必要。
Ubuntuなら

```bash
sudo apt-get install linux-headers-$(uname -r) build-essential dkms
```

# 参考
- [Creating a Base Box](https://www.vagrantup.com/docs/boxes/base.html)
- [Creating a Base Box - VirtualBox Base Boxes](https://www.vagrantup.com/docs/virtualbox/boxes.html)
YOLO2での計算量を調べてみた

一般物体認識のYOLO2での計算量を調べてみました。
![profiling.PNG](https://qiita-image-store.s3.amazonaws.com/0/34750/f4be7826-da44-5d17-0d8c-71a4432b5060.png)

YOLO2をCPUで実行したプロファイル結果では、4.862秒のGEMM（畳み込み演算）を行っており処理の大部分を占めています。

入力される画像の解像度をVGA(640x480）としたとき畳み込み演算が23回、総計で146億回の積和算が行われました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/34750/9a75bb18-4e9b-7b48-ff64-e692a9be6866.png)

現在ノートパソコンに組み込まれているCore i5の内臓GPUの処理能力が約300GFLOPS（理論値）、SGEMMの実効値（clBLASなど）が200GFLOPS前後となるので、一秒あたり10回程度の画像認識が行える（はず）。
GPUカードの場合およそ3TFLOPSから12TFLOPSほどなので、YOLO2では毎秒100フレーム程度で認識ができます。

深層学習でのinfarence(推論）ではこのSGEMMによる畳み込み演算がボトルネックになり、GPUでの実装がカギとなっています。

MobileyeではEyeQチップに組み込まれたベクトル演算プロセッサが、MOVIDIUSではベクトル演算プロセッサSHAVEがこの畳み込み演算を行っています。
![Mobileye-EyeQ4-architecture-MIPS-interAptiv-M5150-CPU-600x500.png](https://qiita-image-store.s3.amazonaws.com/0/34750/7821ad1b-7de9-e756-c6c1-50463bcec309.png)

![Movidius SHAVE.PNG](https://qiita-image-store.s3.amazonaws.com/0/34750/31821265-7cff-fa60-ec82-e825e620e01e.png)
ActiveSupport::StringInquirer を使って、ステータスを active? みたいに管理する

# はじめに
Rails で User モデルに status というカラムがあるとき、

```
Rails.env.production?
```
 のように

```ruby
user.status.active?
```
と書きたいときがあります。その書き方の例です。

# シンプルな実装

ActiveSupport::StringInquirer もしくは、String#inquiry メソッドを使うと簡単に実装できます。
_Userモデルには string 型の status というカラムがあるものとします_

app/mode/user.rb

```ruby
class User < ApplicationRecord
  def status
    attribute(:status).inquiry
  end
end
```

```ruby
[1] pry(main)> user = User.new
=> #<User:0x3ff520751674>
[2] pry(main)> user.status = :active
=> :active
[3] pry(main)> user.status.active?
=> true
[4] pry(main)> user.status = :inactive
=> :inactive
[5] pry(main)> user.status.active?
=> false
[6] pry(main)> user.status.inactive?
=> true
```
簡単ですね。

# ちょっと凝った実装

1個のモデルの1個の属性だけにこれを適用するならば良いのですが、数が増えてくると同じようなことを何度も書く必要が出て来ます。
そんなときは、クラスマクロを実装して、シンプルに済ませませましょう。

app/mode/application_record.rb

```ruby
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  class << self
    def inquiry *attrs
      attrs.each do |attr|
        define_method attr.intern do
          attribute(attr).inquiry
        end
      end
    end
  end
end
```

app/mode/user.rb

```ruby
class User < ApplicationRecord
  inquiry :status
end
```

試してみましょう。

```ruby
[1] pry(main)> user = User.new
=> #<User:0x3fcca0cb0c58>
[2] pry(main)> user.status = :active
=> :active
[3] pry(main)> user.status.active?
=> true
[4] pry(main)> user.status = :inactive
=> :inactive
[5] pry(main)> user.status.active?
=> false
[6] pry(main)> user.status.inactive?
=> true
```

同じように動きますね。引数は複数取るようにしたので、

```ruby
class User < ApplicationRecord
  inquiry :status, :gender
end
```

のように書くと

```ruby
user.gender.female?
=> true
```

のようなメソッドも使えるようになります。

# 参考
ActiveSupport::StringInquirer
http://api.rubyonrails.org/classes/ActiveSupport/StringInquirer.html
Swift3のmacosで現在のWiFi SSIDを取得する方法

意外と調べても見つからなかったのでメモ

***Build Phases***の***Link Binary With Libraries***から***CoreWLAN.framework***を追加

その後、コードに下記を記述

```swift:ssid.swift
import CoreWLAN

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        print(CWWiFiClient.init()?.interface()?.ssid() ?? String())
    }
}
```
別クラスタ間でのレプリケーションDB作成手順(Aurora-Aurora)


別クラスタでAurora（MySQL）を作成し、レプリケーション可能なDBを作成する手順

なんかAWSの公式で手順が公開されてたけど簡易化したらずいぶんと単純だったからまとめる。

これができれば本番に影響を与えずに本番と常にSyncしたデータで色々テストできる。

参考文献
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.Overview.Replication.MySQLReplication.html


# 別クラスタ間でのレプリケーションDB作成手順
別クラスタでAurora（MySQL）を作成し、レプリケーション可能なDBを作成する手順

## 前提条件
コピー元DB（以下マスタDB）がAurora（MySQL）
作成するコピー先DB（以下スレイブDB）はAurora（MySQL）
メンテナンス時間（Aurora再起動時間）が確保できること

```
このメンテナンス時間はクラスタパラメータ（binlog_format）適用時に必要となる時間であり、
既に適用されている場合はダウンタイムゼロで本作業は実施可能である。
```

## マスタDBのバイナリログ記録の有効化

下記のクラスタパラメータを`MIXED`に変更

`binlog_format = MIXED`

**メンテナンスに入っていることを確認**
パラメータ変更後、`マスタDBを再起動`
**この時点でメンテナンス解除は可能**

## スレイブDBの作成

### スナップショット作成
-マスタDBのスナップショット作成

### スレイブDB作成
-作成されたスナップショットからスレイブDBを復元
-DBパラメータ、クラスタパラメータをdefaultからマスタDBと同じパラメータに再設定
-スレイブDBを再起動
-スレイブDBの`アラームと最近のイベント`より下記Eventが出力されていることを確認しメモしておく。

```
Binlog position from crash recovery is mysql-bin-changelog.0000xx XXX
```

-スレイブDBのreaderを作成
-スレイブDB（reader）のインスタンスパラメータを変更
-スレイブDB（reader）の再起動

## レプリケーション開始

スレイブDBにて以下を実行（マスタDBの情報登録）

```
CALL mysql.rds_set_external_master ('<end-point>', 3306, '<user>', '<password>', '<binaryfile-name>', <binaryfile-place>, 0);
CALL mysql.rds_start_replication;
```

end-point：マスタDBのクラスタエンドポイント
user：マスタDBのユーザ
binaryfile-name：前述でメモしたmysql-bin-changelog.0000xxの箇所
binaryfile-place：前述でメモしたXXXの箇所

## 俺が実際ハマったこと

全部終わった後にスレイブ側でslaveの状態を確認してたんだけど

```
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
               
~中略~

      Slave_SQL_Running_State: errorっぽいのは吐かれてなかった※なんで出てたかは忘れた。
```

なんで「あ、うまくいってんじゃん！」とか思ってたら、いつまで経ってもスレイブ側に最新のデータがレプリされない…。

んでよくよく見てたら

```
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: ********.rds.amazonaws.com
                  Master_User: admin
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-changelog.****
          Read_Master_Log_Pos: 125608761
```

こいつ→`Read_Master_Log_Pos: 125608761`
レプリ開始してから全然変わってねぇ。

SGの設定間違えてた…。
マスタ側のインバウンドにスレイブを入れるの忘れてた。

確認する時は以下を見た方が良さげ
```
Read_Master_Log_Pos: 125608761 ⇦更新されていること
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it　⇦このメッセージが出力されていること
```

まぁそこまで調べたわけじゃないけど実機でやった結果、こんな感じでした。

2017年8月23日
超簡単！SVGとCSSによるテキスト表示アニメーション

# 初めに

自分のサイトのトップの文字を表示するアニメーションをSVGとCSSで実装したので書いていきます。

[サンプル](https://theimaginationwasunbroken.com/)

アニメーションの原理は[こちら](http://2ndidea.com/svg/svg-path-drawing-animation-even-ie/)を参考にしました。

# とにかく試してみたいソースコード

#### HTML

```html
<svg>
    <text x="0" y="50%">Hello</text>
</svg>
```

#### CSS

```css
text {
    /* 色はお好みで */
    stroke: black;
    /* 文字の中身は塗りつぶさない */
    fill: none;
    /* 文字が大きい方がアニメーションが綺麗なので50pxを指定 */
    font-size: 50px;
    /* 100%だと最後まで表示されないので多めに設定する */
    stroke-dasharray: 150% 150%;
    /* 線が細いほうがアニメーションが綺麗なので0.5pxを指定 */
    stroke-width: 0.5px;
    -webkit-animation: stroke-anim 5s linear;
    animation: stroke-anim 5s linear;
}
@-webkit-keyframes stroke-anim {
  0% {
    /* 100%だと最後まで表示されないので多めに設定する */
    stroke-dashoffset: 150%;
  }
  100% {
    stroke-dashoffset: 0%;
  }
}

@keyframes stroke-anim {
  0% {
    /* 100%だと最後まで表示されないので多めに設定する */
    stroke-dashoffset: 150%;
  }
  100% {
    stroke-dashoffset: 0%;
  }
}
```

### 解説

試しみると下記のような「Hello」という文字がアニメーションで表示されます。

<img width="255" alt="スクリーンショット 2017-08-16 16.29.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/81308/761b08af-73ed-6c9d-f665-7d891d7a7c97.png">

文字の輪郭がアニメーションによって表示されるため文字の塗りつぶしをしたい場合は一工夫必要です。

# 塗りつぶし対応ソースコード

### HTML

```html
<svg>
    <text x="0" y="50%">Hello</text>
</svg>
```

### CSS

```css
text {
    /* 色はお好みで */
    stroke: black;
    /* 色はお好みで */
    fill: black;
    /* 文字が大きい方がアニメーションが綺麗なので50pxを指定 */
    font-size: 50px;
    /* 100%だと最後まで表示されないので多めに設定する */
    stroke-dasharray: 150% 150%;
    /* 線が細いほうがアニメーションが綺麗なので0.5pxを指定 */
    stroke-width: 0.5px;
    -webkit-animation: stroke-anim 5s linear;
    animation: stroke-anim 5s linear;
}
@-webkit-keyframes stroke-anim {
  0% {
    /* 100%だと最後まで表示されないので多めに設定する */
    stroke-dashoffset: 150%;
    fill:transparent;
  }
  50% {
    fill:transparent;
  }
  100% {
    stroke-dashoffset: 0%;
    fill:black;
  }
}

@keyframes stroke-anim {
  0% {
    /* 100%だと最後まで表示されないので多めに設定する */
    stroke-dashoffset: 150%;
    fill:transparent;
  }
  50% {
    fill:transparent;
  }
  100% {
    stroke-dashoffset: 0%;
    fill:black;
  }
}

```

### 解説

試しみると上記サンプルのように「Hello」の輪郭がアニメーションで表示された後、塗りつぶしアニメーションが開始され下記のように表示されます。

<img width="247" alt="スクリーンショット 2017-08-16 17.15.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/81308/0db970ba-e775-492c-2811-a1fbf4aa4f0d.png">

# 終わりに

思ったより簡単に実装ができましたが、輪郭のアニメーションなので手書き風とはいかなかったです(｀･ω･´)
[途中経過]ニュースについて話せる匿名掲示板をrailsで作る

# 作るもの

匿名で知らない人とニュースのことについて気軽に喋りたい。周りの人間や肩書を気にせず。と考えてニュースフィードが流れていてそれについてログイン無しで喋れる掲示板を作ろうと考えた

# サービス全体像

## ユーザーのニーズ

facebookやtwitterでは基本的にはリアルの人間関係がベースになってしまう。そういうリアルでは全く無関係な人と喋ってみたい、コミュニケーションしてみたいを叶える。なにか媒介が無いと話題に困るので芸能や経済などの記事をベースに喋る。

## ユーザーのフロー

* 検索エンジンで記事ページがヒットする
* 記事を読み気になったことをコメントする
* 他の人と会話をする
* 返信が気になりまたサイトに訪れる。ここで下記をさせないといけない
    * サイト名を覚えさせる
    * ブックマークさせる
    * HOMEに落とさせる
    * SNSをフォローさせる

## グロース戦略

### 初期グロース戦略

初期はSEOを気をつけ、検索経由で新規ユーザーをどれくらい獲得できるかによる。SEOで気をつけたいのは

* コピーと見なされないようにしたい
* コメントを活発化させたい（見せたい）

### 中期〜長期戦略

* メディアの下にチャットウィジェットとして追加してもらう

### 仮説検証ポイント

* 検索流入UU
* 検索で来たユーザーのコメント率
* ユーザーの再帰率（これは正確には測れなさそう）

### 見ていくKPI

# 技術選択、設計

## 使う技術

* rails・・・まあこれの勉強のためなので
* bootstrap・・・デザインはサクッとしたいので
* heroku・・・rubyを入れられるサーバで最も簡単そうなので
* feedjira・・・hatenaのRSS取得
* nokogiri・・・RSS取得したもののコンテンツをDBに入れておきたい→これなくても部分的に引っ張れそう

## やった実装

【rails】kaminariを使ってページネーションを作る

http://qiita.com/you88/items/df68aaee3010e282d1ae

## コンテンツの引っ張り方

### 引っ張る内容

表示速度などのことを考え、DBに記事の情報を少なくとも下記は入れておきたい

* タイトル
* 媒体名
* URL
* meta_descrition
* thumnail_url（画像を入れるとDBの容量食いそう）

### 引っ張り方

* hatenaのRSSをfeedjiraで引っ張る
* DBに内容を保存
* 1日に一回heroku scheduleでrakeを起動させ引っ張る

## DBの設計

![スクリーンショット 2017-08-18 12.48.17.png](https://qiita-image-store.s3.amazonaws.com/0/193389/0cfa4ed6-0ca1-2b0f-e61c-533bc4e9a135.png)

* user・・・user情報を入れるtable。基本は匿名でログインしない。session_idで判別する。ただサイトに表示するのはsessionをそのまま表示するのは嫌なのでuser_idを生成する。user_idはプライマリーで1から順。session_idとuser_idは1対1。
* post・・・textでまずは文章のみの投稿。user_idでuserに紐付ける。フィードから自動で引っ張ってきたものは運営のuser_idに紐付ける。OGPから引っ張る。
* comment・・・postの下にぶら下がっている。これも投稿者が分かるようにuser_idのカラムあり。

## 機能

* ユーザーがコメントした際にユーザーを登録・・・commentアクションを作成し、その中に入れる。
    * ブラウザにsession_idを
    * DBにユーザーを格納
* フィードで記事を毎日引っ張ってくる
    * feedjiraをheroku scheduleで毎日引っ張る
    * DBに記事情報をOGPからひっぱり格納
* 記事の投稿に対してコメントできる機能
    * 基本は削除できなくていいかなー
ETLをサーバレス化するAWS Glueについての概要

## まえがき

最近、AWS Glueが一般人でも使えるようになりました。そこでどんなものかと、調べてみました。一人で調べ物した結果なので、機能を正しく把握できているかいまいち自信がありませんが、理解した限りで公開します。

ハンズオンは他にゆずることにして、概観的な話を中心とします。

## 概要
AWS Glueは、日々行われるデータ集約やETL処理を自動化、およびサーバレス化するサービスです。

いま、未加工のCSVやJSONによるログデータや、
アプリケーションで使用している既存のデータベースなどがあるものの、
そのままでは分析が難しく、データ分析のために整備された領域が求められているとします。

AWS Glueの文脈では、前者をデータストア、後者をデータカタログと位置づけます。
データカタログは主に、フルマネージドなHDFS上のストレージ領域です。
たとえば、Amazon Athenaからデータカタログを分析することができます。

AWS Glueは以下の3要素からなります。

* データ分析の中央リポジトリでありデータを一元管理する**データカタログ**
* 様々なデータストアからデータカタログにデータを集約する**クローラ**
* データカタログ内のデータをETLする**ジョブ**

AWS Glueによって、データ分析基盤のサーバレス化を進めることができます。たとえば、 ` (Customer's Application)-> S3 -(Glue Crawler)-> Data Catalog -> (Athena)` は、データ収集から分析・可視化までをエンドツーエンドでサーバレスに構築する一例です。ここで、データの加工が必要であるならば、`Data Catalog -(Glue Job)-> Data Catalog`を加えればよいでしょう。

AWS Glueはフルマネージドであり、その処理はスケールアウトするため、ユーザはデータ規模やインフラ運用を意識することなく、データを加工するスクリプト(ETLの"T"に対応)の作成に集中することができます。ほかにも、AWS Glueは、データカタログ上のテーブルメタデータのバージョン管理機能や、クローラでの入力データからのスキーマ自動推論機能、クラシファイアでの検査に基づきスキーマの変更を検知する機能などを備えています。


## クローラ
AWS Glueにおけるクローラとは、データストアのデータを、
データカタログに移住させるために使われる機能です。

クローラの目的は、散在する複数のデータストアそれぞれを見張らせ、
最新のデータを発見し、それらのデータをデータカタログへと集約し、データカタログを最新に保つことにあります。

クローラは、クラシファイアという要素を通じて、カラム名変更、型変換などの簡単な変換処理を行ったり、
半構造データをテーブルの形式に整えたり、スキーマの変更を検知できたりします。
クラシファイアは、デフォルトのものを使うことも、自分でカスタマイズすることもできます。

作成されたクローラには、ジョブ実行方法(オンデマンドか、スケジュールベースか、イベントベースか)が定義されています。
たとえば、クローラを定期実行させておくことで、データカタログがデータストアに対しおおむね最新であることが保証されます。

![](http://docs.aws.amazon.com/glue/latest/dg/images/PopulateCatalog-overview.png)


## ジョブ
クローラを使って単にデータをデータカタログへと移住させただけでは、
クエリを叩けてもデータが使いにくく、ユーザにとって分析が難しい場合があります。
このとき、より分析に適した形にするために、ETL処理が必要です。

AWS Glueにおけるジョブとは、抽出・変換・ロード(ETL)作業を実行するビジネスロジックです。
ジョブが開始されると、そのジョブに対応するETL処理を行うスクリプトが実行されます。
こちらもクローラと同様に定期実行などの自動化が可能です。

ユーザは、ジョブ作成者として、抽出元(データソース)、およびロード先(データターゲット)を定義します。
ただし、データソースおよびデータターゲットは、どちらもデータカタログ上のデータです。
ユーザは、ジョブ処理環境を調整したり、生成されるスクリプトをビジネスニーズに基づいて編集したりします。

最終的に、Apache Spark API (PySpark) スクリプトが生成されます。
こうして作成されたジョブは、データカタログで管理されます。

![](http://docs.aws.amazon.com/ja_jp/glue/latest/dg/images/AuthorJob-overview.png)


## 参考文献
AWS Glue 概要

* http://docs.aws.amazon.com/glue/latest/dg/components-key-concepts.html
* http://dev.classmethod.jp/cloud/aws/studying-aws-glue-introcution-in-aws-reinvent-2016-movie/
* https://aws.amazon.com/jp/glue/
* http://dev.classmethod.jp/cloud/aws/aws-solution-days-2017-report-introduction-of-aws-glue/ 
* https://aws.amazon.com/jp/glue/faqs/

クローラ

* http://docs.aws.amazon.com/glue/latest/dg/populate-data-catalog.html
* http://docs.aws.amazon.com/glue/latest/dg/add-crawler.html

ジョブ

* http://docs.aws.amazon.com/ja_jp/glue/latest/dg/author-job.html
[クイズ]javascriptと仲良くなるための一歩　第３０話「関数」

#問題

##第1問

```js
function doit(){
  fn();
  function fn() { console.log("called"); }
}

doit(); //=> ?
```

#第2問

```js
function doit(){
  fn();
  var fn = function () { console.log("called"); }
}

doit(); //=> ?
```

:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:
:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:

#問題

##第1問

```js
function doit(){
  fn();
  function fn() { console.log("called"); }
}

doit(); //=> called
```

##第2問

```js
function doit(){
  fn();
  var fn = function () { console.log("called"); }
}

doit(); //=> Uncaught TypeError: fn is not a function
```

"関数宣言文の巻き上げ"からの問題でした:hugging_face:
いまさらアジャイルサムライを読んでみての感想

https://estore.ohmsha.co.jp/titles/978427406856P
電子書籍が売ってたので衝動買いなのである。
本の中で「ウォータフォールモデル」との対比がなかったのは印象的でした。

## ざっくり個人的まとめ

1. agileとは週単位で成果（≒動くソフトウェア）を顧客にアウトプットしその価値を最大化するために努力しつづける姿勢である
2. 週単位の成果を出すには顧客・開発側双方の視点により開発のスコープ（＝つくられるもの、価値）をコマギレにせねばならぬ
3. 価値を最大化するには常に顧客の要望や開発チームの変化に追従できねばならぬ
4. これらを達成するために必要なチームメイクの手法、開発手法、計画の手法などについてはベストプラクティスがある。参考にせよ

## 印象に残ったフレーズとそれに対する感想

> よいか、アジャイルサムライは眼前に居並ぶ四天王のうち、時間と予算、それから品質は固定されたものとみなし、スコープを柔軟に扱うのだ。

- 自分のふんわり理解していた「アジャイル」の定義に一番しっくりきたフレーズ。いわゆる伝統的ウォータフォールと呼ばれるモデルではスコープ（＝要件）が予め与えられて固定であり他に流動性がある、という文脈での対比が多く成されているように思う。

> 計画はチームのベロシティを踏まえて立てるわけだが、（中略）これは個人の生産性を計測するのとはぜんぜん違う。個人の生産性を測るのは、プロジェクトマネジメントのダークサイドへの道だ。
> 個人の生産性を測ると、バグと手戻りと思い違いが増える。一方、協調しようとかスキルを伸ばそうとか知見を共有しようとかいった態度は薄れていく。（中略）チームメンバー同士で考え方を共有すること。助け合うこと。落とし穴にはまらないように気を配ること。こうしたすべてが失われてしまう。

- ベロシティは個人でも測らねばならぬ、それはとてもつらそうだ、と思っていた私にとっては目から鱗の視点であった。エンジニア同士が助け合える世界になることはとても素晴らしいことだ。

## おすすめ度

- ユニットテストを書いたこともなければCIも触ったことが無いわたくしでも十分楽しく読めたので、これからチームでコードを書く初心者にこそおすすめです
- チームメイクの手法も書いてありますが、個人の心構えとして勉強になるところも多いと思いました
- 喋りが映画っぽくてラノベ読んでるみたいにさくさく読めます。
lensの(^?)はなぜGetting (First a) s aを引数に取るのか

# 結論
　`Getting (First a) s a`は`Maybe a`を返せるような`Prism' s a`の特殊化だから。
（`Getting (First a) s a`は`Prism' s a`）

# (^?)とは？
　`Prism`のアクセサです。
ちょうど`Lens`の`(^.)`と同じですが、`Prism`なので`Maybe`で結果を返します。

```haskell
(^?) :: s -> Getting (First a) s a -> Maybe a
```

　このようなPrismを作った時に使います。

Test.hs

```haskell
{-# LANGUAGE TemplateHaskell #-}

module Test
  ( Foo(..)
  , _Bar
  , _Baz
  ) where

import Control.Lens (makePrisms)

data Foo = Bar Int
         | Baz Char

makePrisms ''Foo
-- 以下の関数がコンパイル時に定義される
-- _Bar :: (Choice p, Applicative f) => p Int  (f Int)  -> p Foo (f Foo)
-- _Baz :: (Choice p, Applicative f) => p Char (f Char) -> p Foo (f Foo)
```

Main.hs

```haskell
import Test
import Control.Lens ((^?))

x :: Foo
x = Bar 10

y :: Foo
y = Baz 'a'

main :: IO ()
main = do
  print $ x ^? _Bar
  print $ x ^? _Baz
  print $ y ^? _Bar
  print $ y ^? _Baz
```

output

```
Just 10
Nothing
Nothing
Just 'a'
```

　`Prism`はこんな型です。

```haskell
type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
-- _Bar :: (Choice p, Applicative f) => p Int  (f Int)  -> p Foo (f Foo)
-- _Baz :: (Choice p, Applicative f) => p Char (f Char) -> p Foo (f Foo)
```

- [Control.Lens.Type (Prism)](https://www.stackage.org/haddock/lts-8.11/lens-4.15.1/Control-Lens-Type.html#t:Prism)

　しかし`Prism`のアクセサである`(^?)`は、
`Prism s t a b`ではなく`Getting (First a) s a`を要求します。

```haskell
type Getting r s a = (a -> Const r a) -> s -> Const r s
```

- [Control.Lens.Getter (Getting)](https://www.stackage.org/haddock/lts-8.11/lens-4.15.1/Control-Lens-Getter.html#t:Getting)


# 結論
　やはり`Getter`, `Getting`、`Setter`, `Setting`の時と同じで、`Getting (First a) s a`は`Prism s t a b`として一般化できます。

```haskell
type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
type Getting r s a = (a -> Const r a) -> s -> Const r s
```

なぜなら……

- - -

　`(->)`は`Choice`なので`p`に当てはまります。

```haskell
instance Choice (->)
```

- [Control.Lens.Prism (Choice)](https://www.stackage.org/haddock/lts-8.11/lens-4.15.1/Control-Lens-Prism.html#t:Choice)

　`First a`は`Monoid`で、かつ`Const (First r)`は`Applicative`なので、
`Const (First a)`が`f`に当てはまります。

```haskell
instance Monoid (First a)
instance Monoid a => Applicative (Const a)
```

- [Data.Monoid (First)](https://www.stackage.org/haddock/lts-8.11/base-4.9.1.0/Data-Monoid.html#t:First)
- [Control.Lens.Getter (Const)](https://www.stackage.org/haddock/lts-8.11/lens-4.15.1/Control-Lens-Getter.html#t:Const)

（`First a`は`Maybe a`と同型です）

　これを簡約すると

```haskell
Getting (First a) s a = (a -> Const (First a) a) -> s -> Const (First a) s
（Const (First a)を一般化） ==> forall f. Applicative f => (a -> f a) -> s -> f s
（(->)を一般化）            ==> forall p f. (Choice p, Applicative f) => p a (f a) -> p s (f s)
                              = Prism s s a a
                              （s,aを一般化） ==> Prism s t a b
```

となるので、`Prism s t a b`は`Getting (First a) s a`の一般化です。

- - -

　それにより`Getting (First a) s a`は`Prism s s a a`になるので、
`(^?)`はより特殊化された型`Getting (First a) s a`を受け取ります。
（特殊化することにより`Maybe a`を返せるようにしてるはず）

　`Prism s s a a`は`Prism' s a`なので、上述の結論に帰着します。

　1,2ヶ月前にlensを使い始めたときからの疑問だったのですが、わかってしまえば最強ですね。
よっしゃ :dog2:
Google ChromeでPOSTパラメータをF5更新で引き継ぐ

追記：現在(60.0.3112.101)ではChromeのアップデートによりpostパラメータが取れるようになったため、この対応をしなくても正常動作します。Goggleさん・・・

# Google ChromeでPOSTパラメータをF5更新で引き継ぐ

postで開いたページをGoogle ChromeでF5更新をするとpostパラメータが空になってしまう・・・
いつの間にこんな仕様変更が・・・
Googleさんやってくれましたね・・・
という事で対策しました。

## Before
```php:index.php
<html>
  <body>
    <form method="post" action="./">
      <input type="text" value="test" name="a" />
      <input type="submit" value="submit" />
    </form>
    <?php var_dump($_POST) ?>
  </body>
</html>
```
この状態では、submitした後にF5更新すると$_POSTが空になってしまう。
## After
```php:index.php
<html>
  <body>
    <form method="post" action="./">
      <input type="text" value="test" name="a" />
      <input type="submit" value="submit" />
    </form>
    <?php var_dump($_POST) ?>
    <?php
    echo f5reloadForm();
    function f5reloadForm()
    {
      $result = '';
      if (!empty($_POST)) {
        $result .= '<form method="post" id="reload_form" action="">';
        foreach ($_POST as $key => $value) {
          $result .= makeTag($key, $value);
        }
        $result .= '</form>';
        $result .= PHP_EOL;
        $result .= <<<JS
<script language="JavaScript"><!--
window.document.onkeydown = function (event)
{
  if (event.keyCode == 116) {
    var target = document.getElementById("reload_form");
    target.action = location.href;
    target.submit();
    return false;
  }
}
//--></script>
JS;
      }
      return $result;
    }
    function makeTag($key, $value)
    {
      $result = '';
      if (is_array($value)) {
        foreach ($value as $k => $v) {
          $result .= makeTag(sprintf('$s[%s]', $key, $k), $v);
        }
      } else {
        $result = sprintf('<input name="%s" value="%s" type="hidden" />', $key, $value);
      }
      return $result;
    }
    ?>
  </body>
</html>
```
F5更新用の擬似formを作ってpostパラメータ全てをhiddenに格納。
F5を押したときに擬似formをsubmitする事でF5更新と同等の挙動をするようにしました。

## 欠点
1. Ctrl+F5が実質使えない
2. ブラウザのリロードボタンは対策できていない

対策は不十分ですが、何も対策できていないより良いよね♪
amazon lambda上で文字コード変換をする上でハマるたったひとつの罠

# 開発環境とlambda環境の違い
- `npm install`で処理するネイティブモジュールは環境に依存するため、lambdaについてはEC2上に同環境を作成して処理しないとうまく動かないことがある
- 特に**iconv！**

```
# mac上だとうまくエンコードできるのに･･･（EC2上でネイティブモジュールを処理したものであればOK）
Error: Encoding not recognized: 'ISO-2022-JP' (searched as: 'iso2022jp')
```

## 最新のlambda環境をつくるためのAMI
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/current-supported-versions.html

## 余談
- nodemalilerでiso-2022-jpがうまく扱えない記事を読みiconvを入れたにも関わらず、うまく動かない一因がおそらくこれ
- 入れただけでうまく動かない場合はmimelibのデコードも合わせて利用しましょう
platformio-ide-terminalからatom-terminalに乗り換えました

platformio-ide-terminalはATOMの中からコマンドを実行するためのターミナルプラグインです。
ATOMのターミナル系プラグイン(terminal-plusやatom-terminalなど)の中では一番ダウンロード数も多く、使いやすかったのですが今回atom-terminalのほうに乗り換えることにしました。
今回はその経緯とその際の設定について書きます。

# 乗り換えた経緯
Electronがうまく実行できませんでした。
vue-cliを使って、electron-vueのプロジェクトを作成したのですが、`npm run dev`を実行しても以下のようなエラーが出て実行できませんでした。

```
┏ Electron -------------------

  C:\test\dist\electron\main.js:3524
        app.on('browser-window-created', (e, win) => {
           ^

  TypeError: Cannot read property 'on' of undefined
      at module.exports.module.exports.opts 

```

調べてみると、electron-debugというパッケージのコードが原因のようだったので、`npm run build`で実行すれば正常にビルドができ、出力された実行ファイルを実行することもできました。

しかし、開発の際には不便なので原因を調べていくと、ATOMのplatformio-ide-terminalでの実行ではうまくいかないとのコメントを見つけました。
そこで、Windows Pawoer Shellから実行したら普通に実行できました。

# atom-terminalへの乗り換え
terminal-plusをまずは健闘したのですが、インストールしても動かなかったので、atom-terminalに乗り換えました。
atom-terminalはplatformio-ide-terminalやterminal-plusとは異なり、ATOMの中でターミナルを実行するのではなく、別ウィンドウで開きます。
実行ファイルも設定できるので、今回のようにatom-terminalで開いた場合には実行できない、ということはなくなるではないかと思います。

## atom-terminalの設定
# Power Shellへの変更
Windowsでatom-terminalを使う場合、標準でコマンドプロンプトのパスが実行ファイルとして指定されています。
Windows 10からはPower Shellが標準になるとのことなので、これに設定を変更します。
ATOMの設定画面のパッケージからatom-terminalの設定画面を開きます。
AppというところにPower Shellの実行ファイルのパスを入れてあげるとPower Shellが起動するようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/115996/4481e925-aa4b-b56c-e719-d758b161cd1b.png)

# キー設定の変更
platformio-ide-terminalでは、`ctrl-@`でターミナルを開いていましたが、atom-terminalのデフォルトのキー設定では`alt-shift-t`で開くようになっていますので`ctrl-@`に変更します。
atom-terminalの設定画面の中の「View Code」というボタンを押すと`atom-terminal.cson`というファイルが開きますので、そこのキー設定を変えてあげます。

```cson
'atom-workspace':
    'ctrl-@': 'atom-terminal:open-project-root'
```

これで、ATOMを再起動すると、`ctrl-@`でPower Shellが起動するようになります。
Power Shellからなら問題なくElectronが動きます。

# まとめ
Electronをやってみたかったので乗り換えましたが、やっぱりエディタの中で直接コマンドが打てたほうがよいので、このバグが直ればplatformio-ide-terminalに戻りたいです。
express4 でファイルアップロード


ファイルのアップロードというか写真のアップロードをしたい。

## クライアント側Angular

```js

  private readFile(file: any) {
    const reader = new FileReader();
    reader.onloadend = () => {
      const formData = new FormData();
      const imgBlob = new Blob([reader.result], {type: file.type});
      formData.append('file', imgBlob, file.name);
      this.postData(formData);
    };
    reader.readAsArrayBuffer(file);
  }

  private postData(formData: FormData) {
    this.http.post("http://192.168.230.22:8080/v1/user_photo", formData)
      .catch((e) => this.handleError(e))
      .map(response => response.text())
      .finally(() => this.loading.dismiss())
      .subscribe(ok => this.showToast(ok));
  }
```


## サーバ側Express

req.bodyでも、req.filesでも、中身を取得できないと悩む始末
reqの内容をダンプしてみている

```bash

api |   headers:
api |    { connection: 'upgrade',
api |      'x-forwarded-for': '172.28.0.1',
api |      host: '192.168.230.22',
api |      'content-length': '17985467',
api |      'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryWxpDgOaYBsqFrsAB',
api |      origin: 'file://',
api |      accept: 'application/json, text/plain, */*',
api |      'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60',
```

##  'content-type': 'multipart/form-data

Expressのapp.jsには、body-parserが入っています。
これが曲者。

```js

app.use(bodyParser.json());

app.use(bodyParser.urlencoded({
   extended: false
 }));
```
body-parserのモジュールは、jsonとurlencode済みのものしか扱いません。ファイルアップロードのようにmultipartのものは扱わないのです。

なので、上記部分をコメントアウトか、パスによって分岐をするかして、ファイルアップロードの際には適用しないようにする


以下では、ContentTypeで適用

```js

// parse application/json 
app.use(bodyParser.json({ type: 'application/*+json' }));

// parse application/x-www-form-urlencoded 
app.use(bodyParser.urlencoded({
  extended: false,
  type: 'application/x-www-form-urlencoded'
}));
```

## multer

いくつかファイルアップロードライブラリがあるので、お好みで。
今回はmulterを利用。以下に簡単サンプルコード。

express/uploadにファイルが作られます

```js

var multer  = require('multer');
var upload = multer({ dest: 'uploads/' })

router.post('/user_photo', upload.any(), (req, res, next) => {
    logger.info(req.files);
    res.status(200).end();
  });
```

log出力内容

```bash
api | 2017-08-15T12:33:57+0000 <info> api.js:269 (router.post) [ { fieldname: 'file',
api |     originalname: 'cdv_photo_015.png',
api |     encoding: '7bit',
api |     mimetype: 'null',
api |     destination: 'uploads/',
api |     filename: '1f73e8b4197b863716f6b21b447551e9',
api |     path: 'uploads/1f73e8b4197b863716f6b21b447551e9',
api |     size: 18025712 } ]
```
クラスタリングでRogue風MAP(部屋の部分)生成

# はじめに
クラスタリングを覚えたのでなんかに応用してしてみたいと思った結果こうなりました。

# 定義
- Mapのサイズ
  - 幅:  64
  - 高さ: 32
- 部屋の数
  - 2 ~ 9個をランダムに決定
- 使用したライブラリ
  - ncurses v5.86.0
  - rand v0.3
- クラスタリングアルゴリズム
  - K-Means

# 実装内容
1. マップの中に点をランダムにいくつか生成する
2. 生成した点をクラスタリングする
3. クラスタリングされた点の群から、最小のx,yを左上、最大のx,yを右下として四角く部屋とする

# 動作イメージ

## 点を生成
- 数値はlabelに相当します
- 数値の隣にドット(.)がついているのはそのラベルのセントロイドです
 
<img src="https://qiita-image-store.s3.amazonaws.com/0/96373/f367e021-2bb3-cc5e-78eb-360c25c5d84a.png" width="500">

## 点をクラスタリング
<img src="https://qiita-image-store.s3.amazonaws.com/0/96373/39b5b7c0-15eb-8aa1-1b14-9e343ff110a4.png" width="500">

## クラスタリングした点から部屋のサイズを取得
- label内の点の最小のx,yが左上、最大のx,yが右下の四角い部屋を作成したいので、その値を取得
- ここでは、左上のx,yとそこからのwidthとheightを取得しています

![point.png](https://qiita-image-store.s3.amazonaws.com/0/96373/d12b4e6e-35cf-bb8f-de49-de3c1a3ba166.png)

## 部屋のサイズから、実際にマップに描画
<img src="https://qiita-image-store.s3.amazonaws.com/0/96373/93995917-07e8-c444-95af-8728b377938a.png" width="500">

# 問題点
- 部屋数を現在ランダムで決定しているので、クラスタリングが失敗するときがある
- K-Meansを用いているので、一応分割的ではあるが、斜めに分割されると、部屋が被るときがある
  - これに関しては、点と点をうまく結ぶことで回避は可能

# まとめ
- クラスタリングで部屋生成することができた
- 他のクラスタリング手法を使えばバリエーションも増やせそうに感じた

# ソース
- https://github.com/kokoax/rogue_rs