OmniAICreator/Qiita-1.07M huggingface dataset:
数百万行あるログから、ごく一部分の期間を最短時間で取得

数百万行あるログから、ごく一部分の期間を最短時間で取得

# 課題
システムを運用していると数百万行を超える膨大なログの中から、ほんの数行のログを抜き出したいことがある。
それもできることなら時間もかけず、サーバーに負荷もかけずに行いたい。

# 検証

Vagrantで仮想マシンCentOS 6.4を立ち上げて検証。
実現するアプローチはいくつもあるが、今回は大きく2つを調べる。
・sedコマンドで行数を指定して抽出
・headで一度抜き取り、そこからtail

どちらが短時間で目的を達成できるか検証した。

検証対象のファイルは500万行あるログファイルとし、
頭の方（  1万行目～  1万1000行目）
中の方（250万行目～250万1000行目）
下の方（499万行目～499万1000行目）
の3パターンで検証した。

## 頭の方（  1万行目～  1万1000行目）

抽出条件
10,000件目から11,000件目の1000件を抜き出す。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/75761/100a1992-604a-e313-7c94-3d1b2cdee2a6.png)


### sedコマンドによる抽出
``` sed
 time sed -n 10000,10999p nginx_access.log > sed-output

real 5m1.768s
user 0m0.330s
sys 0m40.347s
```
sedコマンドでは約5分強かかった。

### head->tailによる抽出
``` head->tail
 time head -n 10999 nginx_access.log | tail -n 1000 > headtail-output

real 0m1.097s
user 0m0.000s
sys 0m0.084s
```

約1秒で抽出ができた。

### 差分確認
もちろんsedで取り出しても、head->tailで取り出しても中身は同じ。

``` 差分確認
diff headtail-output sed-output
(何も表示されない。差分なし)
```

## 中の方（250万行目～250万1000行目）

