OmniAICreator/Qiita-1.07M huggingface dataset:
VSCodeで、Electronをデバックする

#デバックツールの起動
ChromeブラウザのF12を押して起動するデバックツールを使えるようにします。
IDEのリモートデバック機能で、ステップ実行できるのは、メインプロセスのみとなります。
レンダリングプロセスをデバックするのは、Webページをデバックするのと同じ要領となります。

```:main.js
"use strict";

const electron = require("electron");
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
let mainWindow;

// 全てのウィンドウが閉じたら終了
app.on('window-all-closed', function() {
  if (process.platform != 'darwin') {
    app.quit();
  }
});
// Electronの初期化完了後に実行
app.on('ready', function() {
  // メイン画面の表示。ウィンドウの幅、高さを指定できる
  mainWindow = new BrowserWindow({
     width: 1024,
     height: 800,
     icon: __dirname + '/src/icons/comix.ico',
  });
  mainWindow.loadURL('file://' + __dirname + '/index.html');

  mainWindow.webContents.openDevTools();

  // ウィンドウが閉じられたらアプリも終了
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});
```
![Screenshot from 2017-01-22 22-18-36.png](https://qiita-image-store.s3.amazonaws.com/0/7839/dd9765ca-7114-a8e4-736f-03dcb751e065.png)
#VSCodeからElectronをデバック実行する
メニューのデバックを選択して、ツールバーから歯車ボタンを押すとlaunch.jsが開かれます。
このファイルが、デバックの設定ファイルです。
![Screenshot from 2017-01-22 22-39-40.png](https://qiita-image-store.s3.amazonaws.com/0/7839/cface3db-7584-90b6-e6ea-63b22411496c.png)

````:launch.js
{
    // Use IntelliSense to learn about possible Node.js debug attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Main Process",
            "type": "node",
            "stopOnEntry": false,
            "program": "${workspaceRoot}/main.js",
            "args": ["test.jpg"],
            "cwd": "${workspaceRoot}",
            "preLaunchTask": null,
            "runtimeArgs": [],
            "env": {
                "NODE_ENV": "development"
            },
            "linux": {
                "runtimeExecutable": "${env.HOME}/.nodebrew/node/v6.9.4/bin/electron"
            },
            "windows": {
                "runtimeExecutable": "${env.APPDATA}/npm/node_modules/electron-prebuilt/dist/electron.exe"
            },
            "console": "integratedTerminal",
            "sourceMaps": false,
            "outFiles": []
      }
    ]
}
```
Electronのライブラリをグローバルにインストールした場合の設定は、こんな感じで動くみたいです。
WindowsとLinuxの設定を共存させることもできます。
シェルスクリプトのwhile文の中の変数を外で使う方法

シェルスクリプトではwhile文の中で変数の値を書き換えてもwhile文を抜けた後に値の変更が反映されていないことがある。
~~説明を省略して対処法だけ書くと、パイプを使わずにヒアドキュメントを使えばよい。~~

**2020/4/12追記**
Process Substitutionという機能を使った方がいいらしいです。
参考記事：https://qiita.com/kawaz/items/6fd4cd86ca98af644a05


## サンプル
一つ目のwhile文ではパイプで文字列を入力しているため、while文の後で`$i`を参照しても`1`になってしまうが、二つ目のwhile文はヒアドキュメントを使っているので、後で`$i`を参照すると変更が反映されて`6`が表示される。

```
#!/bin/bash

STR="\
a
b
c
d
e"

echo "Using pipe"

i=1
echo "$STR" | while read line ; do
    echo $i, $line
    i=$(( $i + 1 ))
done
echo $i

echo
echo "Using heredocument"

i=1
while read line ; do
    echo $i, $line
    i=$(( $i + 1 ))
done << END
$STR
END
echo $i
```

実行結果

```
Using pipe
1, a
2, b
3, c
4, d
5, e
1

Using heredocument
1, a
2, b
3, c
4, d
5, e
6
```

##解説

パイプを使うと次のコマンドは子プロセスとしてforkされる。そのため、サンプルコードの一つ目のwhile文は別のプロセスとなり、その中で変更された`$i`は親プロセスには反映されず、while文の外で`$i`の値を使用することができない。
だが、二つ目のヒアドキュメントを使ったwhile文では、同じプロセスでwhile文が実行されるためwhile文の外でも`$i`の値を使用することができる。

また、プロセスをforkするときに変数はコピーされるため、パイプを使ったwhile文でも親プロセスの変数をwhile文の中で使用できる。そのため、サンプルコードでは`i=0`からではなく、while文の前で初期化された`i=1`から始まっている。
jquery tabs menu

# タブメニュー

jqueryのタブメニューです。
セレクタにidやclassをあまり使えない作業があったので、data-属性で代替しました。

```ruby:js
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript">
  $(function(){
    $('[data-tabs="container"]').each(function() {
      var active = "is-active",
          inactive = "is-inactive",
          wrap = $(this);
      wrap.find('[data-tabs="tab"]:first-child,[data-tabs="pane"]:first-child').addClass(active);
      wrap.find('[data-tabs="tab"],[data-tabs="pane"]').not('.'+active).addClass(inactive);
      wrap.find('[data-tabs="contents"]').css("height",wrap.find('[data-tabs="pane"].' + active).height());
      wrap.find('[data-tabs="tab"]').find('a').click(function() {
        wrap.find('[data-tabs="tab"],[data-tabs="pane"]').removeClass(active).addClass(inactive);
        $(this).parent('[data-tabs="tab"]').removeClass(inactive).addClass(active);
        $(this.hash).removeClass(inactive).addClass(active);
        wrap.find('[data-tabs="contents"]').animate({height: wrap.find('[data-tabs="pane"].' + active).height() },{duration: 500, easing: 'swing'});
        return false;
      });
    });
  });
</script>
```

```ruby:html
<div class="tabs_container" data-tabs="container">
  <ul class="tabs_nav">
    <li class="tabs_tab" data-tabs="tab"><a href="#foo">タブ1</a></li>
    <li class="tabs_tab" data-tabs="tab"><a href="#bar">タブ2</a></li>
    <li class="tabs_tab" data-tabs="tab"><a href="#baz">タブ3</a></li>
  </ul>
  <div class="tabs_contents" data-tabs="contents">

    <div id="foo" class="tabs_pane" data-tabs="pane">
      <h2>タブ1</h2>
      <p>ダミーテキスト。テキストテキストテキストテキストテキストテキスト</p>
      <p>ダミーテキスト。テキストテキストテキストテキストテキストテキスト</p>
    </div>

    <div id="bar" class="tabs_pane" data-tabs="pane">
      <h2>タブ2</h2>
      <p>ダミーテキスト。テキストテキストテキストテキストテキストテキスト</p>
    </div>

    <div id="baz" class="tabs_pane" data-tabs="pane">
      <h2>タブ3</h2>
      <p>ダミーテキスト。テキストテキストテキストテキストテキストテキスト</p>
      <p>ダミーテキスト。テキストテキストテキストテキストテキストテキスト</p>
      <p>ダミーテキスト。テキストテキストテキストテキストテキストテキスト</p>
    </div>

  </div>
</div>
```

```ruby:css
.tabs_container {}

.tabs_nav {
  font-size: 0;
  line-height: 0;
}

.tabs_tab {
  display: inline-block;
  margin-left: 2px;
  padding: 0.3em 10px;
  font-size: 1rem;
  line-height: 1rem;
  -webkit-transition: all 0.4s linear;
  transition: all 0.4s linear;
}

.tabs_tab:first-child {
  margin-left: 0;
}

.tabs_tab.is-inactive {
  background-color: #eee;
}

.tabs_tab.is-active {
  background-color: #fcc;
}

.tabs_tab:hover {
  opacity: 0.6;
}

.tabs_contents {
  position: relative;
  overflow: hidden;
}

.tabs_pane {
  transition-property: opacity;
  transition-duration: 1s;
  transition-timing-function: ease-in-out;
}

.tabs_pane.is-inactive {
  position: absolute;
  z-index: -1;
  visibility: hidden;
  opacity: 0;
}

.tabs_pane.is-active {
  position: relative;
  opacity: 1;
}
```

jsはclassの出し入れ処理のみにして表示切替動作は全部cssにさせたかったのですが、transitionが height:auto 対応していないので、高さのアニメーションはjs側で対応しました。
複数設置に対応とか中途半端に汎用性持たせようとしたので冗長になってしまいました。
いっそプラグイン化してしまった方が良かったかも。
CloudLoggingからBigQueryに流したログ（tsv in json）をみる

CloudLoggingのWebコンソールからBigQueryに簡単にエクスポートの設定ができます。
こういうときは`textPayload`を分割するViewを作っておくと便利。

```sql:viewのクエリ
-- use regacy sqlはoff
SELECT
  REGEXP_EXTRACT(textPayload,r'^(?:[^\t]*\t){0}([^\t]*).*') AS field1,
  REGEXP_EXTRACT(textPayload,r'^(?:[^\t]*\t){1}([^\t]*).*') AS field2,
  REGEXP_EXTRACT(textPayload,r'^(?:[^\t]*\t){2}([^\t]*).*') AS field3,
  ...