抽出条件
2,500,000件目から2,501,000件目の1000件を抜き出す。
![250.png](https://qiita-image-store.s3.amazonaws.com/0/75761/c5a96ed7-8ef9-6a21-7688-d1a02a1a084b.png)

### sedコマンドによる抽出
``` sed
 time sed -n 2500000,2500999p nginx_access.log > sed-output

real 4m38.208s
user 0m0.439s
sys 0m41.766s
```
約4分40秒かかった。

### head->tailによる抽出
``` head->tail
 time head -n 2500999 nginx_access.log | tail -n 1000 > headtail-output

real 4m26.298s
user 0m0.684s
sys 0m32.164s
```

約4分半かかった。
若干head->tailのが早いが、その差は10秒程度。
vagrantを使って自分のマシンに仮想サーバでの検証なので、ほとんど誤差かもしれない。



### 差分確認
もちろんsedで取り出しても、head->tailで取り出しても中身は同じ。

``` 差分確認
diff headtail-output sed-output
(何も表示されない。差分なし)
```


## 下の方（499万行目～499万1000行目）

抽出条件
4,990,000件目から4,991,000件目の1000件を抜き出す。
![499.png](https://qiita-image-store.s3.amazonaws.com/0/75761/46fd200a-6b30-d36b-7af3-a06fc604e038.png)



### sedコマンドによる抽出
``` sed
 time sed -n 4990000,4990999p nginx_access.log > sed-output

real 5m1.196s
user 0m0.431s
sys 0m42.043s
```
約5分強かかった。

### head->tailによる抽出
``` head->tail
 time head -n 4990999 nginx_access.log | tail -n 1000 > headtail-output

real 10m57.515s
user 0m1.098s
sys 0m25.951s
```

下の方だとhead->tailは11分かかった。
sedコマンドでは安定の5分での取得。
逆にtail->head であればすぐに取得が可能だった。



### 差分確認
もちろんsedで取り出しても、head->tailで取り出しても中身は同じ。

``` 差分確認
diff headtail-output sed-output
(何も表示されない。差分なし)
```

#結論
簡単にsedコマンドで取得しがちだが、
ファイルの上の方の情報を取得したい場合は head->tailが最も早い。
（逆に下の方の情報を取得したい場合は tail->head）
sedコマンドによる情報取得は早くはないが、抽出場所（上か中か下か）による影響は受けない。
SublimeTextのPythonでUnicodeEncodeErrorが発生した場合の対処


SublimteText上でPython実行してたら、日本語データを取り扱ったとたんに`UnicodeEncodeError`が発生した。

標準のpythonではなく、pyenv経由でインストールしたpythonを使うために個別にbuildの設定をしてたんだけど、そこに日本語に対する設定がされていなかったのが問題だった。

### Pyenv.sublime-buildの設定

```json
{
    "cmd": ["/hoge/.pyenv/shims/python", "$file"],
    "selector": "source.python",
    "env": {"LANG": "ja_JP.UTF-8"},
    "file_regex": "file \"(...*?)\", line ([0-9]+)"
}
```
SublimeTextでLuaなどのインデントを自動化する【SublimeText3, 2】

SublimeText3でLuaを最近書いている。

SublimeTextでLuaを書いてて困るのは、
例えば、

```lua:インデントが崩れるコード1.lua
if a then
 elseif b then
end
```

```lua:インデントが崩れるコード2.lua
{
{
{
}
}
}
```

1の例はelseif b と書いた時に、インデントが1つ上がる。
2の例はテーブルを書いた時にインデントが上がらない。
などである。

そこで、同僚がインデントを自動化させていたので、そのTipsを共有しようと思う。
SublimeTextの便利な機能の一つに、自動インデントを言語ごとにカスタムする機能があるので紹介する。

[参考記事　http:////blog.lotech.org/2013/04/fixing-lua-indenting-in-sublime-text.html](http://blog.lotech.org/2013/04/fixing-lua-indenting-in-sublime-text.html)

１、Package ControlからPackageResourceViewerをダウンロードする

２、[Ctr] + P で Package Resource Viewer: Open Resource

３、Lua => Indent.tmPreferencesを編集する

```txt:Indent.tmPreferences
<key>decreaseIndentPattern</key>
<string>^\s*(else|end|\})\s*$|^\s*elseif\b((?!end).)*$</string>
<key>increaseIndentPattern</key>
<string>^\s*(else|elseif|for|(local\s+)?function|if|repeat|until|while)\b((?!end).)*$|.*\{\s*$</string>
```

これで直るはず
どの言語でも使える技なので、SublimeTextの機能を十分に使用して、定時に帰りましょう！
(終わり)
さくらのレンタルサーバーでcomposerめも

# さくらのレンタルサーバーでcomposerめも

## SSH で、さくらのサーバーに接続
macのコマンドプロンプトからはいれる

## シェルを変更

Welcome to FreeBSD!っていわれて、
%
だったら、シェルを変更する

```
% which bash
/usr/local/bin/bash
% chsh -s /usr/local/bin/bash
Password: 
chsh: user information updated
```

```
% vi .bash_profile
```

```
PATH=$PATH:$HOME/bin:$HOME/usr/local/bin
export PATH
```

これで、ログアウト→ログインすると
[tonosamart@www1064 ~]$
とかになる

## composer
```
$ cd ~
$ mkdir -p usr/local/bin/
$ curl -sS https://getcomposer.org/installer | php -- --install-dir=usr/local/bin/
```

おしまい。
送信したOSCメッセージの確認する受信処理を用意する

# OSCの受信を手早く確認するのにProcessingを使用する
Processingだと割と癖がなく、手早くOSCのメッセージを確認することが出来るので
、いつもProcessingのoscP5を利用して、送信したOSCメッセージを確認している

## Processingが手元にないとき
1. Processingの[ダウンロードページ](https://processing.org/download/)に移動する
2. donation(寄付)の選択（払わないときはNo Dunationを選択）して、Downloadボタンをクリック
3. 2.2.1のいずれかを選択（Version 3でも動くとは思うけど未確認）　![20160520_Mocap_PR_001.png](https://qiita-image-store.s3.amazonaws.com/0/111261/8fc6989a-8b65-807d-454c-be2417ceb2ff.png)
4. zipを解凍して、processing.exeを実行する

## oscP5のサンプルソースを修正してOSCの受信を確認する

1. ライブラリをコピーする。　場所：oscP5-0.9.8/oscP5/library/oscP5.jar
2. サンプルソースにcodeフォルダを作成する　場所：oscP5/examples/oscP5sendReceive/code
3. codeフォルダ配下にoscP5.jarをペーストする 場所：oscP5/examples/oscP5sendReceive/code/oscP5.jar
4. oscP5sendReceive.pdeを開いて変更する 場所：oscP5/examples/oscP5sendReceive/oscP5sendReceive.pde

```java:oscP5sendReceive.pde
/**
 * oscP5sendreceive by andreas schlegel
 * example shows how to send and receive osc messages.
 * oscP5 website at http://www.sojamo.de/oscP5
 */
 
import oscP5.*;
import netP5.*;
  
OscP5 oscP5;
NetAddress myRemoteLocation;

int receivePort = 12345;
String sendIP = "127.0.0.1";
int sendPort = 12001;

void setup() {
  size(400,400);
  frameRate(25);
  /* start oscP5, listening for incoming messages at port 12000 */
  oscP5 = new OscP5(this,receivePort);
  
  /* myRemoteLocation is a NetAddress. a NetAddress takes 2 parameters,
   * an ip address and a port number. myRemoteLocation is used as parameter in
   * oscP5.send() when sending osc packets to another computer, device, 
   * application. usage see below. for testing purposes the listening port
   * and the port of the remote location address are the same, hence you will
   * send messages back to this sketch.
   */
  myRemoteLocation = new NetAddress(sendIP,sendPort);
}


void draw() {
  background(0);  
}

void mousePressed() {
  /* in the following different ways of creating osc messages are shown by example */
  OscMessage myMessage = new OscMessage("/test");
  
  myMessage.add(123); /* add an int to the osc message */

  /* send the message */
  oscP5.send(myMessage, myRemoteLocation); 
}


/* incoming osc message are forwarded to the oscEvent method. */
void oscEvent(OscMessage theOscMessage) {
  /* print the address pattern and the typetag of the received OscMessage */
  print("### received an osc message.");
  print(" addrpattern: "+theOscMessage.addrPattern());
  println(" typetag: "+theOscMessage.typetag());
  
  theOscMessage.print();
}
```

theOscMessage.print();

公式ドキュメント
http://www.sojamo.de/libraries/oscP5/reference/oscP5/OscMessage.html

![image](https://qiita-image-store.s3.amazonaws.com/0/111261/2a60c53d-beb2-2ee8-82f6-953200c60167.png)

値をとる時
theOscMessage.get(0).floatValue()

公式ドキュメント
http://www.sojamo.de/libraries/oscP5/reference/oscP5/OscArgument.html
処理待ちの時終了の合図を教えてくれるアラートのエイリアス作った



コンパイル待ちとかインストール待ちとかの時に他の作業しててもわかるように通知してくれるようにするエイリアスの作り方。
terminal-notifierとafplayを使って実装してあります。
afplayの部分をsayコマンドに変えて、Kyokoに喋ってもらうのありかなと思い変えようか迷ってるw

## とりあえず通知用のterminal-notifierを入れる

> brew install terminal-notifier

で完了！

![スクリーンショット 2016-04-25 18.43.48.png](https://qiita-image-store.s3.amazonaws.com/0/31292/3939252f-bd66-577b-0df8-a9ac471bcf6e.png)


> terminal-notifier -message プロセスが終了しました

みたいな感じで使える!

## afplayで終了用の音楽を流す

> afplay /System/Library/Sounds/Hero.aiff

これでMac標準で入ってる音楽流せる

/System/Library/Sounds/以下にいろいろ入ってるのから選んでもいいし、ituensとかの音楽指定したりいろいろ使える

### sayコマンドでKyokoに喋らせる
> say "ほにゃらら"

でKyokoに話させるのもあり

# aliasとして登録する

```lang:.bashrc
alias alert='terminal-notifier -message プロセスが終了しました;afplay /System/Library/Sounds/Hero.aiff'
```

.bashrcにaliasとして登録して完了です！
alias alertをコマンドのあとに繋げれば、コマンドの処理が終わり次第メッセージと音で教えてくれます。

ちなみに
自分は音が一回だと気づかない時があるので3回ならしてますw
Rust でも愛を生む二人を探す

[愛を生む二人を探して](http://qiita.com/shuhei/items/ffddebaa537a34c9ea05)という記事が面白かったので、 Rust でも試してみました。

```rust:couple.rs
use std::char;

/// 定数『愛』
const KANJI_AI: char = '愛';


/// 『愛』を生む可能性のある、『愛』以外の文字の配列を返す。
fn create_kanji_list() -> Vec<char> {
    let mut vec = Vec::new();
    // /[一-龠]/ の範囲を検索
    for bits in ('一' as u32)..('龠' as u32) {
        if bits != KANJI_AI as u32 && bits & KANJI_AI as u32 == KANJI_AI as u32 {
            vec.push(char::from_u32(bits).expect(format!("{:#x} 有効な文字ではありません。", bits).as_str()));
        }
    }
    vec
}

/// 文字の配列を元に、『愛』を生むペアを返す。
fn search(list: Vec<char>) -> Vec<(char, char)> {
    let mut pairs = Vec::new();
    for (i, kanji_1) in list.iter().enumerate() {
        for kanji_2 in list.iter().skip(i + 1) {
            if *kanji_1 as u32 & *kanji_2 as u32 == KANJI_AI as u32 {
                pairs.push((*kanji_1, *kanji_2));
            }
        }
    }
    pairs
}

fn main() {
    let kanji_pairs = search(create_kanji_list());
    for kanji_pair in kanji_pairs.iter() {
        println!("{},{}", kanji_pair.0, kanji_pair.1);
    }
}
```

#結果
出力結果は [GitHub-Gist の pairs_list.txt](https://gist.github.com/mhgp/fac7c73038e298b338fe88c94938f6be#file-pairs_list-txt) をご覧ください。
[2722行目](https://gist.github.com/mhgp/fac7c73038e298b338fe88c94938f6be#file-pairs_list-txt-L2722)に本家大元『死』と『生』のペアが、[2313行目](https://gist.github.com/mhgp/fac7c73038e298b338fe88c94938f6be#file-pairs_list-txt-L2313)に椛(もみじ)ちゃんと猛(たける)くんのペアがいます。

出力が同じであるか確認するためのプログラムは以下の通り。

```rust:check.rs
use std::path::Path;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;


/// &str 型から char 型に変換
/// # Panics
/// 文字列が1文字ではなかった場合、 panic を発生させる。
fn get_char(s: &str) -> char {
    if s.chars().count() == 1 {
        String::from(s).pop().unwrap()
    } else {
        panic!();
    }
}

/// `path` で指定されたファイルから、『愛』を生むペアのリストを読み込み、配列として返す。
fn read_pair_list(path: &str) -> Vec<(char, char)> {
    let mut vec = Vec::new();
    let file = File::open(Path::new(path)).unwrap();
    for line in BufReader::new(&file).lines() {
        let line = line.unwrap();
        let v: Vec<&str> = line.split(',').collect();
        vec.push((get_char(v[0]), get_char(v[1])));
    }
    vec
}

fn main() {
    // オリジナルの出力結果
    let list_1 = read_pair_list("couples.txt");
    // 『 Rust でも愛を生む二人を探す』の出力結果
    let mut list_2 = read_pair_list("pairs_list.txt");
    
    // 出力結果の比較
    for pair_1 in list_1.iter() {
        for idx in 0..list_2.len() {
            if list_2[idx] == (pair_1.0, pair_1.1)
                || list_2[idx] == (pair_1.1, pair_1.0) {
                list_2.swap_remove(idx);
                break;
            }
        }
    }
    if list_2.len() == 0 {
        //-- すべてのペアが一致
        println!("一致");
    } else {
        //-- 一致しないペアが存在
        println!("不一致");
    }
}
```

無事、一致しました！

#なんでアルゴリズムが違うの？
私が理解できなかったからです（泣）。
[UIImage] <-> [CGImage] <-> [CIImage] In Swift


備忘録

UIImage -> CGImage

```swift
let cgImage = uiImage.CGImage
```

CGImage -> UIImage

```swift
let uiImage = UIImage(CGImage: cgImage)
```

UIImage -> CIImage

```swift
let ciImage = uiimage.CIImage
```

CIImage -> UIImage

```swift
let uiImage = UIImage(CIImage: cgImage)
```

CGImage -> CIImage

```swift
let ciImage = CIImage(CGImage: cgImage)
```

CIImage -> CGImage

```swift
let context = CIContext(options: nil)
let cgImage = context.createCGImage(ciImage, fromRect: ciImage.extent())
```
AWS EC2にNginx1.8 + php7 + Laravel5をインストール

## PHP7のリポジトリを追加
```
$ sudo rpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpm
```

## PHP7インストール
```
$ sudo yum install --enablerepo=webtatic-testing php70w php70w-devel php70w-fpm  php70w-mysql php70w-mbstring php70w-pdo php70w-xml
# 自動起動設定
$ sudo chkconfig php-fpm on
```

## nginxのインストール
```
$ sudo yum install nginx
# 自動起動設定
$ sudo chkconfig nginx on
```

### nginx設定
/etc/nginx/nginx.conf

```
# 下記を修正
root         /var/www/html;
# 下記を追加
location ~ \.php$ {
    root           html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /var/www/html$fastcgi_script_name;
    include        fastcgi_params;
}
```

## mysql(server, client)のインストール
```
# mysql5.6のリポジトリを追加
$ sudo rpm -ihv http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
$ sudo yum install mysql-server mysql
# 自動起動設定
$ sudo chkconfig mysqld on
```

## ユーザー作成
```
$ sudo useradd app
```
### www グループをインスタンスに追加
```
$ sudo groupadd www
```

### ユーザーを www グループに追加
```
$ sudo usermod -a -G www app
# ログアウト
$ exit

# インスタンス再接続しgroupsを確認
$ sudo su - app
$ groups
app www
```

### グループ所有者・アクセス権を変更
```
sudo chown -R root:www /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} \;
find /var/www -type f -exec sudo chmod 0664 {} \;
```

### php-fpm設定
/etc/php-fpm.d/www.conf

```
user = app
group = www
```

### nginx/php-fpm起動
```
sudo service nginx start
sudo service php-fpm start
```

## PHPの動作確認
```
$ sudo su - app
$ echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
```

### ブラウザで動作確認
http://[パブリックip]/phpinfo.php

## Composerをインストール
```
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv /home/ec2-user/composer.phar /usr/local/bin/composer
```

## laravelをインストール
```
$ sudo su - app
composer global require "laravel/installer"
```

## project作成
```
$ sudo su - app
$ cd /var/www/html/
$ composer create-project --prefer-dist laravel/laravel test
$ cd test
$ composer install
$ php artisan key:generate
```

## Laravel用にnginx設定を修正
/etc/nginx/nginx.conf

```
# 以下を修正
root         /var/www/html/test/public;

location / {
    # 以下を追加
    try_files $uri /index.php?$query_string;
}

location ~ \.php$ {
    root           html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    # 以下を修正
    fastcgi_param  SCRIPT_FILENAME  /var/www/html/test/public$fastcgi_script_name;
    include        fastcgi_params;
}
```

### nginxとphp-fpm 再起動
```
sudo service nginx restart
sudo service php-fpm restart
```

### ブラウザで動作確認
http://[パブリックip]
でLaravel5 TOP画面が表示されることを確認

## 参考
http://owani.net/php/php7-nginx/285/
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/install-LAMP.html
Rails::Rack::Loggerを継承したmiddlewareをswapする際は引数にlog_tagsを忘れずに

ELBのヘルスチェックをRailsのログに出したくなくて、`Rails::Rack::Logger`を継承したRackミドルウェアで`env`の中身を見て`Rails.logger.silence`するみたいなミドルウェアを作り、`Rails::Rack::Logger`と`swap`するのを試したんですが、`log_tags`が効かなくなってしまいました。

```ruby
class CustomRailsRackLogger < Rails::Rack::Logger
  def call(env)
    if ['/healthcheck'].include?(env['PATH_INFO'])
      Rails.logger.silence { super }
    else
      super
    end
  end
end
```

```ruby
Rails.configuration.middleware.swap Rails::Rack::Logger, CustomRailsRackLogger
```

`Rails::Rack::Logger` を見てみたところ、initializerで第二引数に `taggers` という引数がありました。
これが渡されてなかったから出なかったんですね。

[Rails::Rack::Logger](https://github.com/rails/rails/blob/master/railties/lib/rails/rack/logger.rb#L15)

このようにswapの際にちゃんと渡してあげると`log_tags`が有効になります。

```ruby
Rails.configuration.middleware.swap Rails::Rack::Logger, CustomRailsRackLogger, Rails.configuration.log_tags
```

# 参考

[[rails]ELBのヘルスチェックをアプリケーションログに残さないようにする](https://blog.hello-world.jp.net/ruby/2490/)
GitHubで二段階認証のトークンが使えなくなった時やること

# リカバリコードを控えているか
Yes→リカバリコードを入力すればログインできます
No→次の項へ

# SSHキーは登録済みか
https://github.com/(ユーザID).keys
でkeyが登録されていますか？
Yes→GitHubのサーバにSSH接続することでサポート用のキーを発行してもらえるようです。このキーをつかってサポートに連絡し、二段階認証を切ってもらいましょう。
参考:[How to recover your GitHub account if you lost your 2FA credentials AND recovery codes.](https://medium.com/@kaumac/how-to-recover-your-github-account-if-you-lost-your-2fa-credentials-and-recovery-codes-d171b2bb87f0#.nb4oqmcs2)
No→次の項へ

# リポジトリにpushできるか
Yes→READMEなどにアカウントがログインできなくなったこと書いてpushし、次の項へ
No→次の項へ

# R.I.P.
さようなら。この後悔を心に留め、新しいアカウントを作り、新しいGitHub人生を送りましょう。
前項でpushできる人は、新しいアカウントへの誘導をREADMEに書くのもいいかもしれません。

# さいごに
筆者はこれでアカウントをロックアウトしてしまったので、
みなさんは二段階認証入れるときは必ずリカバリーコードをメモっておきましょう。
大したコードしかうｐされてなくても、無くなってしまうと悲しいものです。
さようなら https://github.com/amichang
こんにちは https://github.com/aminosan
CakePHP3.2.9へのアップデートでエラーを返すようになったexistsInをどうにかする話

**追記：この変更は3.2.10でリバートされました**

***

CakePHP3.2.9がリリースされたのでアップデートしたらテストが通らなくなってしましました… :cry: 
どうやらexistsInが更新されたことが原因のようです。
(変更箇所：[Force ExistsIn rule in new Entiy even with a not dirty field](https://github.com/cakephp/cakephp/commit/66c4011))

今まで以下のような感じの処理をしていました。

```php:src/Controller/ArticlesController.php
public function add()
{
    $article = $this->Articles->newEntity();
    if ($this->request->is('post')) {
        $article = $this->Articles->patchEntity($article, $this->request->data);
        $article->user = $this->Users->get($this->Auth->user('id'));
        if ($this->Articles->save($article)) {
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('保存できません'));
        }
    }
```

```php:src/Model/Table/ArticlesTable.php
public function buildRules(RulesChecker $rules)
{
    $rules->add($rules->existsIn(['user_id'], 'Users'));
    return $rules;
}
```

Controllerでuser_idではなくuserをentityの形で`$article->user`にセットしているので、`$article->user_id`はセットされていないため、`existsIn()`がエラーを返すようになったようです。
今まではuser_idがセットされてなかったらチェックしてなかったけど、新規作成の時はそれは許されなくなったぽい？

というわけで、なんか釈然としないけど、以下を追加しました。

```php:src/Model/Table/ArticlesTable.php
public function beforeRules($event, $entity, $options, $operation)
{
    if (!empty($entity->user)) {
        $entity->user_id = $entity->user->id;
    }
}
```

エラーは出なくなったけど、これでいいのかどうか…。
Vagrant+nginxでストリーミングサーバーを作る方法


ほとんど参考資料のままですが、ストリーミングサーバーをVagrantで作ったので共有します！

# 環境
- MacBookPro (OS X Yosemite ver 10.15.5)
- [Vagrant](https://www.vagrantup.com/) (ver 1.7.4)
- [Open Broadcaster Software](https://obsproject.com/) (ver 0.14.2)
- [VLC media player](https://www.videolan.org/vlc/index.ja.html) (ver 2.2.3 Weatherwax)

# サーバー構築
ストリーミングを中継するサーバーを構築します。
## CentOS7のイメージをダウンロード

```
vagrant box add centos_7_x64_live_stream https://github.com/holms/vagrant-centos7-box/releases/download/7.1.1503.001/CentOS-7.1.1503-x86_64-netboot.box

mkdir vagrant_centos7_live_stream
cd vagrant_centos7_live_stream
vagrant init centos_7_x64_live_stream
```

## ipアドレスを指定

```bash:Vagrantfile
# vi Vagrantfile
...
config.vm.network "private_network", ip: "192.168.33.44"
...
```


## モジュール導入
起動後ログインして、各種設定を行います。

```bash
vagrant up
vagrant ssh
```

### nginxをインストール

```
sudo su
yum update
yum groupinstall "Development Tools"
yum -y install pcre-devel zlib-devel openssl-devel

cd /usr/local/src/
wget http://nginx.org/download/nginx-1.8.0.tar.gz
sudo wget http://nginx.org/download/nginx-1.8.0.tar.gz
tar -zxvf nginx-1.8.0.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
unzip master.zip

# build
cd nginx-1.8.0
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master
make
make install
```

### 設定ファイルの一番下に以下の設定を追加

```bash:/usr/local/nginx/conf/nginx.conf
rtmp {
        server {
            listen 1935;
            chunk_size 4096;

            application live {
                live on;
                record off;
                wait_video on;
            }
        }
    }

```

### iptablesをインストール

```
yum install iptables-services
```

### firewallをオフ

```
systemctl stop firewalld
```

### iptablesを無効化

```
systemctl enable iptables
systemctl stop iptables
```


### nginxの起動確認
nginxを起動したら、Macブラウザから`http://192.168.33.44`にアクセスしてnginxが起動していることを確認します。

```bash
#起動
sudo /usr/local/nginx/sbin/nginx

#停止
sudo /usr/local/nginx/sbin/nginx -s quit
```



# 映像の配信と受信
詳しい手順は参考資料に譲りますが、サーバーの構築が完了したら、
OBSで`rtmp://192.168.33.44/live`に動画と音声を配信開始します。（映像キャプチャデバイス＋音声）
続いて、VLC media playerから`http://192.168.33.44/live/test`にアクセスすると、映像と音声が受信できるようになりました。



# 参考資料

- http://qiita.com/hagane5563/items/842afe6d6e7100db3a28
- http://qiita.com/sparkgene/items/c3ac042f30cc5d0fe324
- http://qiita.com/oggata/items/5933e9a5ab16ece45c5f
- http://qiita.com/ogawatti/items/6a15ced95f6dd2359567
- http://mosuke5.hateblo.jp/entry/2014/09/20/180326
- http://qiita.com/nuxaxtu/items/250ca4fb4e102fa425d7
- http://videojs.com/getting-started/#download-cdn
- http://www.happytrap.jp/blogs/2012/02/23/8243/
ansibleメモ2

またansibleか

■特定ホストのときだけ特定処理(例としてcopy)

---------
[group]
xxx.xx.xx.xa
xxx.xx.xx.xb
xxx.xx.xx.xc yeah=True


---------

    - name: yeah
      copy: src=/file/path/yeah dest=/file/path/yeah_remote owner=foo group=foo
      when: yeah is defined and yeah


---------

未定義チェックをかけてる理由は、変数設定してないホストでエラーになるのを防ぐため。
bool値は先頭大文字のほうがいいらしい。
exists? / present? / blank? メソッド


.exists? とは、Railsアプリケーションを作成した際にデフォルトで読み込まれる ActiveSupport というgemが実現しているヘルパーメソッドです。メソッドを呼び出したレシーバの中から引数として渡した条件で検索をかけ、データが存在すれば true を、無ければ false を返り値とします。
あくまでもRubyが元々持つ機能では無いので、irb上などでは動作しないことに注意してください。

似たようなメソッドとして .present? や .blank? もあります。こちらは、レシーバが空であるか否かを判別するものです。
Jenkins Pipeline Plugin で RejectedAccessException 例外が発生する

Jenkins の [Pipeline plugin](https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+Plugin) (旧称 Workflow Plugin) を使うと、リポジトリに Jenkinsfile というファイルを配置してビルド処理をそこに書くことができます。 ビルド処理は Groovy による DSL で記述します。

さてさて、そんな Jenkinsfile に書かれた処理を Pipeline plugin で実行すると、以下のようなエラーが出ることがあります。 以下の例は `"test".toUpperCase()` を Jenkinsfile に書いた場合に発生したエラーです。 (ちゃんと試してないけど Script Security Plugin の最新バージョンだと起こらないと思います。)

```
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method java.lang.String toUpperCase
	at org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.StaticWhitelist.rejectMethod(StaticWhitelist.java:158)
	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:80)
	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:149)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:146)
	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:15)
	at WorkflowScript.capitalize(WorkflowScript:76)
	at WorkflowScript.run(WorkflowScript:106)
(以下略)
```

これは何かというと [Script Security Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Script+Security+Plugin) の機能です。 Groovy のスクリプトの中に許可されていないメソッド呼び出しがあるとこういう例外が発生します。

Jenkinsfile を弄っているとたまにこういう例外に遭遇して困りますね。 そのメソッドを使わないようにするしかないと思っていたのですが、なんと許可されていないメソッド呼び出しを Jenkins の admin 権限で許可することができます！

一度スクリプトを実行して例外を発生させましょう。 そのあと、**Manage Jenkins** » **In-process Script Approval** で管理画面に進むと、拒絶されたメソッド呼び出しが一覧されるので、そこでメソッド呼び出しの種類を指定して許可することができます。 もちろん危険なメソッド呼び出しは許可しないようにしましょう。

[Pipeline Plugin のチュートリアル](https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md)にも書かれてましたが、ちゃんと読んでなかったのでちょっとハマりました。 Pipeline plugin を使う際にはこういう仕組みが入ってることも覚えておきましょう！

# 関連ページ

* [Jenkinsfile を書く前に知っておくべきこと (セキュリティ制約編)](http://arasio.hatenablog.com/entry/2016/10/07/005055)
BeagleBoneBlackで超音波センサー



今回は、pythonを用い超音波センサーであるHC-SR04を使用します。今回Ubuntu16.04でプログラムを実行しましたが、おそらくUbuntuでなくても無事動くと思います！


詳細をここに置いておきますね。
http://akizukidenshi.com/catalog/g/gM-08762/

http://akizukidenshi.com/catalog/g/gM-08762/

こいつのドキュメントを読むと、Trigに10us以上信号を送ると超音波を送り出すようです。
2つ目のURLに書いてある説明がわかりやすかったです。

####仕様
 - 電源電圧 5V
 - 待機電流 2mA未満
 - 信号出力 0-5V
 - センサ角度 15度以下
 - 測定可能距離 2cm-450cm
 - 分解能 0.3cm
 - 端子間隔 2.54mm

####使い方
1. トリガ端子を10us以上Highにしてください。
2. このセンサモジュールが40kHzのパルスを8回送信して受信します。
3. 受信すると、出力端子がHighになります。
4. 出力端子がHighになっている時間がパルスを送信してから受信するまでの時間です。
5. 出力端子がHighになっている時間の半分を音速で割った数値が距離です。

##配線の仕方
HC-SR04には端子が4本ありますが、それぞれをどのようにBeagleBoneに配線したかを記します。

 - GND
グランドはBeagleBoneのグランドに接続していきます。

 - Vcc
P9_5のVDD_5Vに接続します。理由としては、HC-SR04の使用電圧は5Vのため5Vを提供するPINに接続します。


 - TRIG
トリガーはGPIOに接続します。今回は`P8_16`を使用します。

 - ECHO
エコーもGPIOに接続します。今回は`P8_11`に接続します。
注: HC-SR04で使用される電圧は5Vです。しかし、BeagleBOneのGPIOの電圧は3.3Vです。そのため、ECHOからの信号を受け取る際は電圧を分圧してあげる必要があります。その際、カラー抵抗などを用いると思います。わたしは底らへんの知識がなく、抵抗値の見分け方、分圧の仕方などまったくわからなかったので、以下に回路を組む際に参考にしたサイトを複数挙げておきます。`今回、同じ抵抗が3本ないし、1:2の関係も築けそうになかったので、参考サイトにあったように1kオームの抵抗をつなぎました。`

雑談:
ラズベリーパイとかは電流制限されているらしいからあんまり考慮しなくてもいいというふうに書いてたりもしたので、beagleboneでも同じことが言えるのかもっと調べる必要がありそうです。

####参考サイト
 - http://www.hisatomi-kk.com/Information/resistance/calculation.html
 - http://part.freelab.jp/s_regi_list.html

 - http://make.bcde.jp/circuit/5v%E3%81%8B%E3%82%893-3v%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B/
 - https://github.com/luigif/hcsr04


##コード

```sonic.py
import time
import Adafruit_BBIO.GPIO as GPIO

TRIG = "P8_16"
ECHO = "P8_11"

print "Distanc Measurement In Progress"

GPIO.setup(ECHO, GPIO.IN)
GPIO.setup(TRIG, GPIO.OUT)

GPIO.output(TRIG, GPIO.HIGH)
time.sleep(0.00001) #10us
GPIO.output(TRIG, GPIO.LOW)

while GPIO.input(ECHO) == 0:
  pulse_start = time.time()

while GPIO.input(ECHO) == 1:
  pulse_end - time.time()

pulse_duration = pulse_end - pulse_start

distance = pulse_duration * 17150

distance = round(distansce, 2)

print "Distance:", distance, "cm"

GPIO.cleanup()

```

##参考サイト
 - http://make.bcde.jp/raspberry-pi/%E8%B6%85%E9%9F%B3%E6%B3%A2%E8%B7%9D%E9%9B%A2%E3%82%BB%E3%83%B3%E3%82%B5hc-sr04%E3%82%92%E4%BD%BF%E3%81%86/
 - https://github.com/luigif/hcsr04 

##余談
はじめて上記のプログラムを動作させた際、なんと動きませんでした。なんでだろうと思って、後日配線を別のものに変え動作させてみたところ無事動きました。なので、動かないぞって思ったらだれにか配線の仕方があってるのか、配線を変えて実行してみるなど試してみてください！もちろん、プログラムの間違いがないかも確認してください！
プログラマの考えが・・身につく本より(Python)：ポインタ

今回はポインタの操作ということで、
pythonでポインタを使うには、、、Pythonでは特に考えずにコードが書けてしまったので
あまり勉強になってないのですが、調べたことを記載させて頂きます。

いろいろ調べてみると  [ctypes — Pythonのための外部関数ライブラリ](http://docs.python.jp/3.5/library/ctypes.html)なるものがありました。
これをチュートリアルが日本語だったのでありがたく見ていたのですが、Windowsでの利用方法だったので、Macで使うにはといろいろ探していたら[stacoverflow](http://stackoverflow.com/questions/11554355/mac-os-x-lion-python-ctype-cdll-error-lib-so-6-image-not-found)ですでにあがっていました。

自分の環境でも使ってみたので記載しておこうと思います。

```
>>> from ctypes import *
>>> cdll.LoadLibrary("libc.dylib")
<CDLL 'libc.dylib', handle 7fff6903da98 at 0x1052f6fd0>
>>> libc = CDLL("libc.dylib")
>>> printf = libc.printf
>>> printf(b"Hello, %s\n", b"World!")
Hello, World!
14
>>> strchr = libc.strchr
>>> strchr(b"abcdef", ord("d"))
87110915
>>> 

```

肝心の課題として
<h1>append()関数を作成する</h1>

というものでしたが、
配列の操作で以下解答C++コード

```
void append(arrayString& s, char c){
    int oldLength = 0;
    while(s[oldLength] != 0) {
        oldLength++;
    }
    arrayString newS = new char[oldLength + 2];
    for(int i = 0; i < oldLength; i++) {
        newS[i] = s[i];
    }
    newS[oldLength] = c;
    newS[oldLength + 1] = 0;
    delete[] s;
    s = newS;
}
```

<h2>自分のPythonコード</h2>

```
#!/usr/bin/env python
#coding:utf-8

#ctypesモジュール(mac用)
from ctypes import *
#cdll.LoadLibrary("libc.dylib")
#libc = CDLL("libc.dylib")

def add(s,c):
    print('前の文字列：',list(s))
    print('前のポインタ：', c_wchar_p(s))
    newlength = len(s)+2
    newS = []
    for i in s:
        newS += i
    for j in c:
        newS += j
    print('後の文字列：',newS)
    print('後のポインタ：', c_wchar_p(str(newS)))

>>>(実行ターミナル)
>>> from test38 import add
>>> add("test","! ")
前の文字列： ['t', 'e', 's', 't']
前のポインタ： c_wchar_p(140481723952464)
後の文字列： ['t', 'e', 's', 't', '!', ' ']
後のポインタ： c_wchar_p(140481723970864)
>>> 

```
あんまりctypesモジュール必要になかったけど、PythonでもC言語使えることを知りました。
nginxでメンテナンス中ページを出すだけのサーバを立てる方法

AWSでプロダクション環境をメンテナンスするときに、一時的にメンテナンスページを表示する方法です。ここでは、ELBとEC2をつかったやりかたを紹介します。ここで紹介する方法の他にもRoute53とS3を組み合わせて、自動でDNSフェイルオーバーすることで、メンテナンスページを出す方法もありますが、「AWS ソーリーページ Route53 S3」などで検索するとたくさん情報があるので、サーバレスのソーリーページの実現方法はそちらに譲りたいと思います。

ここで紹介するEC2でメンテナンスページを出す方法としては、

1. メンテナンスに入る前に、ELBからアプリケーションサーバを切り離し、
2. それと同時に、ELBにソーリーサーバを繋ぐ

という手動運用で行われる計画停止を前提としています。


## ソーリーサーバの構築

AWS公式のUbuntu AMIから適当に1台、EC2のインスタンスを起動します。つぎに、nginxをインストールします。

```
apt-get install nginx
```


## ソーリーサーバのファイル構成

ファイル構成としては、必要最低限にするのがポイント。ファイルが見つからなかったら、503レスポンスを返すため。

```
/usr/share/nginx/html
├── ping.html ... ELBのヘルスチェック用ファイル。200レスポンスを返す必要がある
└── maintenance.html ... メンテナンス中のソーリーページ。どんなURLにアクセスしてもこのページを出すようにする
```

## ソーリーサーバのnginxの設定

デフォルトのサイト設定 `/etc/nginx/sites-enabled/default` を3箇所書き換えます。

```nginx:
server {
	listen 80 default_server;
	listen [::]:80 default_server ipv6only=on;

	root /usr/share/nginx/html;
	index index.html index.htm;

	# Make site accessible from http://localhost/
	server_name localhost;

	location / {
		try_files $uri @maintenance; # ここ！
	}

	# ここ！
	location @maintenance {
		return 503;
	}

	# Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
	#location /RequestDenied {
	#	proxy_pass http://127.0.0.1:8080;
	#}

	# error_page 404 /404.html;

	# redirect server error pages to the static page /50x.html
	# ここ！
	error_page 503 /maintenance.html;
	location = /maintenance.html {
		root /usr/share/nginx/html;
	}

...以下はデフォルトのまま
```

以上でソーリーサーバの構築は完了です。
非脱獄向けTweak（？）巷で話題のSideloadを試してみたらかなりの可能性を感じた話。

## 巷で話題のSideloadを試してみた。
JB界隈では脱獄無しのTweakとかいう~~新時代の幕開けみたいな~~ものが出てきましたね。
いわゆる、「Sideload」ってやつです。
## Sideloadの仕組み
(~~イマイチ仕組みはわかってないですが~~)簡単にいえば、アプリ内にdylibをぶち込んで、dylibごとIPAにしてインストールしちゃおう！って感じです。

好きなdylibを参照するためにアプリのバイナリをいじったりします。

## やり方。
Macがないとダメです（Xcodeで署名するため）
~~仮想で組んでおくと便利だったりする(小声)~~
#### 必要なもの

- Xcode7
入れ方はぐぐってください。（丸投げ

- optool (バイナリの改変に使う)
https://github.com/alexzielenski/optool 
releasesから落としてPATHの通ってるとこにでも置いといてあげてください。

- iOS App Signer(IPAの署名するためにつかう)
https://github.com/DanTheMan827/ios-app-signer
落として好きなところに置いといてあげてください。

- Theos-Jailed(Sideload用のTheos) 
https://github.com/BishopFox/theos-jailed/
落として好きなところに(ry
※バージョンが古いせいでlibsubstrate.dylibがarm64対応してないので適宜差し替えてね。

- HookしたいアプリのIPA
今回は、そこにあったYoutubeのIPAでやってみました。

###1.Xcodeで実機デバッグ出来るようにする（省略
Xcodeでプロジェクトを作り実機デバッグできるようにしておいてください。
Apple IDでログインしてﾎﾟﾁﾎﾟﾁで出来るはず。
詳しくはGoogleさんに。。

###2.IPAを解凍
unzipコマンドでもなんでも良いです。
解凍しておいてください。

```bash:IPAファイルの解凍
unzip Youtube.ipa
```
解凍したら、Payloadフォルダ以外のファイルは基本的に要らないので消すなりなんなりと。。。

###3.Theos-Jailedでプロジェクト作成
Theoserお馴染みの`nic.pl`でプロジェクトを作れるので省略。
初期のテンプレだと`Makefile`にいろいろ書いてあるけど下を参考に書き換えてください。

```mf:Makefile
include theos/makefiles/common.mk
ARCHS = armv7 arm64 #←追加
TWEAK_NAME = HelloWorld
HelloWorld_FILES = Tweak.xm fishhook/fishhook.c #これだけでOK！

include $(THEOS_MAKE_PATH)/tweak.mk

after-install::
	install.exec "killall -9 SpringBoard"
```

次に`Tweak.xm`を適当に。。。

```logos:Tweak.xm
#include "fishhook/fishhook.h"
%hook YTAppDelegate
-(BOOL)application:(id)arg1 didFinishLaunchingWithOptions:(id)arg2{
	bool r=%orig;
	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"HelloWorld" message:@"Hello non jailbreak tweak! ;)" delegate:nil cancelButtonTitle:@"┐(ツ)┌" otherButtonTitles:nil];
    [alert show];
	return r;
}
%end
```

###4.`make`る
ふつーに`make`してあげてください。
すると、同じディレクトリの`obj`フォルダに`HelloWorld.dylib`ができてるはずです。

###5.アプリのバイナリにdylibのパスを設定
2で解凍したディレクトリに移動し

```bash:optool
optool install -c load -p @executable_path/HelloWorld.dylib -t Payload/YouTube.app/YouTube
optool install -c load -p @executable_path/<dylibファイル名> -t <バイナリの位置>
```

###6.dylibを`Payload/<アプリ名>.app/`にコピー
4でできたdylibを`Payload/<アプリ名>.app/`にコピーしてあげてください。

```bash:コピー
cp obj/HelloWorld.dylib ../../sideload/Payload/YouTube.app
cp <dylibへのパス> <IPAを解凍したディレクトリ>/Payload/<アプリ名>.app/
```
そうしたら、zipコマンドでipaに戻してあげましょう。

```bash:IPA化
zip -r Youtube-Hacked.ipa Payload/
```
###7.iOS App SignerでIPAに署名
落としておいた、iOS App SignerでIPAに署名します。
プロビジョニングプロファイルのところは、1で作ったXcodeのプロジェクトを選択してください。
![iOS App Signer](https://qiita-image-store.s3.amazonaws.com/0/97864/3be59dd2-058b-4614-1174-c7efd4b01154.png)
あとは適当に。。
そうしたら、「Start」を押すと、署名済みIPAの保存場所を聞いてくるので適当に設定してあげてください。

###あとは、IPAをインストールするだけ！
IPAをインストールすれば完了です。(・∀・)
<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Hello World ;) <a href="https://t.co/cMWauahScQ">pic.twitter.com/cMWauahScQ</a></p>&mdash; すり身焼き㌠ (@ChikuwaJB_blog) <a href="https://twitter.com/ChikuwaJB_blog/status/733548207708377089">2016年5月20日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

##非脱獄で出来るのが面白いところ！
IPAを改変し、ｵﾚｵﾚ(開発用)署名で動かすという~~凄い裏ワザ感~~。。
質問等があったらコメントにドンドン書いてもらって大丈夫です(´∀｀)
ではでは～
htmlのtableを自由自在に操りたい


#参考サイト

http://mairis.at.webry.info/201108/article_2.html
http://qiita.com/ritukiii/items/349ad7dee239bb220d6b

#とにかく、テーブルを分割することはできない

なので全て **結合でなんとかする** と考えることです。
以下のコードのような3×3のテーブルをベースとします。

```
<table>
  <tr>
    <td>A</td>
    <td>B</td>
    <td>C</td>
  </tr>
  <tr>
    <td>1</td>        
    <td>2</td>
    <td>3</td>
  </tr>
  <tr>
    <td>a</td>
    <td>b</td>    
    <td>c</td>
  </tr>
</table>
```

実際にできるテーブルはこんな感じ。

|A|B|C|
|:--:|:--:|:--:|
|1|2|3|
|a|b|c|

#結合には２つある

##縦方向

|▲|B|C|
|:--:|:--:|:--:|
|▲|2|3|
|▲|b|c|

縦3つの`▲`カラムを結合するには `rowspan` を使います。

```
<table>
  <tr>
    <td rowspan="3">▲+▲+▲</td>
    <td>B</td>
    <td>C</td>
  </tr>
  <tr>
    <td>2</td>
    <td>3</td>
  </tr>
  <tr>
    <td>b</td>    
    <td>c</td>
  </tr>
</table>
```

##横方向

|△|△|△|
|:--:|:--:|:--:|
|1|2|3|
|a|b|c|

横3つの`△`カラムを結合するには `colspan` を使います。

```
<table>
  <tr>
    <td colspan="3">△+△+△</td>
  </tr>
  <tr>
    <td>1</td>
    <td>2</td>
    <td>3</td>
  </tr>
  <tr>
    <td>a</td>    
    <td>b</td>
    <td>c</td>
  </tr>
</table>
```
formに入力する必要のない自明のデータはhidden_field_tagを使ってパラメーターに送信する


form_tagの場合
    `<%= form_tag(new_answer_path, method: :get, class: "question_submit") do %>
      <%= hidden_field_tag(:question_id, question.id) %>
      <%= submit_tag("回答する") %>
    <% end %>`

form_forの場合
    `<%= form_for(@answer) do |f| %>
      <h3><span>Q</span><%= @question.text %></h3>
      <div class="form-group">
        <%= f.text_area :text, placeholder: "回答を入力してください", cols:"30", rows:"10", autofocus:"true", class:"form-control" %>
      </div>
      <%= f.hidden_field :question_id %>
      <%= f.submit "回答する", class:"btn btn-primary withripple"%>
    <% end %>`
hidden_fieldをform_forメソッド内で使用する際には f.hidden_field :カラム名 の形で指定します。
【イベントレポート】TORETA BizDev Nightで感じた事

[TORETA BizDev Night (2016/05/19開催)](http://toreta.connpass.com/event/31029/)に参加してきました。イベントのテーマは**事業開発(Business Development)**。海外では比較的タイトルとして確立している印象を持っていますが、日本国内ではまだまだ定着しているとはいえない立ち位置について、実際に日々どんな業務を行っているかを赤裸々に語る座談会となりました。

[Twitter #Bizdev_Night](https://twitter.com/hashtag/bizdev_night?f=tweets&vertical=default&src=hash)

###事業ステージによってBizDevは異なる
**(1)起業直後などゼロからイチ、事業を生み出す事を目的とした新事業開発**
 スタートアップの期初はここであり必ず通過しなければならない。事業軸を決定、確立させ、人材採用や徹底したビジョン創出などあらゆる活動。方向性的にはInternal Business Developmentと言えると思います。

**(2)事業開始後、その事業を成長させるための事業開発**
 パートナーシップ、アライアンス、M&Aなど膨大なパートナー候補から交渉、提携活動を行ったりという諸活動。こちらはExternal Business Developmentと言えそうです。

**(3)事業基盤を成熟したのちに、ニーズや変化に合わせて事業を再構築**
 大企業のオープンイノベーションのように破壊的な変革だったり、既存事業のテコ入れなどを狙った事業開発活動。ここは表現は難しいですが、Open Innovationがひとつの近しい考え方だと思います。

###Biz Devは触媒
セールス、デザイナー、プロデューサー、エンジニア、財務、HR、としてCEOや取締役。社外パートナーなど関係者の間で広く実業を見ながら触媒のように動くことである。また、その人材像としてはMっ気のある人。様々な状況や数値を見ながら、時には窮地に立たされたり、批判を浴びることもあるがその困難を乗り換えることに価値を見出し、情熱を持って推進できる。逆に、技術やプロダクト志向のCEO、CTOなどと比べた場合、**猪突猛進さが必ずしも必須ではない**とも言えるかもしれない

今回のMF、メルカリ、WiL、トレタの皆さんに共通して感じたのは、随所に**バランスを意識**されている点。例えば、著名なエンジニアやCTOなどは自分自身の技術や、揺るぎない軸を持って自身をブランディングしたりする場合がありますが、事業開発ではバランスがとても大切。態度も低姿勢であるべきだが、決して迎合するわけではなく、自分自身が事業で実現したいゴール、ビジョンを常に情熱的に語れる事が求められる。

最近、大企業でオープンイノベーションが推進されている事にも起因されてか、スタートアップ、大企業を含めた協業模索、もしくは大企業や様々な企業の共通プラットフォームになるようなビジネスモデルのスタートアップも多数出ている印象があります。

その点、今回の登壇者に多かったキャリアパスのように大企業、特にレガシーで固めの会社での実務経験も、ビジネス開発における重要なベーススキルであると感じられました。
PHPでSingletonとFactoryの間のデザインパターンを考えてみる

#前提
先日はシングルトンのようで、ファクトリーパターンのような仕組みが必要になったのがきっかけです。
シングルトンの場合は、インスタンスが1度だけ生成されて、それ以降はStaticプロパティーを参照するのみですね。
ファクトリーパターンの場合は、インスタンスを生成し続ける目的で、場合によってはクラスの中で管理することもある。
その役割をミックスさせてパターンが必要になったので、備忘録代わりに書こうと思います。

#1クラスにつき1インスタンスだけ生成させるパターン！
わかりにくいと思いますので、簡単なサンプルを載せいておきます。

```php:sample.php
abstract class Singleton
{
	protected static $instance;

	protected function __construct(){}

	public static function get_instance()
	{
		if( static::$instance === null )
		{
			static::$instance = new static();
		}

		return static::$instance;
	}

	final function __clone()
	{
		throw new \Exception('Clone is not allowed against' . __CLASS__);
	}

	final function __wakeup()
	{
		throw new \Exception('Unserialize is not allowed against' . __CLASS__);
	}
}

class A extends Singleton {}

class B extends Singleton {}

A::get_instance();
B::get_instance();

// 結果：両方ともAクラスのインスタンスを返す
```
当然、両方のインスタンスはAクラスのものになります。これはシングルトンの正常動作ですね。
しかし、今回は1クラスにつき1つまでのインスタンスを生成したいので、下記のように変更します。

```php:sample.php
abstract class Singleton_Factory
{
	protected static $instances = array();

	protected function __construct(){}

	public static function get_instance()
	{
		$called_cl = get_called_class();

		if( ! isset(static::$instances[ $called_cl ]) )
		{
			static::$instances[ $called_cl ] = new static();
		}

		return static::$instances[ $called_cl ];
	}

	final function __clone()
	{
		throw new \Exception('Clone is not allowed against' . __CLASS__);
	}

	final function __wakeup()
	{
		throw new \Exception('Unserialize is not allowed against' . __CLASS__);
	}
}
```
各クラスのインスタンスをStaticプロパティーで管理して、1つ以上は作らせない仕組みですね。
そもそもインスタンスを1つに制限させる理由は、使用するメモリを減らすことと、不具合を防ぐためですね。
Wordpressを例にすると、下記のようなコードをプラグインでよく見かけます。

```php:sample-plugin.php
class Sample_Plugin
{
	public function __construct()
	{
		add_action("init", array(&$this, "init"));
	}

	public function init()
	{
		echo "do something here";
	}
}

new Sample_Plugin();
```
よく考えると、このクラスは1度しか初期化されちゃいけないんですよね。
なぜなら、initフックが二重で登録され、initメソッドが複数回呼ばれてしまうからです。
プラグインの中であれば製作者だけの問題なのですが、配布するとなれば気をつけた方がいい気がします。

以上、使い道は少なそうですが、備忘録用に載せておきます。
【SHA-256対応】PHPのcURLテストコード

最近というかいよいよ決済関係でSHA-256の対応が必須になってきました。
割りと最近のサーバであればあまり気にすると事がないようですが、手軽に出来る確認方法が無いものかと探していたところ、そのものズバリがありましたので、共有します。

参考：[【sha-256対応】PHPのcURLテストコード](http://zuntan02.hateblo.jp/entry/2015/11/16/155422)

これを確認するサーバに入れて、ブラウザで開くと

![ダウンロード.png](https://qiita-image-store.s3.amazonaws.com/0/19336/b3ab8a12-f19c-ab0a-e94f-89cd62b841ea.png)

という画面が表示されます。
`This page is for TEST SHA256 SSL Certificate.`と表示されていれば問題無いようです。

問題がある場合には、エラーログに出ていると思いますので、ご確認下さい。
PHPで適当な数のテストデータを配列として作成


データベースを作るほどの量は必要なかったのでベタで配列を作成。
配列まわりが相変わらずわかってないのでメモ。

#手順

1. からっぽの配列つくる
2. 順に差し込む（[2]とすれば2番目、[]だと一番後ろに入る）


```
// 手順１
$testData = [];

// 手順２
$testData[] = [
    "company" => "株式会社クエスチョン",
    "name" => "鈴木博",
    "kana" => "すずきひろし"
];
$testData[] = [
    "company" => "株式会社testtest",
    "name" => "山田太郎",
    "kana" => "やまだたろう"
];
$testData[] = [
    "company" => "さんかく（株）",
    "name" => "田中一郎",
    "kana" => "たなかいちろう"
];
```
ヘルパーメソッドtime_ago_in_wordsで投稿時間を表示する

time_ago_in_words

投稿時間を「○○時間前」のようにしたい場合に利用するビューヘルパーメソッドです。
特にgemを追加する必要なく利用することができます。デフォルトだと英語なのでrailsの環境設定を日本語で表示したい場合は、config/application.rbの言語設定を日本語（config.i18n.default_locale = :ja）にしておく必要があります。また、日本語の文言表示のためにconfig/locales以下にja.ymlを配置しておきましょう。

<%= time_ago_in_words question.created_at %>
questionが作成された時間をxx時間前　のように表示する
人工知能活用事例まとめ


人工知能についてさまざまな分野で活用方法が検討されていますが、どんな分野でどういう風に活用されているのかイマイチよく理解していなかったため、人工知能の活用事例についてメモしておきたいと思います。


***
★[ガリバーインターナショナル]
(http://keieimatome.jp/tag/%E4%BA%BA%E5%B7%A5%E7%9F%A5%E8%83%BD/)

人工知能を活用した店舗解析プラットフォームである「ABEJA DASHBOARD」を活用して、販売比率を1割アップさせた事例。
来店者情報をディープラーニング技術でリアルタイム解析し、人間に理解しやすい情報に可視化することで、「ABEJA DASHBOARD」をアップさせたとのことでです。
販売店舗を保有している企業では有効活用できそうなので、ファッションとか家具などの産業にも活かせるかもしれません。
***

★[松源（マツゲン）](http://ascii.jp/elem/000/001/120/1120795/)

こちらも「ABEJA DASHBOARD」を利用してリテールアナリティクスを実施し、スーパーでの人工知能技術活用により売上が１．６倍となったそうです。
大阪・和歌山を中心に店舗展開を行うスーパーマーケットとのことですが、地方スーパーでの人工知能活用が今後加速していきそうな効果を上げています。
***
★[タカノメ](http://research.pirika.org/)
ポイ捨て調査・分析を人工知能画像解析技術を用いて行うシステムが「タカノメ」です。
現状のゴミ状況をデータ化することで、清掃活動計画を立てたり、美化清掃活動範囲の決定など、さまざまな環境活動に役立てることができそうですね。
ゴミの分布状況をマップに可視化することで、清掃意識が高まる効果もありそうです。

***
★[iRobot「ルンバ」- AWARE(アウェア）](http://labo.irobot-jp.com/history/)

ルンバの中に内蔵されているのが「AWARE(アウェア）」と呼ばれる人工知能です。
部屋の大きさや形状などをセンサーで認識して情報を収集し、即時に情報結果を掃除方法に反映されるようになっています。
「かしこく」「くまなく」「ていねいに」をテーマに掃除をしてくれるので、同じ場所は平均４回ほど掃除走行するようになっています。
***
★[AmiAgent(アミエージェント）](https://www.advanced-media.co.jp/newsrelease/6058)

人工知能を活用したバーチャルオペレータが「AmiAgent(アミエージェント）」です。
カーナビ・家電・ロボットなどさまざまな機器にカスタムして搭載でき、従来人間が行っていた、問い合わせ対応・プロモーション・ビッグデータ収集などに活用できます。
発話者の音声を認識する「音声認識エンジン（AmiVoice)」と音声合成エンジンを連携させて対話できるとのこと。
今後受付業務等が人工知能に置き換わっていきそうですね。
***
★[Capitalico（キャピタリコ）](https://www.capitalico.com/)

金融の分野でも「株取引のノウハウ」を人工知能に学習させ、初心者でも独自取引アルゴリズムを用いて株取引ができるサービス。
「Financial Innovation Business Conference」で大賞を獲得した実績を持ち、CPU+GPUのクラウドクラスタ上で動作するとのこと。
金融・投資分野の取引で人工知能が活躍する場がさらに拡大していくのかもしれません。
***
★[KIBIT（キビット）](http://www.ubic.co.jp/technology/kibit.html)

人間の行動から「機微」を理解して「オススメ情報」などを提供してくれる人工知能が「KIBIT（キビット）」です。
暗黙知を少ないデータから導き出し、マーケティング活動に活かすなど、実業務で有用なサービスを展開するとのこと。
マーケティングに特化した人工知能開発を得意としている企業が開発をしているため、あらゆる企業で活用可能性がありそうです。

***
【その他参考サイト】
◆[理論抜きでザックリ「人工知能」を理解したい！「人工知能」で使われる理論とは？](https://www.programming-fun.net/article/article_19.html)
◆[ベンチャーや中小企業にも大チャンスとなる「人工知能」ビジネス]
(https://www.programming-fun.net/article/article_19.html)
◆[AIセレクション](https://www.ai-gakkai.or.jp/whatsai/AIselection.html)
◆[人工知能 (AI) はどこまで進歩しているのか – 4つの知能レベルと実商品例 –](http://blog.btrax.com/jp/2015/11/09/artificial_intelligence-01/
)
◆[人工知能で人事の手間を軽減。「OfferBox」会いたい学生を自動検索するシステムを拡充](http://offerbox.jp/company/info/6619.html)
Python(Pandas/XlsxWriter)を使ってExcelファイルを操作してみる①



PandasというかXlsxWriterを使ってExcelファイルを操作してみる。
ちょっと触ってみた感じXlwingsの方が使いやすそうな感じもしたけど、
Pandasが使っているので、こっちを使ってみよう。

[ファイルの読み込みについてはこちら](http://qiita.com/katzhide/items/50d989a49a2eecd867f6)

## 参照

[pandas](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_excel.html)
[XlsxWriter](http://xlsxwriter.readthedocs.io/index.html)

## サンプル

今回はExcelファイルを作成する編。

```python
# import lib
import pandas as pd
import numpy as np

# create data
dates = pd.date_range("20130101", freq='D', periods=6)
df = pd.DataFrame(np.random.randn(6,4),index = dates, columns = list("ABCD"))

# set data
fileName = "hoge.xlsx"
writer = pd.ExcelWriter(fileName)
df.to_excel(writer, sheet_name="hoge1")
df.T.to_excel(writer, sheet_name="hoge2")

workbook  = writer.book
worksheet1 = writer.sheets['hoge1']
worksheet2 = writer.sheets['hoge2']

# Add some cell formats.
format1 = workbook.add_format()
format1.set_font_color('red')

index = workbook.add_format({'align': 'left'})
index.set_font_color('blue')

# Set the column width and format.
worksheet1.set_column('C:C', None, index)
worksheet2.set_column('B:B', 20, format1)

# save
writer.save()
```
WindowsでNYTProfを利用してPerlプログラムの実行を解析する

あるお客様からのオーダーでバッチに9時間かかるというので、
調査した時の検証基礎資料。

# ActivePerlをインストール

ここからOSバージョンに合わせてActivePerlをインストール
http://www.activestate.com/activeperl/downloads

# ppmを利用して、NYTProfをインストール

## NYTProfのサポートバージョンを確認する
NYTProfのサポートバージョンを確認する。

NYTProf
https://code.activestate.com/ppm/Devel-NYTProf/

## コマンドプロンプトを管理者権限で起動する

管理者権限で『cmd』コマンドを実行する



### 一般ユーザー権限だとppmコマンドは利用できなかった

```lang:
C:\Users\システム管理者>ppm
'ppm' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
```

## NYTProfコマンドをインストールする

```lang:
ppm
```

Perl Package Managerが起動するので、
GUIにてプログラムをインストールする

![image](https://qiita-image-store.s3.amazonaws.com/0/19439/20482c56-6c41-8128-ef0a-0db66c66ad1d.png)


### ユーザー名が日本語入りの場合、以下のようなエラーが出る。

```lang:
C:\WINDOWS\system32>ppm
ppm gui failed: DBI connect('dbname=C:\Users\システ~1\AppData\Local/ActiveState/ActivePerl/2201/ppm-MSWin32-x64-multi-thread-5_22.db','',...) failed: unable to open database file
```

その場合には以下のようにディレクトリを新規作成して、パスを指定すると良い

```lang:
C:\WINDOWS\system32>MKDIR C:\Perl\ppm
C:\WINDOWS\system32>SET ACTIVEPERL_PPM_HOME=C:\Perl\ppm
```

### CUIでインストールも出来るらしい（未確認）

```lang:※未確認
C:\WINDOWS\system32>ppm-shell
ppm 4.20 (ActivePerl 2201)
Copyright (C) 2013 ActiveState Software Inc.  All rights reserved.
ppm> install Devel-NYTProf
```

# プロファイリングを実行する

## サンプルスクリプト作成
以下のファイルを『C:\Perl\sample.pl』に作成する

```lang:perl
print "hello, world\n";
```

## プロファイリング作成

```lang:
C:\WINDOWS\system32>C:\Perl64\bin\perl -d:NYTProf C:\Perl\sample.pl
hello, world
```

## プロファイリングレポート作成

```lang:
C:\WINDOWS\system32>nytprofhtml
No such signal: SIGUSR2 at C:\Perl64\bin/nytprofhtml line 162.
Reading nytprof.out
Processing nytprof.out data
Writing line reports to nytprof directory
 100% ...
Extracting subroutine call data ...
Extracting subroutine links
Generating subroutine stack flame graph ...
```

Windowsのプロファイルファイル、レポートファイルの保存場所は初期が以下になる

トレースファイル
C:\Windows\System32\nytprof.out
レポートファイル
C:\Windows\System32\nytprof\index.html

## プロファイリングレポートファイルの閲覧

systemフォルダのファイルをブラウザでは閲覧できない為、フォルダ移動をして確認を行う。

```lang:
C:\WINDOWS\system32>xcopy C:\Windows\System32\nytprof C:\Perl\report
C:\Windows\System32\nytprof\all_stacks_by_time.calls
C:\Windows\System32\nytprof\all_stacks_by_time.svg
C:\Windows\System32\nytprof\C-Perl-sample-pl-1-line.html
C:\Windows\System32\nytprof\flamegraph_subattr.txt
C:\Windows\System32\nytprof\index-subs-excl.html
C:\Windows\System32\nytprof\index.html
C:\Windows\System32\nytprof\packages-callgraph.dot
C:\Windows\System32\nytprof\style.css
C:\Windows\System32\nytprof\subs-callgraph.dot
C:\Windows\System32\nytprof\subs-treemap-excl.html
10 個のファイルをコピーしました
```

C:\Windows\System32\nytprof\index.html

をブラウザで開く

サンプル出力結果
https://dl.dropboxusercontent.com/u/4127244/report/index.html
ack使ってる人は、ag(The Silver Searcher)に乗り換えるべき

# 自分のソースコード検索にackじゃなくてagを使おう

---

※20190122追記
ずいぶん前にこれ書いてあって放置されていたんで、改めて。
さらに**RG(ripgrep)**ってやつのほうが早いんで、そっちに載せかえが良いです。
agはもう不要らない子。

---

itermなどターミナルで

```shell-session
find ./ -name "*" | grep "検索したい言葉"
```

で、そのディレクトリ下位のファイルに対してgrepかけられるわけですが、こんな長いコマンド打ってられない！として、
以前まで、**ack**を利用していました。

が、ackなんぞよりももっと早いのあるよ。というのを教えてもらってメリットしかなかったので、オススメします。

ackより圧倒的に高速なくせに、使い方は一緒。
今のところ単に上位互換でしかないのでack使うからag使うほうがいい。


## ag(The Silver Searcher)のインストール方法

```sh
brew install ag
```
homebrew でインストールするだけ。


## ag(The Silver Searcher)の使い方
```
ag "検索したい言葉"
```
itermなどのターミナル上で、目的のディレクトリに着いたらagコマンドで検索すると、その下層にあるファイル全部に対してgrepしてくれる。


## ちょっとした注意点

```
brew list
```
で見ると、
the_silver_searcher
という名前でインストールされている。
agでインストールするのに。

インストール、アンインストール時に「あわわ、agないよー」なんてことにならないように。

参考元：[ackを捨てて、より高速なag(The Silver Searcher)に切り替えた](http://blog.glidenote.com/blog/2013/02/28/the-silver-searcher-better-than-ack/)
部分テンプレートrender partialを使用する際、collectionで変数を渡し、partial側でローカル変数で参照できる

render partialオプション
renderメソッドに :partialというオプションをつけることで、明示的に部分テンプレート名を指定し、部分テンプレートを表示することができます。

コレクションをレンダリングする
パーシャルはデータの繰り返し (コレクション) を出力する場合にもきわめて便利です。:collectionオプションを使用してパーシャルにコレクションを渡すと、コレクションのメンバごとにパーシャルがレンダリングされて挿入されます。

index.html.erb
`<h1>Products</h1>
<%= render partial: "product", collection: @products %>`

_product.html.erb
`<p>Product Name: <%= product.name %></p>`

パーシャルを呼び出す時に指定するコレクションが複数形の場合、パーシャルの個別のインスタンスから、出力するコレクションの個別のメンバにアクセスが行われます。このとき、パーシャル名に基づいた名前を持つ変数が使用されます。上の場合、パーシャルの名前は_productであり、この_productパーシャル内でproductという名前の変数を使用して、出力されるインスタンスを取得できます。

参照：http://railsguides.jp/layouts_and_rendering.html
regex_replace のご利用は計画的に

Movable Type のテンプレートで、記事の内容を操作したいときに、グローバルフィルタの `regex_replace` をどうしても使いたいときがあります。しかし、いささか重いのです。たくさんあると、重くなってテンプレートの編集や再構築がとても遅くなってしまうことがあります。

```
<mt:EntryBody regex_replace="<img ","<amp-img " regex_replace="<iframe ","<amp-iframe " >
<mt:EntryMore regex_replace="<img ","<amp-img " regex_replace="<iframe ","<amp-iframe " >
```

こういうように同じ regex_replace が続くときには

```
<mt:Unless
    regex_replace="<img ","<amp-img "
    regex_replace="<iframe ","<amp-iframe "
    regex_replace="<audio ">,"<amp-audio "
    regex_replace="<video ">,"<amp-video "
>
  <mt:EntryBody>
  <mt:EntryMore>
</mt:Unless>
```

のように、なにもしない`<mt:Unless>`コンテナタグに入れてしまうと、`mt:EntryBody` と `mt:EntryMore` の両方に対して、一回の処理で済むので、再構築も早くなります。おすすめです。
mergeメソッドで、入力してもらったparamsと一緒に予め別のテーブルに持っている情報を保存する

  `def create
    Question.create(create_params)
    redirect_to :root and return
  end`

  `private
  def create_params
    params.require(:question).permit(:text).merge(user_id: current_user.id, group_id: current_user.group_id)
  end`

mergeメソッドを使うことによって、ストロングパラメーター(create_params)が生成される際にuser_idとgroup_idのキーと値を持つハッシュを追加することができます。
CircleCIでビルドが走らないようにするには、コミットメッセージに[skip ci]や[ci skip]を含める

## TL;DR

CircleCIでビルドが走らないようにするには、コミットメッセージに`[skip ci]`や`[ci skip]`を含める。
https://circleci.com/docs/skip-a-build/

## 悩んだこと

CircleCIでビルド後BumpBuildVersionをコミットする必要があると思う。
例えばAppStoreでは、ビルドバージョン(CFBundleVersion)が同じビルドは、例えバージョン(BundleShortVersion)が上がっていたとしてもAppStoreにアップすることは出来ない。
ここで気をつけなければいけないのは、リモートブランチにPushしてしまうとCircleCIが律儀に再度ビルドを走らせてしまい、ビルドのループに陥ることになる。

## 解決策

https://circleci.com/docs/skip-a-build/
コミットメッセージに`[skip ci]`や`[ci skip]`を含めることで、CircleCIでビルドを走らせないように出来る。
fastlaneのlaneはこんな感じ。

```
  desc "Commit version"
  private_lane :commit_version do
    commit_version_bump(
      message: "Bump version [skip ci]",
      xcodeproj: "HelloWorld.xcodeproj",
      force: true
    )
    push_to_git_remote
  end
```
redirect_toにand returnを組み合わせると、リダイレクトする前にアクション内の処理を全て実行できる

redirect_to :root and returnのand returnの部分に注目して下さい。
redirect_to :rootを書くだけではアクション内の処理は終了せず次の行のコードを実行していってしまいます。
今回のケースでは下に続く処理がないので問題ないのですが、慣習的につけるようにするのがベターです。
 
 `def create
    Question.create(create_params)
    redirect_to :root and return
  end`

  `private
  def create_params
    params.require(:question).permit(:text).merge(user_id: current_user.id, group_id: current_user.group_id)
  end`