FROM
  `projectname.datasetname.somelogs_*`
;
```

`Use regacy SQL`のチェックを外しておくと`*`でテーブルをワイルドカード指定できるので、CloudLoggingが自動的に日ごとにテーブル分割したログをまとめられます。

## 課題

BigQueryのクエリは「処理したデータ量」（`Query complete (13.1s elapsed, 32.4 MB processed)`の32.4MBの部分）に応じて課金ます。インデックスはなく常に全レコードのフルスキャンなので、なるべく条件を減らして参照するカラムを減らしたほうが安く済みます。

> 料金  |  BigQuery のドキュメント  |  Google Cloud Platform
> https://cloud.google.com/bigquery/pricing?hl=ja

上のようにtextPayloadからtsvにするviewを使っているとクエリを投げるたびにtextPayload内が全て読まれるため、無駄です（例えばfield1がhogehogeのときのfield2のcount distinctが欲しい時など）。

なのでデータ量が多いなら予めちゃんとtsvと同じ構造のテーブルにログを入れておいたほうがよいです。
Destination Tableを使うと楽に実現できそうなので今後試します。
Improved Learning of Gaussian-Bernoulli Restricted Boltzmann Machines

PythonでRBMを書いて実験しました．
Bernoulli-Bernoulli RBMだけでなく，Gaussian-Bernoulli RBMも実装しました．
ただし，GB-RBMは***"Improved Learning of Gaussian-Bernoulli Restricted Boltzmann Machines"***\[[pdf](https://users.ics.aalto.fi/praiko/papers/icann11.pdf)\]という論文を参考に分散を更新するようにしています．

improved GB-RBMは人間の音声のパラメータであるメルケプストラム系列を使って実験しました．

実装は[Gitレポジトリ](https://github.com/39cu4c/RBM)にあります．

## 実験（BB-RBM）
MNISTからランダムに取り出した画像50枚で学習します．
![figure_2.png](https://qiita-image-store.s3.amazonaws.com/0/133491/474e4644-0367-75b7-614e-ea1658b29cdf.png)

reconstruct error$E$はいい感じに下がっています．

```math
E = \frac{1} {2}(data-reconst)^{2}
```

![figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/133491/f08a990c-cc88-cd59-c421-840e580a9d8c.png)

さて，RBMにパターンを覚えさせたところで，適当にノイズを加えた画像をRBMにつっこんでみます．
![figure_3.png](https://qiita-image-store.s3.amazonaws.com/0/133491/2ccacf1c-72bc-b06f-a753-b958964af331.png)

元画像のようなものが復元できたのではないでしょうか．
![figure_4.png](https://qiita-image-store.s3.amazonaws.com/0/133491/d569403e-6607-81be-ff1b-4e93fecb2e6e.png)

## 実験（GB-RBM）
reconstruction error
![figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/133491/1195a5f7-b2dd-4e12-4bba-379840dee97d.png)

reconstした連続値のデータ（メルケプ系列）
![figure_2.png](https://qiita-image-store.s3.amazonaws.com/0/133491/a5c06290-e3af-8779-f666-8884bdcf4675.png)
Laravelを使ってWebページを表示する基本的な手順(失敗編)


#この記事を書いた背景
[ララ帳](https://laravel10.wordpress.com/category/はじめての-laravel-5-1/)の20まで終了してそれっぽいWebページを表示することができるようになったが、いざそこまでの知識でwebページを表示しようと思ったら、ハマってしまったので、とりあえず手順だけまとめて書きます。
後日、”ちゃんと動作する”方法を書き、何が間違っていたのか比べるための記事。

#簡単に、手順
1. マイグレーションファイルの作成とマイグレーション
2. モデルの作成と、マスアサイメント
3. コントローラーの作成
4. ビューの作成
5. ルーティングの設定


#マイグレーションファイルの作成とマイグレーション

####マイグレーションファイルの作成
`php artisan make:migration create_todos_table --create=ToDos`

```create_todos_table.php

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;
 
class CreateArticlesTable extends Migration {
 
      public function up()
    {
        Schema::create('ToDos', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
            
        });
    }
}
```
####マイグレーション
`$ php artisan migrate`



#`ToDo.php`(モデル)の作成とマスアサイメントの設定
####モデルの作成
`php artisan make:model ToDo`

####マスアサイメントの設定
```ToDo.php
・
・
・
class ToDo extends Model
{
    //マスアサイメントの設定
    protected $fillable = ['title', 'body'];
}
```

#`ToDoController`の作成
`$ php artisan make:controller ToDoController`

```ToDoController.php
namespace App\Http\Controllers;

class ToDoController extends Controller
{
    //
    public function index()
    {
      $todos = ToDo::all();
      return view('todos.index', compact('todos'));
    }
}
```


#ビューの作成

####layout.blade.phpの作成
表示するWebページのためのテンプレート。
このテンプレートを作成することで、ページごとにhtmlを書かなくてよくなる。

```php
<!DOCTYPE HTML>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>ToDO List</title>


//ブートストラップのcssファイルを読み込む
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
</head>

<body>

  <div class="container">
    @yield('content')
  </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>

```

####index.blade.php
todoリスト一覧を表示するページ。

```php
@extends('layout')

@section('content')
<h1>My ToDo List</h1>
<hr/>

  @foreach($todos as $todo)
    <todos>
      <h2>
        <a href="{{ url('todos', $todo->id) }}">
          {{ $todo->title }}
        </a>
      </h2>

      <div class="body">
        {{ $todo->body }}
      </div>
    </todos>
    @endforeach
@endsection

```


#一覧ページへのルーティングを設定
`Route::get('myList', ToDoController@index);`

- `http://localhost/myList`にアクセスした時に、ToDoControllerのindexメソッドが呼ばれる。
- indexメソッドではヘルパー関数のviewメソッドにより、`index.blade.php`に`$todos`に格納されているデータ一覧が配列として渡される。（compact関数によって）
- ビューでは、foreach文により配列が取り出され、一覧として表示される。

###はずだったのだが、
エラーでページが表示されない。
ConoHaのKUSANAGIテンプレートなCentOSで.html拡張子でPHP有効化するメモ

ConoHaで提供されているKUSANAGI WordPressが動くテンプレイメージで、WordPress以外のPHPスクリプトを動かしたくて苦戦。同イメージではPHPはFastCGI経由で動いていて、通常のAddHandlerに追記するなどの方法ではダメ。

php-fpm側の設定(/etc/php-fpm.d/www.conf)で、
```
security.limit_extensions = .php .html
```
などとすればいいというところまで突き止めたんだけどなぜかこれもダメ。

しかし散々悩んだ挙げ句、よくみたら、/etc/php7-fpm.d/というディレクトリが他にあり、こちらのwww.conf
で上記設定を書き足せばいいというだけでした...（PHP7環境）

ついでにこの環境でのphp.iniは、/etc/直下ではなく、/etc/php7.d/php.iniなのもメモ。
新入社員の定番の役割をPythonで効率化してみた

こんにちは。
新入社員の定番の役割、電話応対をPythonで効率化してみました。

電話を取り次ぐ相手が自席にいないのはよくあること。そのときは電話があったことをメールで伝えるわけですが、決まりきった文面を毎回書くのは実際面倒。ということで本文と件名を作るプログラムを書いてみました。

## 今回やること
* 電話があったことを伝える伝言メールの本文作成
* 過去に電話があった社名・名前を基に電話番号サジェスト

※ メール作成・送信は手動です('ω')

こんな感じのtxtファイルを出力します。
1行目が件名。それ以降が本文です。

```TELmemo.txt
【伝言メモ】foobar様

hogeさん

お疲れ様です。【自分の名前】です。
fooのbar様よりお電話がありました。
折り返しをお願い致します。
TEL 000-000-000
```

以下、ソースコードです。

``` TELmemo.py
#coding:utf-8
import time
from datetime import datetime
import csv
import pandas as pd
import os.path

def existsLog():
    # ログファイルが存在しない場合は作成する
    if os.path.exists("telLog.csv") == False:
        f = open('telLog.csv','w')
        writer = csv.writer(f,lineterminator='\n')
        header = []
        header.append('To')
        header.append('From')
        header.append('incNm')
        header.append('Tel')
        header.append('Time')
        writer.writerow(header)
        f.close()

# 入力された名前, 会社名を持つログから電話番号をサジェストするメソッド
def suggestTelNo(df,nm,incNm):
    telNo = ""
    select = ""
    for index,row in df.iterrows():
        if row['From'] == nm and row['incNm'] == incNm:
            print("もしかして、この電話番号? : ",end="")
            print(row['Tel'])
            print("y/n: ",end="")
            select = input()
            telNo  = row['Tel']
            break
    if select == 'y':
        return telNo
    else:
        return None

# ログを出力するメソッド
def mkLog(To,From,incNm,telNo):
    time = datetime.now()
    timeStr = time.strftime("%Y.%m.%d %H:%M:%S")
    info = [To,From,incNm,telNo,timeStr]

    with open('telLog.csv','a') as f:
        writer = csv.writer(f,lineterminator='\n')
        writer.writerow(info)
    f.close()

if __name__ == "__main__":

    f = open('TELmemo.txt','w')

    ln1 = "\nお疲れ様です。【自分の名前】です。"
    ln2_1 = "の"
    ln2_2 = "様よりお電話がありました。"
    ln3 = "折り返しをお願い致します。"
    ln4 = "TEL "

    print("---伝言メールの本文作ってくれるやつ---")
    print("---伝言履歴---")

    existsLog()

    # 電話番号サジェスト用データフレーム
    df = pd.read_csv('telLog.csv',encoding='UTF-8')
    del df['Time']
    # 伝言履歴を表示する
    print(df)

    print("\n※ 名前の入力は敬称略。")

    print("誰宛て?:",end="")
    to = input()
    print("どこから?")
    print("社名:",end="")
    incNm = input()
    print("名前:",end="")
    nm = input()
    ln2 = incNm + ln2_1 + nm + ln2_2

    # 入力された名前, 会社名を持つログから電話番号をサジェストする処理
    tel = suggestTelNo(df,nm,incNm)
    # 初めて掛かってきた場合は電話番号を入力
    if tel is None:
        print("TEL:",end="")
        tel = input()
        ln4 = ln4 + tel
    # 過去に掛かってきている場合は電話番号を表示
    else:
        print("TEL:" + tel)
        ln4 = ln4 + tel
    # ログを出力
    mkLog(to,nm,incNm,tel)

    # 件名を作成
    sub = "【伝言メモ】" + incNm + nm + "様" + '\n'
    # 本文に入れる文言を分割・格納する
    msg = (sub,to+"さん",ln1,ln2,ln3,ln4)

    # 本文を1行ずつtxtファイルに書込み・画面に出力
    for line in msg:
        print(line)
        f.write(line + '\n')

    f.close()
    # 3秒間だけ待ってやる(内容確認のため)
    time.sleep(3)
    exit()

```
ggplot2における2軸プロットの使いみち

[ggplot2で2軸プロットをする - Qiita -](http://qiita.com/nozma/items/7e430994a2840aad645f)でggplot2 2.2.0から2軸プロットが公式にサポートされている点について書いたが、意味の違う複数の系列を1枚のグラフに収めることについてHadleyが推奨するようになったとかそういうことではなくて(要するに先の記事の使い方はあまり良くない例です)、そもそもそういう用途に便利な実装になっていない。

主軸を何らかの関数で変換して第2軸を作成できるというのがポイントで、1つの系列に対して2つの軸が欲しいというときにこの仕組みが役に立つ。

例えばmpgはデータセットの名前の通り、燃費が「mile par gallon」で記録されているが、「km par little」の軸も欲しいという場合はこうする。

```r
library(ggplot2)
library(dplyr)

# hwy : highway miles per gallon
#  1mile == 1.60934km
#  1gallon == 3.78541L
#  ∴ mile / gallon = 1.60934 / 3.78541 km / L

mpg2kpl <- function(x) x * 1.60934 / 3.78541

mpg %>% 
  ggplot(aes(displ, hwy)) +
  geom_point() +
  scale_y_continuous(sec.axis = sec_axis(~ mpg2kpl(.), name = "km/L")) +
  labs(y = "mile/gal") +
  theme_classic()
```

![Rplot01.png](https://qiita-image-store.s3.amazonaws.com/0/109348/cc029adf-4a27-cadb-ee64-985664217dc9.png)

第2x軸を使う例。

```r
# temperature: deg C
# pressure:    mm of Hg
# 1 mmHg == 0.133322 kPa

mmHg2kPa <- function(x) x * .133322
C2K <- function(x) x + 273.15

pressure %>%
  ggplot(aes(temperature, pressure)) +
  geom_point() +
  scale_x_continuous(sec.axis = sec_axis(~ C2K(.), name = "Temperature (K)")) +
  scale_y_continuous(sec.axis = sec_axis(~ mmHg2kPa(.), name = "Pressure (kPa)")) +
  labs(x = "Temperature (C)",  y = "Pressure (mm of Hg)") +
  theme_classic()
```

![Rplot02.png](https://qiita-image-store.s3.amazonaws.com/0/109348/329f0d76-3f8e-9238-4e10-aa0c59694a9b.png)


# 参考

[ggplot2 2.2.0 coming soon! | RStudio Blog](https://blog.rstudio.org/2016/09/30/ggplot2-2-2-0-coming-soon/)
【DB】正規形の説明【NF2,NF3】

試験とか受けるたびに正規化について覚えなおしている気がするので、
デスペ受けるついでに人に説明する→記憶に定着する、という期待を狙って書いてみる。


# 簡単な説明

## 正規化のポイントは関数従属

### 関数従属について
数学で[関数](https://ja.wikipedia.org/wiki/関数_(数学))というものを習っていると思うが、
>二つの変数 x と y があり、入力 x に対して、出力 y の値を決定する規則

を関数という。
例えば、下記の例にxに適当な数字を入れれば、yの値が決まる。

```math:
y = 4x
```

この「X」にたいして「Y」が一つ決まるの関係のことを
YはXに対して関数従属する、といい

```math:
X \to Y
```

と表現する


数学の世界に限ったことではなく
個人を特定する数字、本を特定する数字、など現実世界にもある。
「マイナンバー」が決まれば「日本人」が特定できる(マイナンバー→個人)
「ISBN」が決まれば「本」が特定できる(ISBN->本)

正規化を理解するコツはデータベース上にある、余計な関数従属を見抜くことにある。

## 第2正規型

主キーの一部 →　非キー列　

の関数従属を**部分関数従属**という。
第2正規型とはこの部分関数従属がない状態のことをいう。

主キーの一部、という記述から分かるように、そもそも第2正規化かどうか、という問題はキー列が複数あるテーブルに対してしか発生しようがない。
まず第2正規型かどうか？という状況になったときは、そのテーブルに存在する全てのキー列をペアに、非キー列の値が一意に決まる以前に、

**一部のキーだけで値が決まってしまう非キー列があるかどうか**

を意識するのが第2正規型かどうかを考えるポイントとなる。

### 第2正規型にしないと何が起こるのか？

式の例では日付、商品cdがキー列のテーブルで
商品cd->商品名の関数従属精があるとする

販売実績テーブル

| \_日付_ | \_商品cd_ |商品名|売上|
|:--:|:--:|:--:|:--:|
| 20161225 |109|クソスマスケーキ|300000|
| 20161225 |110|靴下|400000|
| 20161225 |109|クソスマスケーキ|60000|
| 20161225 |112|ソリ|3000|

#### 問題点1.関数従属のある列の更新が大変

たとえば109の商品「クソスマスケーキ」に誤字が発覚したため、更新してほしいとの要望が発生した。
上記の場合、1行目、2行目の2箇所を修正しなければならない。
データが多くなれば、出現場所全てを修正しなければならないので、データがちぐはぐになる危険性がある。
#### 問題点2.売上のない商品を登録できない。
例の商品実績テーブルは日付がキー列のためnullにすることができない。
このテーブルだけだと、販売実績のない商品、つまり日付と売上の無いレコードをシステム上で扱うことが出来ない。

#### 対策
下記のように関数従属のある列を適切に切り分ければ、変更箇所は商品テーブルの一箇所で済み、
販売実績のない商品は商品テーブルの方に登録することもできる。


販売実績テーブル

| \_日付_ | \_商品cd_ |売上|
|:--:|:--:|:--:|
| 20161225 |109|300000|
| 20161225 |110|400000|
| 20161225 |109|60000|
| 20161225 |112|3000|

商品テーブル

| \_商品cd_ |商品名|
|:--:|:--:|
|109|クリスマスケーキ|

### 第2正規型まとめ

第2正規型とは、部分関数従属(キーの一部→非キー列)がない状態のことである。
部分関数従属がない状態、つまり全ての主キー、非キー列間に関数従属性がなりたっていることを**完全関数従属**という。

## 第3正規型

非キー列 → 非キー列

の関数従属を**推移関数従属**という。
推移関数従属、というとわかりにくいが、

主キー → 非キー列1 → 非キー列2
簡略化: 主キー → 非キー列2

という風に主キーから段階的に推移するイメージができると
「推移関数従属」という言葉と意味が覚えられると思う。
下記の販売実績テーブルではオプションcd → オプション名に関数従属があるとする。
(主キー → オプションcd → オプション名 に推移関数従属がある)

販売実績テーブル

| \_日付_ | \_商品cd_ |売上|オプションcd|オプション名|
|:--:|:--:|:--:|:--:|:-:|
| 20161225 |109|300000|1|蝋燭セット|
| 20161225 |110|400000|2|洗濯ネット|
| 20161225 |109|60000|1|蝋燭セット|
| 20161225 |112|3000|4|トナカイ3匹|
| 20161225 |109|60000|5|和蝋燭|

### 第3正規型にしないとなにが起こるのか？

更新が大変&売上のないオプションが登録できない、
第2正規形とここはほぼ同じ内容になるので省略
※今後の学習次第で特別に加筆の必要に気付いた場合、加筆します。

### 第3正規型まとめ

第2正規型で非キー列が主キーに、非推移的に関数従属する時、
第3正規型である、といえる。

# 正規型まとめ

もちろん下位の正規型の条件を満たす、という前提があるが、
完結にまとめると以下のようになる。

第2正規型:キーの一部 → 非キー列に関数従属性がないこと
第3正規型:非キー列 → 非キー列の関数従属精がないこと

## 正規化のデメリット
正規化すればするほど、更新コスト&リスクが減る代わりに検索コストが増加する。
検索スピードに課題がある場合、ハードウェアや構成に手を入れる選択肢の他に、
予算がない場合はあえて非正規化して対策する、という場合があるらしい。

# 補足
デースペは問題にBCNF,4NF,5NFが出てきているので、そちらも理解しておく必要がある。
issueのテンプレートを再利用するchrome extensionを作った

みなさまこんにちは
chromeのextensionを作ったので紹介します。
issueのテンプレートはすごくいいと思います。
でもそこへのサポートが薄いので、テンプレート運用する時にいい感じにするchrome extensionを作りました。
あともう1つの理由は、chrome extensionを作ってみたかったから:point_up:

## 作ったもの
Githubでissueの雛形を保存しておける拡張機能です。
![apply.gif](https://qiita-image-store.s3.amazonaws.com/0/7442/13c9adec-63e4-fe0f-605a-9584de96c644.gif)

この一瞬で気になっちゃった方はこちらから
[useful issues](https://chrome.google.com/webstore/detail/useful-issues/ndjffnpnjoipcpbpfkgengipennjbblh?hl=ja)

## issueにテンプレートを使う

僕が携わっているプロジェクトではissueを書くときにテンプレートを使っています。
テンプレートに沿ってissueを立てることで誰が書いても最低限の情報が記載され、
「ん？こいつはなにが言いたいんだ:no_mouth:」ということが少なくなります。
質のばらつきや情報のヌケモレがなくなり、足りない情報だけを求めればいいですね
書いてあることを直接本人に尋ねるなんて二度手間なことを避けられますね:relaxed:

## issueを立てるのにwikiにいく

GitHubではissueのテンプレートを作成できる仕組みが備わっています。

[GitHub Issueはテンプレート化で、綺麗に書かせる!](http://qiita.com/yoshimikeisui/items/3e1873e3bf1bbafe8733)
こちらの記事で紹介されているように、issueの新規作成ページにgetパラメータを渡すことで、テンプレート（各項目のデフォルト値）を指定できます。

僕らはこれを利用させていただき、目的別に4つのテンプレートを作って、**wiki**にリンクを張っています。
![スクリーンショット_2017-01-22_21_52_43.png](https://qiita-image-store.s3.amazonaws.com/0/7442/df338085-0728-c251-a881-4a3018439ec7.png)
こんな感じで:rolling_eyes:

だから、「issueを作るためにはwikiを開きます」
頭の中は「issue立てよー」となっているのに「issueのページじゃなくwikiに」行かないといけないんですね。
このせいでちょっとさみしい気持ちになった回数は数えきれません:frowning2:

ISSUE_TEMPLATE.mdファイルを用意することでもテンプレートを用意できるそうですが、1種類だけ？しか用意できない？っぽい？のでスルーです:thinking:
[Issue and Pull Request templates](https://github.com/blog/2111-issue-and-pull-request-templates)

## issueのテンプレートを再利用するchrome extensionを作った
このような背景でissueのテンプレートを再利用するchrome extensionを作りました。
こちらからDLできます:earth_asia:
[useful issues](https://chrome.google.com/webstore/detail/useful-issues/ndjffnpnjoipcpbpfkgengipennjbblh?hl=ja)

## useful issuesでできること
いろいろとアイデアは出てきますが今できるのはこの3つ
- issueテンプレートの保存
- issueテンプレートの適用
- issueテンプレートの削除

### issueテンプレートの保存
![save.gif](https://qiita-image-store.s3.amazonaws.com/0/7442/c5501007-58d2-fd12-b97e-057e288e61c0.gif)
1. issueの作成ページを開く
2. useful issuesのsaveボタンを押下

### issueテンプレートの適用
![apply.gif](https://qiita-image-store.s3.amazonaws.com/0/7442/d6f20fff-5f12-d679-2038-758ec05484a5.gif)
1. issueページでテンプレートを書く
2. useful issuesのapplyボタンを押下

### issueテンプレートの削除
![スクリーンショット 2017-01-22 22.44.50.png](https://qiita-image-store.s3.amazonaws.com/0/7442/dbc64209-3ea2-09ad-476f-fcf431ba45a4.png)
popupのconfigボタンからひらけます。
保存しているテンプレートのプレビューと、削除ができます。

### インストール
こちらから:earth_asia:
[useful issues](https://chrome.google.com/webstore/detail/useful-issues/ndjffnpnjoipcpbpfkgengipennjbblh?hl=ja)

## chrome extensionの作り方
HTML・CSS・Javascriptで作ります。
初めてだったのでいろいろ参考にさせていただきました。

- extensionを作るときの雛形や開発ツールを一通り用意してくださっています。gulp・babel・SCSSに知見のある方向けです。  
[2016年度版 僕が考えたChrome拡張機能を作るときのデザインパターン](http://qiita.com/yoichiro6642/items/d446256e0bd709e2d76b)
- chrome extensionの構成を簡潔に解説してくださってます。あの拡張はこの機能で作られてるのね〜ってなります  
[Chrome拡張 | アーキテクチャ](http://qiita.com/tbpgr/items/168a90ba07badc86e1e6)
- 本家ドキュメントで、APIの具体例も載ってます  
[What are extensions? - Google Chrome](https://developer.chrome.com/extensions)

## まとめ
chrome環境でしか動かないので、ブラウザ環境を気にする必要がなくてよかったです:blush:
あとここからインストールできます:earth_asia:
[useful issues](https://chrome.google.com/webstore/detail/useful-issues/ndjffnpnjoipcpbpfkgengipennjbblh?hl=ja)
Meteorで作ったアプリをherokuを使って独自ドメインで公開するまで

Meteorで作ったアプリをherokuで本番公開するまでの手順を書きたいと思います。
と、その前にまだherokuのアカウント作成とパソコンにherokuをインストールしてない人はそこから始めてください。

## herokuインストール

※Macになります

``` command:command
$ brew install heroku
$ npm install -g heroku-cli
$ heroku --version // versionが表示されれば無事インストール
$ heroku login     // herokuアカウントを入力
```

参考サイト
https://devcenter.heroku.com/articles/heroku-cli

##前提となること

* Meteorアプリを制作済み
* DBは「[mLab](https://mlab.com/)」を使う
* herokuのアカウント作成とインストール
* 独自ドメインを購入済み(レンタルサーバーと契約済み)

##手順

- アプリのディレクトリでherokuアプリを作る
- Meteor Buildpack Horseを設定  
- herokuとmLabを繋げる
- herokuのdomainsに独自ドメインを追加
- herokuのROOT_URLも独自ドメインに変更
- デプロイ
- CNAME変更

## 作業

・アプリのディレクトリでherokuアプリを作る

```
$ heroku create myapp_name
```


・Meteor Buildpack Horseを設定

```
$ heroku buildpacks:set https://github.com/AdmitHub/meteor-buildpack-horse.git
```

・herokuとmLabを繋げる

```
$ heroku config:set MONGO_URL=mongodb://<dbuser>:<dbpassword>@xxx.mlab.com:xxxx/<database_name>
```
「database_name」はmLabで作ったデータベース名前を入れます。
そして、Usersで「dbuser」と「dbpassword」を作って、それを上記のところに書きます。
※「xxx.mlab.com:xxxx」はアカウントに紐付いたものです。

・herokuのdomainsに独自ドメインを追加

```
$ heroku domains:add xxxxxxx.com
```
購入した独自ドメインを追加します。
そうすると。。。

```
$ heroku domains
```

と叩くと

```
Domain Name
xxxxxx.com

DNS Target
xxxxxx.herokudns.com
```

が表示されるかと思います。


・herokuのROOT_URLも独自ドメインに変更

```
$ heroku config:set ROOT_URL=http://xxxxxx.com
```

・push

```
$ git push heroku master
```
これでデプロイされました。

・最後にサーバーのCNAMEを変更

さきほどのDNS Targetの

```
xxxxxx.herokudns.com
```

をサーバーのドメインのDNS設定でCNAMEの項目にそのドメインを書けばドメインとアプリが紐付きます。
これで独自ドメインのページが本番公開されます。
Android スプラシュ画面の実装

#スプラッシュ画面
起動した際に表示される画面です。
スプラッシュ画面は、プログラムの立ち上げが実行中である段階で表示され、
基本的には立ち上げが完了した時点でメイン画面に切り替わります。

下記画面が起動時のスプラッシュ画面です。
画像はユニティちゃんを拝借。

![1485090610oT_NFgDojqET3ul1485090610.gif](https://qiita-image-store.s3.amazonaws.com/0/15564/70db9392-f48d-976e-62b2-9a95e1105b3e.gif)

実装方法は2種類あり、それぞれの特徴は下記となります。
◆Activityでの実装
　長所
　・起動させている間に処理を実行することができる
　・複雑なアニメーションなどを表現できる
　欠点
　・起動時に数瞬ブランクが表示される

◆Theme指定での実装
　長所
　・起動時に数瞬ブランクが表示される
　欠点
　・事前の処理が行えない

今回は特に事前処理がないので、後者ので実装を説明します。
通信で最新の情報などを取得する場合は前者の実装が良いです。

#実装
前回のソースからの変更点を記載します。　→　[Android開発 Hello world表示](http://qiita.com/yamikoo@github/items/8d20dff026af0cc50bef)

<img width="304" alt="スクリーンショット 2017-01-22 22.28.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/15564/ca84425f-70e3-cbd7-aae7-3a75a95df54d.png">

実装時に新たに追加したファイルは
・splash.xml
・splash.png
となります。

splash.xmlには背景色とスプラッシュ用画像をセンターに表示するように記載します。

```xml:splash.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:opacity="opaque"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <item
        android:drawable="@color/colorBack"/>

    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/splash"/>
    </item>

</layer-list>
```

style.xml に　SplashTheme　という名前でスタイルを追加します。
中では　windowBackground　に先ほど作成した　splash.xml　を指定します。


```xml:style.xml
<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="SplashTheme" parent="AppTheme">
        <item name="android:windowBackground">@drawable/splash</item>
    </style>
</resources>
```

Manifestファイルの起動Acivityのthemeに先ほどのスタイルを設定します。

```xml:Manifest.xml一部抜粋
    <activity
        android:name=".MainActivity"
        android:theme="@style/SplashTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
```

上記の設定で起動時にスプラッシュが表示されるようになりますが、
起動後のMainActivityのテーマがスプラッシュ用のテーマのままなので、
Activity内部で変更する必要があります。
また、スプラッシュ画面はコンマ数秒で終わるので、とりあえず＋1秒ほど表示しています。

```java:MainActivity

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ここで1秒間スリープし、スプラッシュを表示させたままにする。
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        // スプラッシュthemeを通常themeに変更する
        setTheme(R.style.AppTheme);
        setContentView(R.layout.activity_main);
    }
```

出来上がりを見ると、フェードイン・フェードアウトをしたくなります。
その場合はActivityでの実装しかありません。
Google Play Musicで再生してる曲を #nowplaying でツイートするブックマークレット

とりあえずということで、シンプルに 『{曲名}』{アーティスト名} と #nowplaying のハッシュタグでツイートするだけ。

```
javascript:void((function(){
	var i, t, a, tw;
	var s = function(i){
		var e = document.getElementById(i).innerHTML;
		return e
		.replace(/&amp;/g, "%26")
		.replace(/&lt;/g, "%3c")
		.replace(/&gt;/g, "%3e");
	};
	t = s("currently-playing-title");
	a = s("player-artist");
	tw = encodeURIComponent("『" + t + "』" + a + "\n#nowplaying");
	void(window.open("https://twitter.com/intent/tweet?text=" + tw));
})());
```

単純に曲名やアーティスト名を ```document.getElementById('foo').innerHTML;``` で取得するだけだと、タイトルに「&」が含まれてたときにツイート文字列が ```&amp;``` になるなどブザマな状態になるので、予め置換処理を行ってます（バッドノウハウかも……）。
Mojolicious x RaspberryPiでコンパクトにIOT試作をする 

# はじめに #
先日、[perl入学式 in大阪 第五回](http://www.perl-entrance.org)へ行ってきた。
内容はperlのMojoliciousというwebアプリケーションフレームワークを使って、掲示板を作ってみようというもの。
そこで実際にMojoliciousを使ってみて、RaspberryPiでIOTする上で自前のwebアプリ制作に使えそうだ、という気分になったので、とりあえず簡単なものを作ってみた。
なお、成果物をまるっと紹介したいだけなので、ライブラリのインストールや、ラズパイのセッティング等は割愛している。

# Why Mojolicious?? #
なぜ、MojoliciousがRaspberryPiでIOTするのに良さそうと思ったかは以下の通り

* linuxの素のシステムパールでさくっと動く
* 一つのperlスクリプトを書くだけでwebアプリが完結する
* webサーバアプリケーション本体を内蔵している
* その気になれば完成度の高いものも作れる
* webiopiのように全て用意されてしまっていないので、自由に作れる

# 環境 #
* サーバ
 * RaspberryPi3
  * OS
   * Raspbian jesse(debian系のlinux)
* perl
 * Raspbian内蔵のシステムperl
* Mojolicious
 * ver.7.20
* ブラウザ
 * safari

#　ブラウザでLチカするだけの試作 #
できた。

![mojo_led.gif](https://qiita-image-store.s3.amazonaws.com/0/143910/729f2b2f-922e-6ef4-e5e8-82f6068e6774.gif)

ざっとMojoliciousのDocを読んで目に付いたのがこれだけだったので、まさかのラジオボタン。
ともかくブラウザで入力した情報を'POST'でサーバへ送って、それを元にサーバのアプリケーションで電子回路を制御する、というIOTっぽい基本的な流れを作れたのでよしとする。

# ハード #
ただledを光らせたいだけなのでこれだけでOK。
![Rpi_led.png](https://qiita-image-store.s3.amazonaws.com/0/143910/42ffafb1-9c5b-18b8-d5b5-efb1707e13ca.png)
アノード側にGPIOを接続している。

# ソフト #
とりあえずwebアプリ側をperl x Mojoliciousで、電子回路制御アプリ側をpythonで用意した。
HTMLはperlスクリプトの\_\_DATA\_\_セクションに記述できるようになっているので、今回はこの2ファイルのみで実装できる。

以前に同じような試作をした時は、HTML, JavaScript, PHPのリソースを一式用意して、apacheに乗せてサーバを立ち上げて...とかなり手間と時間がかかったので拍子抜けするくらいシンプルで楽にできてしまった。

`Mojo_IOT`

```perl
#!/usr/bin/env perl
use utf8;
use Mojolicious::Lite;


my $led ="";

get '/' => sub {
    my $c = shift;
    $c->render(template => 'index');
};

post '/post' => sub {
    my $c = shift;
    $led = $c->param('led');
    `python mojoIOT_led.py $led`;
    $c->redirect_to('/');
};

app->start;

__DATA__

@@ index.html.ep
% layout 'default';
% title 'IN';

%= form_for '/post' => method => 'POST' => begin
    LED<br>
    on
    %= radio_button 'led' => '1'
    off
    %= radio_button 'led' => '0', checked => 'checked'
    %= submit_button 'send'
% end

@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
    <head>
        <title><%= title %></title>
    </head>
    <body>
        <%= content %>
    </body>
</html>
```
* webアプリ側でやっていること
 * `POST`でラジオボタンから値('1' or '0')を取得して変数へ格納し、それを起動引数として下記のpythonスクリプトを実行
 * その他タイトルや文字列の表示

`mojoIOT_led.py`

```python
#!/usr/bin/python

import RPi.GPIO as GPIO
import sys

gpio1 = 18
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(gpio1,GPIO.OUT)

args = sys.argv

if args[1] == '1' :
	GPIO.output(gpio1, GPIO.HIGH)
else :
	GPIO.output(gpio1, GPIO.LOW)
```
* 電子回路制御アプリでやっていること
 * コマンドライン引数を取得し、値に応じてGPIOへhigh/lowの信号を出力する

# サーバの起動 #
Mojolicious内蔵のサーバで起動する。
`$morbo MojoIOT`
デフォルトのポートは`:3000`なので、あとは好きにlocalhostなり、ローカル,
グローバルにアクセスしてブラウザから操作すればOK。

#　まとめ・TODO　#
* まとめ
 * ハード側の開発に時間をかけて、それを利用するweb側をさくっとやっつけたい、でも後々はそれなりのアプリにできたらしたい、みたいな人にはMojoliciousは良さそうだなと思った
* TODO
 * いまいちMojoliciousのDocを読み切れていなくチープな実装になっているので、もう少しweb系のテクニックの習得合わせてしっかりとした実装にしたい
 * 制作しているIOTなマシンに実際に使っていきたい
オブジェクト型配列→Variant型の罠

VBAではVariant型に配列を代入することができる。
このとき、値型配列では正しく型が伝播され、特に問題は起きない。

```vb
Sub 値型配列の場合､正しく型が伝播する()
    Dim Lngs() As Long
    ReDim Lngs(0 To 1)
    
    Dim tmp As Variant
    tmp = Lngs
    
    Debug.Print VBA.TypeName(Lngs)  'Long()
    Debug.Print VBA.TypeName(tmp)   'Long()
    
    tmp(0) = 1
    'tmp(1) = "a"    ’エラー Long型にStringは入らないので
    
    Lngs = tmp
    Stop
End Sub
```

対して、具象オブジェクト型配列をVariant型に入れるとObject型配列として扱われ、具象型によるフィルターが効かなくなる(Variant型ではそこまでの情報を保持できないため)。

```vb
Sub 動的オブジェクト配列の罠()
    Dim cols() As VBA.Collection
    ReDim cols(0 To 1)
    
    Set cols(0) = New VBA.Collection
    'Set cols(1) = Err   'エラー 型が一致しません。→OK
    
    Dim tmp As Variant
    tmp = cols
    
    Debug.Print VBA.TypeName(cols)  'Object()
    Debug.Print VBA.TypeName(tmp)   'Object()
    
    Set tmp(0) = New VBA.Collection
    Set tmp(1) = VBA.Err
    
    cols = tmp  '←！？
    
    
    Set cols(0) = cols(1)   '←！？
                  '↑ErrObject
    Stop
End Sub
```

![DynamicObjectArray.png](https://qiita-image-store.s3.amazonaws.com/0/142842/b8bb7df2-938d-f1a9-b9b4-469110e09c04.png)

# まとめ

Variant型は便利だが、具象オブジェクト型配列を入れる場合注意が必要。
汎用性を落として良い場面では、引数の型・戻り値の型を対象オブジェクト型の配列として宣言すること。
Genericコレクションが欲しい。
配列を配列に追加するときに注意すること

知らんかった...

JavaScript

```js
const data_list = [];
let data = [];
data[0] = 0;
data[1] = 1;
data[2] = 2;
data_list.push(data);
console.log('data:', data); // [0, 1, 2]
console.log('data_list:', data_list); // [[0, 1, 2]]

// data = [];
data[0] = 3;
data[1] = 4;
data[2] = 5;
data_list.push(data);
console.log('data:', data); // [3, 4, 5]
console.log('data_list:', data_list); // [[3, 4, 5], [3, 4, 5]]
```

Python

```py
data_list = []
data = [0, 0, 0]
data[0] = 0
data[1] = 1
data[2] = 2
data_list.append(data)
print ('data: ', data) # [0, 1, 2]
print ('data_list: ', data_list) # [[0, 1, 2]]

# data = [0, 0, 0]
data[0] = 3
data[1] = 4
data[2] = 5
data_list.append(data)
print ('data: ', data) # [3, 4, 5]
print ('data_list: ', data_list) # [[3, 4, 5], [3, 4, 5]]
```

よく考えれば当たり前のような気がしますが，1回目に追加された配列と2回目に追加された配列のアドレスが同じなので，参照される頃には同じ値となっているわけです．
期待する結果である `[[0, 1, 2], [3, 4, 5]]` を出力するには，適切なタイミングで配列を初期化する必要があります．

思考停止で配列の中身を上書きしてはいけません．
スクリプト言語を使っている場合でも，配列を扱う時ぐらいはメモリを意識するようにしましょう．

ちなみに私はこの方法で実験で集めるはずだったデータを闇に葬りました（泣）（アホ）
libeventの開発版の2.1.xでのopensslとの連携での安定版(2.0.x)との非互換問題かも

```c
bufferevent_socket_new
```
その後

```c
bufferevent_openssl_filter_new
```

でopensslと連携させようとしたら、その後、意図したソケットの送受信のイベントで、
コールバックが呼ばれなかった。

```c
bufferevent_openssl_socket_new
```

で生成時にopensslと連携したAPIを使ったら、意図したソケットの送受信の
イベントが受け取れた。

# まとめ

バージョン違うんだから非互換性問題ってわけじゃないかもだが、
2.1系でも割とそのまま2.0のコードが動く感じだったので、この違いは結構
大きいかなといった感想を持った。

# 関連記事

- [Windows 10でMSVCでnghttp2のサンプルを動かす](http://abrakatabura.hatenablog.com/entry/2017/01/14/072846)
jQuery UIの自分用メモ(v1.12.1)

# Autocomplete Widget
自動入力補完用のライブラリです。
https://jqueryui.com/autocomplete/


## 補完リストの全項目を表示したい
デフォルトでは1文字以上入力しないと、補完リストは表示されません。
全ての項目を表示したいときは、`minLength`の値を`0`にします。

```js
$( ".selector" ).autocomplete({
  minLength: 0
});
```

## 補完リストにスクロールバーを付けたい

`ui-autocomplete`クラスにスクロールバーのスタイルを設定します。
https://jqueryui.com/resources/demos/autocomplete/maxheight.html

```css
  .ui-autocomplete {
    max-height: 100px;
    overflow-y: auto;
  }
  ```
  
## 補完リストを上方向に表示したい
`position`オプションを使います。

  ```js
  $( ".selector" ).autocomplete({
  position: { my : "lef bottom", at: "left top" }
});
```
意味は、「一覧要素の左側・下側を、input要素の左側・上側に合わせる」です。


## 項目数が多いときのみ、補完リストを上方向に表示したい
`position`オプションの`collision `を指定します。

  ```js
  $( ".selector" ).autocomplete({
  position: { collision : "flip" }
});
```

"flip"の意味は、下記の通りです。
http://js.studio-kingdom.com/jqueryui/method_overrides/position
>ターゲットの反対側に要素を配置します。 より多く要素部分が表示される側に配置されます。




# Slider Widget

## changeイベントとsliderイベントの違い


* changeイベント
    - スライダーからフォーカスアウトしたときにイベント発生
    - `value`メソッドでを使ってvalueの値が変わったときも、イベント発生
* sliderイベント
    - マウスを動かすごとにイベント発生

## スライダーハンドルにIDを付ける方法

スライダーハンドルは、`slider`メソッドを呼び出したときに生成されます。

スライダー要素の中に`ui-slider-handle`クラスを持つ要素を配置して、`slider`メソッドを実行すれば、その要素がスライダーハンドルになります。
`ui-slider-handle`クラスを持つ要素に、IDも付与すればOKです。
また、span要素でなくdiv要素も使えます。

```html
<div id="slider">
  <span id="min-handle"  class="ui-slider-handle" ></span>
  <span id="max-handle" class="ui-slider-handle" ></span>
</div>
```

```js
$( "#slider" ).slider({
  range: true,
  min: 0,
  max: 500,
  values: [ 75, 300 ]
});
```

https://jqueryui.com/slider/#custom-handle


# Selectable

## 要素が多いと初期処理に時間がかかる
100行20列のtable要素にSelectableを設定したときの初期処理を計測しました。

|  Browser  | filter指定 | 初期処理時間[sec] |
|:---------:|:----------:|------------------:|
|    IE11   |    なし    |               1.7 |
|    IE11   |    "tr"    |               0.1 |
| Firefox56 |    "tr"    |              0.03 |

以下、測定条件です。

* 100行20列のtable要素
* IE11(11.608.15063.0)
* Firefox 56.0

```html
	<div id="wrapper">
		<table id="selectable"></table>
	</div>
```

```js
//table生成
	let tableElm = document.getElementById("selectable");
	for (let i = 0; i < 100; i++) {
		let rowElm = document.createElement("tr");
		for (let j = 0; j < 20; j++) {
			let cellElm = document.createElement("td");
			cellElm.textContent = i + "-" + j;
			rowElm.appendChild(cellElm);
		}
		tableElm.appendChild(rowElm);
	}

// 	jQuery Selectableを有効にする
	console.time('selectable');
    $( "#selectable" ).selectable({
		filter:"tr"
	});
	console.timeEnd('selectable');
```

計測した結果です。

* fitlerを使うと、処理が速くなる。
* IE11よりFirefoxの方が速い。


## td要素の中にa要素がある場合
デフォルト設定だと、リンクを選択できません。
`cancel`オプションに`a`要素を指定すれば、リンクを選択できます。

http://api.jqueryui.com/selectable/#option-classes 参照
slack入門 ~登録編~


## 登録

1.各チームの指示に従ってアドレスを教えてもらってください。


2.メールアドレスの登録
![スクリーンショット 2017-01-22 21.56.52.png](https://qiita-image-store.s3.amazonaws.com/0/95873/6d105414-e4c5-95b6-e81e-ab5b71a4b85b.png "スクリーンショット 2017-01-22 21.56.52.png")

リンクをクリックすると上記のような画面に移動します。
左側にある入力フォームにご自身が普段利用しているメールアドレスを入力してください。

入力が完了したら「Verify email」を押してください。


3.確認画面

ステップ2がうまくいっていれば下記のような画面になります。

![スクリーンショット 2017-01-22 21.57.42.png](https://qiita-image-store.s3.amazonaws.com/0/95873/af812db5-841c-f6a3-db0f-b2f82f4b3115.png "スクリーンショット 2017-01-22 21.57.42.png")

上記画面を確認後、登録したメールを確認してください。
下記のようなメールが届いているはずです。

![スクリーンショット 2017-01-22 21.59.14.png](https://qiita-image-store.s3.amazonaws.com/0/95873/f23a2dec-435b-0fe7-2e5a-1b6a2608cdfc.png "スクリーンショット 2017-01-22 21.59.14.png")

中身はこのような感じです。

![スクリーンショット 2017-01-22 21.59.37.png](https://qiita-image-store.s3.amazonaws.com/0/95873/123fafaf-3cd8-fdec-dc16-2c53e79d3306.png "スクリーンショット 2017-01-22 21.59.37.png")

メールに記載されている「Confirm Email」をクリックしてください。


4.ユーザー登録

「Confirm Email」をクリックすると下記の画面に移動します。
移動後は、「Your name」、「Username」に必要事項を入力してください。
※Usernameはニックネームのようなイメージです。

![スクリーンショット 2017-01-22 22.01.24.png](https://qiita-image-store.s3.amazonaws.com/0/95873/4927254b-eec0-2b41-e870-940c481435cc.png "スクリーンショット 2017-01-22 22.01.24.png")

項目入力後、「Next」を押してください。


5.パスワードの登録

![パスワード画面キャプチャ.png](https://qiita-image-store.s3.amazonaws.com/0/95873/9fbbd455-f536-4add-8cae-5fad4a2e3119.png "パスワード画面キャプチャ.png")

>Passwords must be at least 6 characters long, and can't be things like password, 123456 or abcdef.

最低でも6文字以上、英数字を使ってください。

PWの登録画面が出るのでPWを入力してください。


5.確認ステップ

英語ですが内容を確認後、「I Agree」を押してください。

![スクリーンショット 2017-01-22 22.03.56.png](https://qiita-image-store.s3.amazonaws.com/0/95873/c9682c81-0f75-6065-ece3-f8f8bd26a6cf.png "スクリーンショット 2017-01-22 22.03.56.png")


6.登録完了

これでslackの登録が完了です。
「Explore Slack」をクリックしてください。

![スクリーンショット 2017-01-22 22.04.34.png](https://qiita-image-store.s3.amazonaws.com/0/95873/b193bcbc-6863-cc01-6399-bdb93bace783.png "スクリーンショット 2017-01-22 22.04.34.png")


7.Welcomeページ

slackのチュートリアルを受けることができます。

![スクリーンショット 2017-01-22 22.04.50.png](https://qiita-image-store.s3.amazonaws.com/0/95873/ab4ce9fa-8fb0-997b-1ef9-9e357dead903.png "スクリーンショット 2017-01-22 22.04.50.png")

チュートリアルを受けない場合は「Skip the tutorial」をクリックしてください。


8.slackへようこそ

![スクリーンショット 2017-01-22 22.05.26.png](https://qiita-image-store.s3.amazonaws.com/0/95873/3291fbfd-a94d-adda-c2de-fad455e0c021.png "スクリーンショット 2017-01-22 22.05.26.png")

##こちらもどうぞ
[新人の指導者 or 新人の方へ](http://qiita.com/y_sekitoba/private/89e421c5e2b28dfe5dfb)
ggplot2で分割したグラフ毎に異なるtableGrobを書き込む

あまり上手くできていない。

# 使用するデータ

mpgをdisplとhwyの関係をdrv毎にプロットする。

```r
p <- ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  facet_wrap(~drv) +
  theme_bw() +
  theme(panel.grid = element_blank()) +
  geom_smooth(method = "lm")
```

# tableGrobを作成する

drvで分割して回帰して切片と傾きを取り出してデータフレームにしてtableGrobを作成する。

```r
tpar = list(bg_params = list(fill = "gray", alpha = 0.8)) # 表の外観パラメータ
tg <- mpg %>%
  split(.$drv) %>%
  purrr::map(., ~ (lm(hwy ~ displ, data = .) %>% broom::tidy())[1:2]) %>%
  purrr::map(., ~ data.frame(coef =  round(.[2], 1),
                             row.names = c("(Intercept)", "displ"))) %>%
  purrr::map(., tableGrob,
             theme = ttheme_minimal(
               base_size = 10,
               padding = unit(c(2, 2), "mm"),
               core = tpar,
               colhead = tpar,
               rowhead = tpar
             ))
```

# プロットする

```r
## gtableの作成
g <- ggplot_gtable(ggplot_build(p))

## facetsの取得
facets <- grep("panel", g$layout$name)

## tableGrobを書き込む
g2 <- with(g$layout[facets, ],
           gtable_add_grob(g, tg,
                           t=t, l=l))
plot(g2)
```

![Rplot.png](https://qiita-image-store.s3.amazonaws.com/0/109348/f0eb671f-d34b-036f-b023-d78d22afa6fe.png)

位置の調整ができない…。

# 参考

- [r - Annotate specific area of ggplot2 facet backgrounds with images of a specified size - Stack Overflow](http://stackoverflow.com/questions/31987096/annotate-specific-area-of-ggplot2-facet-backgrounds-with-images-of-a-specified-s)
- [tidyverse脳になって階層構造のあるデータフレームを使いこなそう](https://suryu.me/post/r_advent_calendar_day3/)
Forgeの鉱石辞書を利用したレシピ追加

#概要

レシピの素材指定に鉱石辞書を使う方法の説明をします。

鉱石辞書自体は[こちらの記事](http://qiita.com/shift02/items/f05e67c3e65b880c11bc)で解説しています。



#コード

バニラのレシピと同じように、鉱石辞書利用レシピにも定形レシピと不定形レシピがあります。

それぞれ、```ShapedOreRecipe```クラスと```ShapelessOreRecipe```クラスを利用します。

基本的にはItemやBlockのインスタンスを指定していた箇所を、鉱石辞書に登録した文字列に変更するだけです。

##定形レシピ

CraftManagerにShapedOreRecipeのインスタンスを登録します。

```java

CraftingManager.getInstance().addRecipe(new ShapedOreRecipe(new ItemStack(Blocks.PLANKS, 1),
                new Object[] {
                        "xxx", "xxx", "xxx",
                        'x', "stickWood"
                }));

```

このコードでは木の棒を3*3に並べると木材になるレシピを追加しています。

木の棒の指定が```"stickWood"```で、鉱石辞書に登録した文字列になっているので、
バニラ＋Modで追加された全ての木の棒を素材にすることが出来ます。

##不定形レシピ

CraftManagerにShapelessOreRecipeのインスタンスを登録します。

```java

CraftingManager.getInstance().addRecipe(new ShapelessOreRecipe(new ItemStack(Items.DIAMOND, 1),
                new Object[] {
                        "paper"
                }));

```

このコードでは紙をダイアモンドにクラフトするレシピを追加しています。
Grandstream HT-503でアナログ回線をAsteriskに収容する

Grandstream HT-503を利用し、アナログ回線をAsteriskに収容する方法を紹介します。

# 前提環境

* Grandstream HT-503 1.0.15.5
* Asterisk 11.25.1

# HT-503の設定

普通に使うところは割愛して、たぶん肝となる設定は次の部分

### Basic Settings / Unconditional Call Forward to VOIP

FXO側から着信があった際に、SIPサーバのどのユーザにINVITEを投げるか(Portが5061なのはTLSを利用しているからです)
後で出てくる、extensions.confと合わせます。
![CallFwdVoip.png](https://qiita-image-store.s3.amazonaws.com/0/25028/7c999cc8-058e-ad38-9953-3fd0feac2edd.png)

### Advanced Settings / Call Progress Tone

![Tone.png](https://qiita-image-store.s3.amazonaws.com/0/25028/570bb4ec-796a-5c0d-1711-ce0ef675d09d.png)

### Advanced Settings / FXO Port / Caller ID

ナンバーディスプレイ使っている場合は設定必要
![CID.png](https://qiita-image-store.s3.amazonaws.com/0/25028/cab83c6b-06e6-47a1-a4d7-183e192068e1.png)

### Advanced Settings / FXO Port / Caller ID Transport Type

~~Caller IDをFromヘッダーにマッピングすると、同じIPアドレスからRegistしてる
別のSIP端末と間違って認識するっぽい(？)からPPIで渡すようにしています。(どっか別の設定がおかしい気もするけど。)~~
**2018/8/10 追記**：Asteriskのsip.confで「match_auth_username=yes」を追加すると、
標準のRelay via SIP Fromでも上記問題が発生しません。

![CidTransport.png](https://qiita-image-store.s3.amazonaws.com/0/25028/667307ef-e666-c537-ed17-248410d6c96a.png)

### Advanced Settings / FXO Termination / Channel Dialing

いろいろ触ってどれが原因か微妙だけど、FXOから抜けるのに苦労して、
Wait for Dial-ToneとStage Method (1/2): が怪しい気がする。

![FXO.png](https://qiita-image-store.s3.amazonaws.com/0/25028/1c405518-0b62-44a9-7a11-3e9fb8582bd3.png)

### FXO Port / SRTP Mode

手元の環境では、RTPもSRTPで暗号化しているため、「SRTP Mode」を「Enabled and forced」にしています。
Asterisk側のsip.confの「encryption=yes」と合わせます。

# Asterisk側

Asterisk側は別に普通で、こんな感じ

### sip.conf

```
[general]
match_auth_username=yes

[ht503_fxo]
context=ht503demo
fromdomain=voip.example.com
disallow=all
allow=ulaw
allow=gsm
type=peer
insecure=invite,port
host=dynamic
transport=tls
encryption=yes
directmedia=no
nat=force_rport,comedia
qualify=5000
secret=foobar
```

###extensions.conf

```
exten => 054xxxxxxx,1,NoOp(${CALLERID(num)})
exten => 054xxxxxxx,n,Dial(SIP/client11)
exten => _0.,1,Dial(SIP/${EXTEN}@ht503_fxo)
```
Dell XPS15 9550 に Ubuntu を入れる

* そろそろMacもオワコン感
* かと言ってWindowsは未だゴミ
* ヤッパ ウブンチュ ジャネッスカ

# なぜこの組み合せ

* XPS15 9550
    * MacbookPro15と比較対象にできる世界で唯一のPC
        * タッチバーに絶望したマカーの移行先として究極
    * 米国流質実剛健を体現したハード
* Ubuntu
    * OSインスーラーが優秀で、だいたいデバイスドライバを入れ尽くしてくれる
    * わたしは Ubuntu GNOME を。HiDPIの扱いが安定してる感があった

# 用意するもの

* XPS15(9550)
    * http://www.dell.com/jp/p/xps-15-9550-laptop/pd
    * https://www.amazon.co.jp/dp/B01G3EQZF0
* USBメモリ16GB x 2

# Ubuntuインストールまで

* 回復ドライブの作成
    * Windowsのコンパネで「回復ドライブの作成」を検索、実行
* UbuntuインストールUSB作成
    * インストールしたいUbuntuフレーバーのISOファイルを入手
    * どうにかしてISOファイルをUSBメモリに書き込む
* BIOS設定の調整
    * 電源ON後、F2キー連打で、BIOS画面
        * Fastbootをminimumに変更
            * これはもしや不要だったかも？
        * SATAをRAIDからAHCIに変更
        * SecurebootをEnableからDisableに変更
* Windows再インストール
    * SATA設定を変更したことで、Windowsが起動しなくなる
    * 回復ドライブを挿して起動
    * ウィザードに従って再インストール
* パーティション分割
    * Cドライブ以外は絶対触るな
    * Windowsで、MiniTool Partition Wizard で、Cドライブを分割
        * http://forest.watch.impress.co.jp/library/software/partwizhome/
        * Cドライブになってるパーティションだけ、Resizeでサイズ変更
            * Cドライブが460GBくらいある。Cドライブ100GB、Linux用に360GBで分割した
                * 配分はお好みで
* Ubuntuインストーラーの起動
    * BIOS設定の調整
        * 電源ON後、F2キー連打で、BIOS画面
            * Boot Sequens を、「UEFI」から「Legacy」に変更
            * USBメモリがSSDより先に読まれるように並ベ替え
        * BIOS設定を保存して再起動
    * UbuntuのUSBメモリを挿して起動
    * しばらくすると起動するので、Ubuntuインストール
        * ブートローダーはSSDのトップレベルにインストール(nvme0n1)すること

# Ubuntuインストール後の設定

* ansibleを使って、カスタマイズ適用を自動化
    * https://github.com/sasasin/dotfiles/tree/master/linux/ansible
    * デフォルト構成の一部分は、微調整しないとダルい
        * GPU。Nvidiaに変更。明らかにサクサクになる。
        * サスペンド設定。なんかいろいろ不具合がある。
        * 省電力設定。やらないよりマシだけど、その程度。
        * IME。fcitxに変更。
        * 参考にしたサイト
            * http://qiita.com/NewGyu/items/d25cda12e0e1c5259121
            * https://ubuntuforums.org/showthread.php?t=2317843
            * https://booleestreet.net/archives/10321
* Ubuntu Gnomeなので、Gnome shell extentions。なんかコマンドラインで入らないのかこれ....
    * https://extensions.gnome.org/extension/495/topicons/
        * 奇怪にも左下にワサワサ出てくるのを、画面右上のツールバーに統合してくれる
    * https://extensions.gnome.org/extension/261/kimpanel/
        * IMEの変換候補を、Gnomeに馴染む感じにしてくれる
    * https://extensions.gnome.org/extension/1065/docker-status/
    * https://extensions.gnome.org/extension/1055/docker-integration/
    * https://extensions.gnome.org/extension/657/shelltile/
    * https://extensions.gnome.org/extension/15/alternatetab/
* 諸々やって、再起動すると、設定反映される

# 起動するOSの選択

*  Ubuntuの起動
    * BIOSに入って、起動を「UEFI」から「Legacy」に変更して再起動。
* Windowsの起動
    * BIOSに入って、起動を「Legacy」から「UEFI」に変更して、再起動。

# ここまで終えて

* 問題なし
    * Wifi
    * ディスプレイ
        * タッチパネル
        * 4k表示
        * HiDPI表示
    * Nvidia GPU
    * サスペンド
    * タッチパッド
    * USB, HDMIなど外部接続
* 動かねえ
    * Bluetooth
* まいっか
    * UbuntuをUEFIブート
        * なぜMBRに...
        * BIOSで変更する謎運用でカバーだけど、まいっか
(C#)Listで要素を検索し取得する

#### やりたかったこと
データをリスト形式で入れ込んだ後に、プロパティ項目に対応する要素を抽出する。 
#### やったこと
[List.Findメソッド](https://msdn.microsoft.com/ja-jp/library/x0b5b5bc(v=vs.110).aspx) で対応しました。
#### 前提
以下のようなプロパティを持つクラスを作成します。

```csharp
public class City
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Path { get; set; }
}
```

### 使い方
id が 0 リストの path を取得したいと思います。

```csharp
// 1. List作成
List<City> cityList = new List<City>
{
    new City { Id = 0, Name = "tokyo", Path = "./path/tokyo" },
    new City { Id = 1, Name = "osaka", Path = "./path/osaka" }
};

// 2. Findで取得
string filepath = cityList.Find(x => x.Id == 0).Path;

// 表示確認
Console.WriteLine(filepath);
// ./path/tokyo と表示されます
```
### 説明
1. List作成  
プロパティに対応させて値を入れ込みたいので、  
クラスの型でリストを作成し、配列にクラスインスタンスを追加しています。
2. Findで取得  
Findは最初に合致した要素のみを返すので、  
(x => x.id == 0) で  `id` の値を指定して、  
最初に合致した `id`  を含む要素を抽出します。  
この条件取得のやり方はラムダ式という取得方法のようです。  
今回取得したい要素は `path` なので、末尾に`.path` を付け取得します。

### 宿題
ラムダ式について理解できていないので調査します。
### 参考にさせていただいたサイト

[C# List<T> 任意の項目を削除・抽出・変換する](http://programmers.high-way.info/cs/list-remove.html)

### 変更履歴
* 20170123 「2.Findで取得」 部分にてFindの説明が誤っていたため修正しました。
* 20170131 コード内の「1.List作成」部分にてプロパティと対応して、データを入れ込む処理に修正しました。
* 20200419 記載しているコードが正常に動作しなかったため、ソース内容を変更しました。