OmniAICreator/Qiita-1.07M huggingface dataset:
GitコミットメッセージにMarkdownを使えるようにする

* __要約__
    * Markdownの`#`がGitコミットメッセージではコメントと解釈される。
    * Gitの設定を変えてコメントを`#`以外の文字にする。[やり方]
    * Markdownが問題なくコミットログに入るようになる。

[やり方]: #git%E3%81%AE%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%82%92%E4%BB%A5%E5%A4%96%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B

## GitとMarkdownで`#`の役割が異なる

* Gitのコミットメッセージはコメント行 (つまりコミットログに残らない)
* Markdownで見出し

つまり、下のMarkdown風コミットメッセージは見出し行がコメントとして解釈される。

```bash
バグ修正

## 再現手順

あれしてこれしてこうする

## 期待の振る舞い

こうなる

## 実際の振る舞い

そうならない

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
```

このままコミットすると、見出しだけが抜けたログができあがる。

```
❯ git show
commit d8ed4ccf8095b83310ba7924c27b02d9185a251b
Author: suin <suinyeze@gmail.com>
Date:   Fri Feb 2 13:42:14 2018 +0900

    バグ修正

    あれしてこれしてこうする

    こうなる

    そうならない
```

## Gitのコメントを`#`以外に設定する

`core.commentchar`にコメント記号にしたい文字を指定できる。

```
git config --global core.commentchar ';'
```

* 注意点
    * 文字は1文字でなければならない。 `//`などはNG
    * おそらくマルチバイト文字は正しく解釈されない。
    * コミットメッセージにソースコードを書くことを想定した、コメント扱いされないよう記号選び
        * 例えば、`$`はPHPでは行頭に来やすいが、`$`をコメントにしてしまうとコミットメッセージからPHPスニペットが消えることが考えられる。
AR.js で毎回忘却のかなたにいってしまうTipsメモ

# AR.jsって？

https://github.com/jeromeetienne/AR.js/blob/master/README.md
こちらです。ブラウザだけで AR を実現してしまうすごいやつです。
ARマーカーが``Hiro``だったり``人``だったりするところに日本人としては親しみを覚えます。

良記事がたくさんあるのでAR.js自体の説明は省略して、毎回毎回調べたり考えたりすることを書いておきます。
気が向いたときにアップデートします。

## さっそくTips
### 座標系は？
**ARマーカー**（Hiroとか人とか）を世界の中心（地面）とした**右手座標系**です。
ARマーカーを机の上におくなら``Y``が上方向。 ARマーカーをPCモニタや壁やポスターなど垂直にうつすのなら``Y``が手前方向で``-Z``が上方向です。

![01.jpg](https://qiita-image-store.s3.amazonaws.com/0/33095/1b4f2c9b-d9f4-e313-9c3a-bfe5f5a54b52.jpeg)　![02.jpg](https://qiita-image-store.s3.amazonaws.com/0/33095/e7a85549-fac0-5ecf-2c0b-391a8b257708.jpeg)

右手座標系では、親指を 軸の+方向 に向けたときに残りの指が向く方向が+の回転方向です。 ARマーカーを壁やポスターなどにした場合には X軸 方向に -90度 の回転をかけることで正しい方向に向かいます。

### 長さの単位は？大きさは？
**ARマーカー** の1辺が **1** になります。
なので ``<a-sphere radius="0.5">`` で、半径 0.5 ＝ 直径 1.0 で、ちょうどマーカーと同じサイズの球が表示されます。
この時に、ARマーカーが 10cm x 10cm だったら10cmのボールが表示されることになります。 ARマーカーが 5cm x 5cm だったら5cmのボールが表示されることになります。

> e.g.
> ARマーカーを 5cm x 5cm で印刷
> 野球ボール（約直径7cm）を正しいサイズで出したければ、実寸で半径3.5cmなので、AR.js座標系にするため、3.5 / 5 で ``<a-sphere radius="0.7">`` の球体を表示するとよいことになります

### マーカーの上にちょうどよく立方体をのせるには？
``AR.js``というか``a-frame``はデフォルトだとオブジェクトの中心が座標の中心になるので、1 x 1 x 1 の立方体の場合には、中心から 0.5 ずつまわりに広がってることになります。
なので、マーカーの上に立方体をのせるためには、0.5 分だけ上にずらす必要があります。

![04.jpg](https://qiita-image-store.s3.amazonaws.com/0/33095/6d0ecb96-af7b-2d38-9127-7d75b4db9c24.jpeg)
FirebaseのDynamic Linksのデバッグ方法メモ

実機でのデバッグ方法に悩んでいたが下記にて出来るらしいのでメモ。

1. アプリをアンインストールする
2. App Storeを開くURLを開く
3. Xcodeで実機にアプリをインストールする

参考）
https://stackoverflow.com/questions/39107766/firebase-dynamic-deep-link-arrives-nil-after-install?rq=1
.getAttribute('href')と.hrefの違い  

a要素に対し element.getAttribute('href')すると属性値がそのまま、element.hrefには絶対URIが入る。

```html:HTML
<a href="../test.html" id="link">link</a>
```

```JavaScript:JavaScript
var link = document.getElementById('link');
console.log("link.getAttribute('href') --> " + link.getAttribute('href'));
console.log("link.href                 --> " + link.href);
```

```:CODEPEN上での実行結果
link.getAttribute('href') --> ../test.html
link.href                 --> http://s.codepen.io/boomerang/test.html
```

[CODEPENで見る](https://codepen.io/anchoor/pen/oYmzMq/?editors=1011)

##参考サイト

* [element.getAttribute - Web API インターフェイス | MDN](https://developer.mozilla.org/ja/docs/Web/API/Element/getAttribute)
* [Document Object Model HTML > Interface HTMLAnchorElement](https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-48250443) 

  > <dl><dt><a>href</a> of type DOMString</dt>
  > <dd>The absolute URI [IETF RFC 2396] of the linked resource.</dd></dl>
MNISTの生データとTensorflowのデータ

MNISTの生データを読み込むと5, 0, 4, 1...といった順に数字が読み込まれるはずである。

しかし、Tensorflowの```mnist.train.images```で見てみると、7, 4, 5...といった順に並ぶ。

あれ？なんかおかしいぞ。画像の順列が違う・・・。
これは6万枚あるTrainingデータの最初の5000枚をValidationデータ
としてTensorflowが省いているからなのである。

そのため、```mnist.train.images```は5.5万枚しかない。

画像の順列を合わせたい場合はoffsetとして+5000すればよい。
Windows7だとVagrant+VirtualBoxを最新バージョンで利用できない！

# 概要
Windows7にVagrant+VirtualBoxで仮想環境を作ろうとすると、Vagrantのver.2以降がWindows7のPowerShellのバージョンに対応していないため動かないという問題があります。
PowerShellのバージョンを上げれば対応できますが、今回はPowerShellのバージョンを上げずにWindows7でも問題なく利用できる手順をまとめます。

# Vagrantをインストール
ver.1の中で最新である**ver.1.9.8**を入れる

下記から.msiファイルをダウンロードしてインストール
https://releases.hashicorp.com/vagrant/1.9.8/

# VirtualBoxをインストール
ver.5.2以降はインストールしたVagrantが対応していないため、
ver.5.1の中で最新である**ver.5.1.32**を入れる

下記から5.1.32のWindows hostsをダウンロードしてインストール
https://www.virtualbox.org/wiki/Download_Old_Builds_5_1

# 仮想サーバー構築
今回はCentOS7.0のサーバーを構築する
### VM（バーチャルマシーン）の作成
好きな場所にディレクトリを作成
作成したディレクトリにコマンドプロンプトで移動し以下を実行
```$ vagrant box add CentOS7.0 https://github.com/tommy-muehle/puppet-vagrant-boxes/releases/download/1.1.0/centos-7.0-x86_64.box```
```$ vagrant init CentOS7.0```

### Vagrantfileの編集
ディレクトリ配下にVagrantfileが作成されるので、それをエディターなどで編集する

```
# config.vm.network "private_network", ip: "192.168.33.10"
　↓ コメントアウトの#を外してip番号を変える
config.vm.network "private_network", ip: "192.168.33.11"
```

### 仮想サーバーの立ち上げ
作成したディレクトリにコマンドプロンプトで移動し以下を実行
```$ vagrant up```

### 接続
TeraTermなどで

```
ホスト：192.168.33.11
ポート：22
```
にSSH接続。

```
ユーザ名：vagrant
パスフレーズ：vagrant
```
で認証すれば接続完了。

### おまけ
Vagrantfileと同配下にvagrant_up.bat（ファイル名はなんでも良い）を作成し、中に```vagrant up```と書いておく。
このファイルをWindowsのファイル名を指定して実行に登録しておけば、ファイル名を指定して実行でvagrant_up.batを実行するだけで簡単に仮想環境を立ち上げてくれる。（vagrant haltも同様）
大学のサークルでのゲーム製作プロジェクトを完遂するにあたって良かった点と悪かった点

# はじめに
私は某大学のゲーム製作サークルに所属している修士2年の学生です。
今回1月末締め切りのゲームコンテストに無事ゲームを完成させて応募することができたので、今回のプロジェクトを終えてやって良かったと思うことと悪かったと思ったことをまとめました。
同じように大学のサークルというプロのノウハウを得難い環境でゲーム製作を頑張っている人に参考になればと思います。

# プロジェクト概要
## プロジェクト期間
2017年7月末　始動
2017年10月始め 中間成果物発表
2018年1月末　ゲーム完成
## メンバー
- 私: プロジェクトリーダ、プロジェクトマネージャ、ディレクター、プログラマー
- プログラマー1人
- グラフィッカー1人
- サウンドデザイナー1人

## 作ったゲーム
2Dの四人対戦アクションゲーム
(スマブラとかボンバーマンとかそのへんをイメージしてもらえれば)

# 良かった点
## プロジェクトマネージャがいたこと
プロマネがいることで全体の進捗の管理を行えます。誰が今何をしているのかを把握することでチーム全体の状況を俯瞰しできます。
あって当然の役職ではありますが、リーダーとはまた別の役割である、ということが重要です。
メンバーのケツを叩くのは基本プロマネの仕事。

## 締め切りが明確だったこと
今回のプロジェクトの大きな締め切りは10月と1月に二回ありました。
締め切りがないことはプロジェクトがエターナる原因になります。
一番わかりやすい締め切りを作るには、やはりコンテストが一番わかりやすくていいです。
締め切りがないプロジェクトはプロジェクトではありません。

## プログラマが二人いたこと
プロジェクト立ち上げ直後のゲームのプロトタイプ作成の際はプログラマが複数いても暇人が出ます。
しかしプログラマ二人体制が真価を発揮するのは締め切り間際です。二人が並行して開発することで片方が詰まってもプロジェクトにデッドロックが起きません。
当然、二人が効率よく分担作業ができる前提です。

## メンバーが全員楽しめるゲームを作っていたこと
もともと全員でこういうゲームにしたい、という思いでプロジェクトを始めました。
ディレクターやプランナーだけの思いが強すぎて、メンバーがついてこない、なんてことはよくあります。
プロジェクトのモチベーションに関わるのでとても大事です。

## 苦痛な作業をなるべく少なくしたこと
ゲーム製作の際には作るジャンルにもよりますが、苦痛な単純作業はつきものです。
私はモチベーションの上がる作業(新キャラの追加・新ルールの導入など)を定期的に差し込んで、開発のモチベーションを維持しました。
どうしても単純作業が必要な時は、なるべくリーダーがやりましょう。

## 顔を合わせて作業を行ったこと
製作会を多く開いてとにかくプログラマとディレクターが顔を合わせて製作する機会を作りました。
メンバー同士が同じ空間にいると進捗が湯水のごとく生まれます。
また製作会をしていると、プログラマの作業中はどうしてもディレクターは暇になったりしますが、その間はむしろゲームについて深く考えられる時間が増えるのだとプラスに捉えましょう。

## デバッグをめちゃくちゃやったこと
サークルというコミュニティを最大限生かしていろんな人に遊んでもらいました。
4人対戦ゲームという特性上、デバッグの協力者を集めるのは大変でしたが、そこは頑張りました。
またサークル外の知人にも協力してもらって、なるべく多くの人にデバッグしてもらいました。これは初見プレイの意見をたくさん聴くためです。そのゲームに慣れた人の意見はどうしても偏ってしまうので初プレイの感想はとても重要です。

## 作業効率が良くなるツールをちゃんと使ったこと
開発のノウハウがないと、ツールの知識が入ってこないことがあります。
これは少し調べればたくさん出てくるので、プロジェクトリーダーは調べてみましょう。
大切なのはツールに振り回されないことです。必要なツールをしっかり取捨選択して、開発の効率を上げましょう。
今回私のプロジェクトで用いたのは以下のツールです。導入コストの少ないもの必要最小限で済ませました。
- git: バージョン管理、ソースコード共有
- slack: 連絡ツール
- trello: タスク管理ツール


# 悪かった点
## 連絡がなかなかとれないメンバーがいた
連絡手段を統一していたにもかかわらず、チェックしてないメンバーがいたため、連絡が取れないことがありました。この原因はマネージャが徹底できなかったことが一つと、普段使わないツールを連絡手段に用いたことが一つです。
プロジェクトの最初に、メンバー全員が必ずチェックできる連絡手段を選び、使わせましょう。

## コスパの悪い作業をさせていた時があった
欲しい機能だったのですが、実装に時間がかかる&バグが多く含まれそうな機能を実装させていました。
結局スケジュールに間に合いそうになかったので、この機能は見送ることにしました。
単純に時間がもったいなかったです。プログラマと相談して初めにしっかりどのくらい実装にかかるか見積もりましょう。

# さいごに
すべてのゲーム製作をしている学生へ
大人にとやかく言われず好きなゲームを作れるのは今だけかもしれません。
ゲームを完成させることは大事なことですが、なによりそのゲーム製作自体を楽しんでください。
すでに入力されたフォームに対してVue.jsを使う

バリデーションエラーなどで
フォーム入力画面に戻ってきた時など

```javascript
var data = (function() {
  var $ = function(value) {
    return document.querySelectorAll(value);
  };
  var data = {};

  var inputsSelector = ["text", "date", "email", "color", "month", "number", "search:", "tel", "time", "rul", "week"]
    .map(function(item) {
      return 'input[type="' + item + '"][name]';
    })
    .join(", ");
  var inputs = $(inputsSelector);
  [].forEach.call(inputs, function(input) {
    var result = input.getAttribute("name").match(/\[(\d*)\]$/);
    var name = input.getAttribute("name").replace(/\[\d*\]$/, "");
    var value = input.getAttribute("value");
    var index;
    if (result !== null) {
      index = result[1];
      if (!Array.isArray(data[name])) {
        data[name] = [];
      }
      data[name][index] = value;
    } else {
      data[name] = value;
    }
    input.removeAttribute("value");
  });

  var textareas = $("textarea[name]");
  [].forEach.call(textareas, function(textarea) {
    var name = textarea.getAttribute("name");
    var value = textarea.value;
    data[name] = value;
    textarea.value = "";
    textarea.innerHTML = "";
  });

  var checkboxs = $('input[type="checkbox"][name]');
  [].forEach.call(checkboxs, function(checkbox) {
    var name = checkbox.getAttribute("name").replace(/\[\d*\]$/, "");
    var isChecked = checkbox.hasAttribute("checked");
    if (!Array.isArray(data[name])) {
      data[name] = [];
    }
    if (isChecked) {
      data[name].push(checkbox.getAttribute("value"));
      checkbox.removeAttribute("checked");
    }
  });

  var radios = $('input[type="radio"][name]');
  [].forEach.call(radios, function(radio) {
    var name = radio.getAttribute("name");
    var isChecked = radio.hasAttribute("checked");
    if (!data.hasOwnProperty(name)) {
      data[name] = null;
    }
    if (isChecked) {
      data[name] = radio.getAttribute("value");
      radio.removeAttribute("checked");
    }
  });

  var selects = $("select[name]:not([multiple])");
  [].forEach.call(selects, function(select) {
    var name = select.getAttribute("name");
    var option = select.querySelectorAll("option[selected]");
    var isSelected = option.length > 0;
    if (!data.hasOwnProperty(name)) {
      data[name] = null;
    }
    if (isSelected) {
      data[name] = option[0].getAttribute("value");
      option[0].removeAttribute("selected");
    }
  });

  return JSON.parse(JSON.stringify(data));
})();

var vm = new Vue({
  el: "#form",
  data: data
});
```
【JavaScript】インクリメンタルサーチの実装（要jQuery）

インクリメンタルサーチの実装する必要があったので書いた。
APIに問い合わせる感じのやつです。

# 動き
検索欄にキーワードを入力すると、非同期でキーワードをGET送信する。
送信したキーワードに対して前方一致する検索結果がある場合、取得してフォームの下に表示する。

# インクリメンタルサーチ

```IncrementalSearchFormSample.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>IncrementalSearchFormSample</title>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
        <script type="text/javascript">
        $(function () {
            var keyupStack = [];
            $('#search').on('keyup', function () {

                keyupStack.push(1); //配列の後ろに追加

                // 指定時間後に処理を実行させる
                setTimeout(function () {

                    keyupStack.pop(); //配列の中身排出

                    // 最後にkeyupされてから次の入力がなかった場合
                    if (keyupStack.length === 0) {

                        $.ajax({
                            type: "GET",
                            url: "/apiurl",
                            data: {keyword : $('#search').val()} , // キーワードを送信してデータを検索してにいく
                        }).done(function(data) {

                            // 取得したデータを処理する（ここではjsonを受け取る想定）
                            var test_len = Object.keys(data["test"]).length;
                            for(var i = 0; i < test_len; i++){
                                $("#test").append("<li>" + data["test"][i]["name"] + "</li>");
                            }

                        }).fail(function(data) {
                            alert('failed!');
                        });

                    }
                }.bind(this), 500); // 0.5秒設定

            });

        });
        </script>
    </head>
    <body>
        検索欄：<input type="text" name="keyword" id="search">
        <ul id="test"></ul>
    </body>
</html>
```

jQuery依存症から抜け出せない


# 参考
- [ライブラリを使わずJavaScriptでインクリメンタルサーチを実装する | Black Everyday Company](https://kuroeveryday.blogspot.jp/2016/03/incremental-search.html)
stringr::str_replace_allについてのメモ

ちょっとちゃんとした文章にする余裕がなかったのでメモだけ。詳しくは`?stringr::str_replace_all`のExampleを参照してください。


```r
library(tidyverse)

# サンプルデータ
xlist <- c(100, 500, 1000, 2000, 5000)
n <- 20
df <- data.frame(
  id = 1:n,
  x = sample(xlist, n, replace = TRUE)
)

# 変換(というか生成したい)ラベルベクトル作成
xlabel <- paste("x", 1:length(xlist), sep = "_")

# 今回の場合，名前付きベクトルでは無理なのでstr_replace_allのpatternを合成して適用
# 正規表現のマッチングパターンベクトル作成
pattern <- str_c("^", xlist, "$", collapse = "|")

# xの値から対応するxのラベルをmutateする
df2 <- df %>% 
  mutate(label = str_replace_all(x, pattern, xlabel))
head(df2, 8)
#>    id    x label
#>  1  1 5000   x_1
#>  2  2 2000   x_2
#>  3  3 5000   x_3
#>  4  4 2000   x_4
#>  5  5  500   x_5
#>  6  6 2000   x_1
#>  7  7  500   x_2
#>  8  8 5000   x_3

# 名前付きベクトルはこういう時に
# nameは商品A:Eとする
xname <- paste0("商品", LETTERS[1:5])
names(xname) <- xlabel

# labelの文字列からxnameという名前付きベクトルを利用してnameという変数を生成
# 名前付きベクトルでの置換は，patternがnames，replacementがベクトルの値とする
df3 <- df2 %>% 
  mutate(name = str_replace_all(label, xname))
head(df3, 8)
#>    id    x label  name
#>  1  1 5000   x_1 商品A
#>  2  2 2000   x_2 商品B
#>  3  3 5000   x_3 商品C
#>  4  4 2000   x_4 商品D
#>  5  5  500   x_5 商品E
#>  6  6 2000   x_1 商品A
#>  7  7  500   x_2 商品B
#>  8  8 5000   x_3 商品C
```
ssh経由でリモートサーバーのディレクトリをマウントする （CentOS6系想定）




#### インストール  
libfuse/sshfs を利用する
https://github.com/libfuse/sshfs

```bash
yum --enablerepo=epel -y install fuse-sshfs
```

#### マウント
```bash
#sshfs [user@]hostname:[directory] mountpoint

sshfs user@192.168.0.2:/home/data /mnt/data
```


#### 自動マウント /etc/fstab
```bash
user@192.168.0.2:/home/data /mnt/data fuse.sshfs _netdev 0 0

# _netdev （ネットワークが起動してから）
# CentOS７ systemd使う場合は下記オプション必要だと思う
# x-systemd.automount
```

#### アンマウント

```bash
fusermount -u /home/foo/mnt
```

  
  
　
　
Mac用などもあるので個人プロジェクトでssh経由でファイルやり取りが頻繁にあるようなら、利用時だけマウントしてローカルマシンからアクセスなども需要あるかな。
AWSのEC2とRDS(mysql)を他アカウントへ移行してみるテスト


# 方針
ちょっとだけサーバを止める
移行前=>VPC1 / AP1 / DB1
移行後=>VPC2 / AP2 / DB2
って名前にする
ロードバランサなどについては特に記述しない

##移行手順
- VPC2を作る
- VPC2とVPC1をピア接続する
- AP2を作る
- AP2からDB1へ接続する
- DNSサーバをAP1からAP2へ向き先を変える
- 浸透を待ち、AP1止める
- DB2を作る
- DB1からDB2へDBを移行(ダンプとかで)
- データ移行が終わった段階で、AP2を止める
- AP2の向き先をDB2へ変更
- DB2を親にする
- AP2を起動する
- (ﾟ∀ﾟ)


# 作成
## vpc2を作る
以降元とprivate-ipが被らないようにする

## ピア接続
こちらを参考に作成しました
https://dev.classmethod.jp/cloud/aws/vpc-peering-different-awsaccount/

+ vpc2からvpc1へピア接続を作る
+ vpc1のアカウントIDとvpc-idを設定する
+ vpc1アカウントのvpc=>ピア接続で、リクエストを承認する
+ vpc1とvpc2双方のルートテーブルへ、お互いのip範囲でターゲットなピア接続を追加

## EC2の移行
こちらを参考に作成しました
http://keisukeohta.hatenablog.com/entry/2016/03/01/210556

+ AP1のインスタンスからイメージを作る
+ AMIのイメージパーミッションの設定で移行先アカウントIDを追加する
+ 移行先アカウントのAMI=>プライベートイメージに共有されているので、それを使ってEC2を作成
+ ap2からdb1へピア接続出来ることを確認する
  => db1がパブリック接続許可の場合、パブリックIDで接続しに行ってしまうので、ローカルIDで接続する

# 以上
これで「AP2からDB1へ接続する」から先が作業可能となります
MacでスタイリッシュなER図を作成する(Oracle)

## 「Schema Spy」とは？

Java製のER図生成ツールです。
JDBCドライバを使うことで、OracleやSQL Server、MySQLやPostgreSQLなど様々なDBからER図を生成することができます。
ER図の他にテーブルや制約の定義などもセットで図化されます。

全体的にスタイリッシュなデザインなので、生成したあとはニヤニヤできます。

## 環境

- OS：macOS High Sierra 10.13.3
- Schema Spy：v6.0.0 RC2
- Java：Version 8 Update 161
- Graphviz：2.40.1
- DB：Oracle Database 10g Release 10.2.0.5.0 - 64bit Production

## セットアップ

### Schema Spyのダウンロード

以下のURLからダウンロードします。
https://github.com/schemaspy/schemaspy#schemaspy-v600-rc2

現行版の5.0.0はスタイリッシュではないので、SchemaSpy v6.0.0 RC2をダウンロードします。

### Java 8のインストール

Schema Spyの動作にはJavaが必要なので、インストールします。
すでにインストールしている場合は飛ばしてください。

以下のURLから[Mac OS X]をクリックし、インストーラをダウンロードします。
https://java.com/en/download/manual.jsp

.dmgファイルを実行してインストールします。

### Graphvizのインストール

「Graphviz」とは、dot言語というフォーマットで書かれたテキストファイルをグラフへ変換し、画像として出力するツールです。
Schema SpyではER図の出力に使用しています。

Macの場合、Homebrewからインストールします。

```bash
$ brew install graphviz --with-librsvg --with-pango
```

`brew install graphviz` のみだと生成時に「-Tcmapx' failed with return code 139」エラーが発生してER図が生成されません。
https://github.com/schemaspy/schemaspy/issues/33

### JDBCドライバのダウンロード

「JDBCドライバ」とは、JavaアプリからDBを操作するためのミドルウェアです。
「JDBC」は「Java Database Connectivity」の略です。

ベンダごとにドライバが異なり、通常は各ベンダから配布されています。
Oracleも公式サイトで配布しており、バージョンに応じたJDBCドライバをダウンロードします。
http://www.oracle.com/technetwork/jp/database/features/jdbc/index-099275-ja.html

私の場合、Oracleがインストールされている環境にJDBCドライバが含まれていたので、そちらを使用しました。

## テーブル定義・ER図の生成

ここまで来たら準備完了です。
以下のコマンドを実行すると、テーブル定義やER図が生成されます。
テーブルや列数によりますが、生成には数十秒～数分かかります。

```bash
# java -jar {schemaspy.jarのパス} -t {DBタイプ} -dp {JDBCドライバのパス} -db {DB名} -host {ホスト名} -port {ポート番号} [-s {スキーマ名}] -u {ユーザー名} [-p {パスワード}] -o {出力先パス} -gv {GraphVizのフォルダパス} -cat %
$ java -jar schemaspy-6.0.0-rc2.jar -t orathin -dp ./drivers/ojdbc14.jar -db testdb -host 192.168.10.1 -port 1521 -s TESTSCHEMA -u testuser -p testpass -o ./output -gv /usr/local/Cellar/graphviz/2.40.1 -cat %
```

DBタイプは「orathin」を指定します。
Oracleのポート番号は「1521」がデフォルトです。

Oracleの場合、スキーマ名を省略するとエラーになりました。
スキーマ名は大文字・小文字を区別するので注意してください。

`-cat %` を付けないと「ERROR - Catalog name can't be null」エラーが発生して生成できません。
https://github.com/schemaspy/schemaspy/issues/160

## テーブル定義・ER図の参照

テーブル定義などはHTML形式で出力されます。
出力先パスの直下にある「index.html」をWebブラウザで開くだけで参照できます。

## 参考リンク
- [SchemaSpy — SchemaSpy 6.0.0 documentation](http://schemaspy.readthedocs.io/en/latest/index.html)
Docker + Kubernetes. How a serverless platform is built on top of containers 

# Event Info

- https://events.docker.com/events/details/docker-san-francisco-presents-docker-kubernetes-how-a-serverless-platform-is-built-on-top-of-containers

# Talk.1 Docker + Kubernetes. How a serverless platform is built on top of containers

https://www.meetup.com/ja-JP/Docker-meetups/events/246946006/

## How a serverless platform is built on top of Containers

### The Internals of Open Source Fn Project

- About Fn project
 - https://github.com/fnproject
- Overview
 - FaaS
  - Container vs Function.
- What is a Function ?
 - Function is a special kinds of container.
 - Function is also a container.
- Fn feature
 - STDIN / STDERR
- vs kubernetes
 - kubernetes is too slow (maybe heavy)
 
- Fn project
 - 目的・概要
  - docker 操作をより速く簡単に使うためのツール（プロジェクト）
 - 特徴
  - Serverless に拘る (*)
  - 全てを Function として定義 (*)
 - docker で使えるとあるが、OpenSource、汎用的ではある
 - デプロイ（リリース）に主眼を置いている印象
 　- init -> run -> test -> deploy -> call
   - update = new deploy
   - monitor はあまり考慮に入っていない？
  
*) 
　言葉の問題で具体的に何の意味があるのかよく分からない。
　ただし、対象や機能を絞って定義することでコマンドの簡素化
　処理の高速化を実現しているようには見える。

## Talk.2 Kubernetes + Docker

- Docker (CE,EE) supports kubernetes
 - You can enable kubernetes in docker application on Mac.

### About Docker CE on Mac 

- You can kubernetes with docker in case you install docker-CE Edge version
 - Not stable version right now.
- kubernetes settings
 - ~/.kube/config 
  - You can also use kubectl command.
- Example
 - When you kick the command, docker use also kubernetes.
  
```
 $ docker stack deploy --compose-file docker-compose.yaml doge
```

- Link
 - https://docs.docker.com/docker-for-mac/kubernetes/

### Docker EE

- Create stack
 - You can chose mode - basic, swam, and "kubernetes"
  - also select "namespace" comes from kubernetes.
 
### Summary

- You can deploy both kubectl and docker stack.

-> Docker CEでもEEでもkurernetes使えるよ。
   Docker EEならば簡単にkubernetesの設定作れるよ。だから使ってね！　な印象。。
(C言語)ポインタとか配列の書き方


#ポインタ代入の書き方

宣言時

```C
char str[10] = "";
char *ptr = str;
```

---
後からポインタへ代入する場合は、*を付けない_ポインタ変数名_に対して代入する。
配列の先頭アドレスを代入したい場合は、&を付けない_配列変数名_を代入する。

```C
char str[10] = "";
char *ptr;

ptr = str;
```
---
配列の途中のアドレスを代入したい場合は、&を付ける。

```C
char str[10] = "";
char *ptr;

ptr = &str[5];
```

#ポインタの中身へ代入
ポインタが指しているメモリの中身へ代入する場合は、*を付ける。

```C
char str[10] = "";
char *ptr = str;

*ptr = "t";
ptr++;
*ptr = "e";
ptr++;

```

#ポインタの中身を取り出す
ポインタが指しているメモリの中身を取り出す場合は、*を付ける。

```C
char str[10] = "text";
char *ptr = str;
char c;

c = *ptr;
ptr++;
c = *ptr;
ptr++;

```
puttygenでキーを作成すると、githubに拒否られる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83911/ccda58c6-a58a-19df-b838-aa0ceb95dc06.png)

Key is invalid. It must begin with 'ssh-rsa', 'ssh-dss', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', or 'ecdsa-sha2-nistp521'. Check that you're copying the public half of the key

puttyのputtygenでキーを作成しても拒否られる。ssh-rsaとかから始まるフレーズにしろといわれているとおもうのだが、オプションを変えても、かわらず。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83911/4d0579bf-57a9-fd23-4641-6bdbba1953fe.png)

vmのcentosで作成したら、さくっと登録できた。むー。

ssh-keygen -t rsa

[gitHubでssh接続する手順~公開鍵・秘密鍵の生成から~ - Qiita](http://qiita.com/shizuma/items/2b2f873a0034839e47ce)
sambaで繋いだファイルサーバに、git cloneするとパーミッションがめんどくさくなる

tortoise git 
sambaで、linuxにつながっているときとか
cloneは、linuxじゃなくて、windowsのほうでやる。でやれば、なんかステキになりそう。
linux側で、cloneするとpermissionがバラバラになるね。

fileのパーミションを複数の環境で素敵にするのが今後の課題(2018年2月現在）
Ruby/Railsで月の何週目、何曜日から日付を求める

```ruby:lib/date_helper.rb
require 'date'
require 'active_support'
require 'active_support/core_ext/date'

class Date
  def date_from_week_and_day(week, wday)
    # 当月の初日を出す
    d = beginning_of_month
    # 初週の日数
    first_week = 7 - d.wday

    day = first_week + (7*(week-2)) + wday + 1  # 日曜始まりにするためにwday+1にする
		
    # その月に存在しない日になったらfalse
    return false if end_of_month.day < day || day < 1
    Date.new(year, month, day)
  end
end
```

### 使い方
```ruby
require 'date_helper'

d = Date.today
# => Fri, 02 Feb 2018

# 今月の3週目火曜日（wday=2）の日にち
d.date_from_week_and_day(3,2)
# => Tue, 13 Feb 2018
```

### 日付から何週目、何曜日を求めたいとき
こちらが参考になりました。多謝。
https://gist.github.com/komiya-atsushi/3269033
【サルが書く】cakephp2のcomponent内でcomponentを使うぞ


公式cookbookから引用



```php


// app/Controller/Component/CustomComponent.php
// コンポーネントを使う方

App::uses('Component', 'Controller');
class CustomComponent extends Component {
    // 実装中のコンポーネントが使っている他のコンポーネントここで指定する
    public $components = array(
      'Existing'
    );

    public function initialize(Controller $controller) {
        $this->Existing->foo();
    }

    public function bar() {
        // ...
   }
}
```

```php


// app/Controller/Component/ExistingComponent.php
// 使われるコンポーネント

App::uses('Component', 'Controller');
class ExistingComponent extends Component {

    public function foo() {
        // ...
    }
}
```
Yarn、Node.js 4系 or 8系 をインストールする

Railsプロジェクトに「[AdminLTE](https://adminlte.io/)」が「[Yarn](https://yarnpkg.com/ja/)」を使って入れられるようになった模様。

ここではその最初のステップである「Yarn」と「Node.js」のインストール方法を覚書きします。

※「Yarn」から「AdminLTE」を入れるには、別途「Node.js」が必要になります。

# 実行環境

```bash
$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
```

実行環境は「CentOS 7系」です。

# Yarnのインストール

```bash
$ sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
$ sudo yum install yarn
```

[公式ドキュメント](https://yarnpkg.com/ja/docs/install#linux-tab)を参照。

# Node.js 4系の場合

```bash
$ sudo rpm -Uvh https://rpm.nodesource.com/pub_4.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm
$ sudo yum install nodejs
$ node -v
v4.8.5
```

# Node.js 8系の場合

```bash
$ cd /etc/yum.repo.d # インストール場所はとりあえずここで
$ curl -O https://rpm.nodesource.com/pub_8.x/el/6/x86_64/nodejs-8.4.0-1nodesource.el6.x86_64.rpm
$ rpm -ivhU nodejs-8.4.0-1nodesource.el6.x86_64.rpm
$ node -v
v8.4.0
```

# メモ
最新のYarnはNode.jsのバージョンが「4.0」以上でなければ動かないようです。

```bash
$ yarn --version
Node version 0.10.48 is not supported, please use Node.js 4.0 or higher.
```

# 参考記事
[CentOS 6.xにLTS(4.3.0)のnode.jsをインストールする - Qiita](https://qiita.com/zaburo/items/a69ab94f707454a5bbe7)
[setup_8 not works for CentOS6 #517 - GitHub](https://github.com/nodesource/distributions/issues/517)
windows7+vscode+xamppでデバッグ


launch.jsonの設定にダダはまり。
windowsでやろうとすると、pathの設定とかが各種資料と違うんだよねｗ
localsourcerootは、deprecatedと言われるたので、pathMappingsに変更。メッセージがきちんと出るのが親切だなぁ。
自分が作るシステムもそうしたい。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/83911/0bfb535e-db6e-a9d4-13a9-055fab2135d3.png)

C:\work\git\aaaa\.vscode\launch.json

```json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "log": true,
            "pathMappings": {
                "${workspaceRoot}": "${workspaceRoot}"
            }
        },
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "log": true,
            "program": "${file}",
            "cwd": "${fileDirname}",
            "pathMappings": {
                "C:\\aaa\\bbb\\cccc": "${workspaceRoot}"
            },
            "port": 9000,
            "runtimeExecutable": "C:\\xampp\\php\\php.exe"
        }
    ]
}
```
止まったｗ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/83911/f1d10e1b-32ce-101a-f42d-9365096a11a2.png)
【サルが書く】phpでのucfirst、lcfirstはどっちがどっちだかわからなくなる



#ucfirst関数、lcfirst関数
文字列（アルファベット、英字）の最初の文字を大文字及び小文字変換することができます。

**引数**
　　$string 
　　最初の文字を大文字 / 小文字に変換する文字列を指定します。 
**返り値**
　　最初の文字を大文字 / 小文字に変換した文字列を返します。 



```php

// コードの例

<?php
// 文字列を指定する
$komoji = "banana is very cool.";
$oomoji = "BANANA IS VERY COOL.";
 
var_dump( ucfirst($komoji) );
var_dump( ucfirst($oomoji) );
var_dump( lcfirst($komoji) );
var_dump( lcfirst($oomoji) );
```

```php

// 実行結果
string(20) "Banana is very cool."
string(20) "BANANA IS VERY COOL."
string(20) "banana is very cool."
string(20) "bANANA IS VERY COOL."

```

スネークケースとキャメルケースを使い分ける時に使えそうな気がする。
text_fieldのdisabledオプションがtrueの場合はparamsに値が入らない

Railsのフォームは癖があって慣れるまでに時間が掛かりますね。

# こんな時どうする

```
ビューの中のフォーム部品（今回はtext_field）を使用不可の状態で、値（value）だけコントローラー側に投げたい
```

そのフォーム部品と関連するカラムに「NOT NULL」制約を設けている場合は困りますね。

# こうする
フォームオプションの`disabled`が有効の場合は`params`に値が入らないため、こういう場合は`readonly`を有効にする。

```html+erb
<%= f.text_field name, disabled: true %> <!-- Not good -->
<%= f.text_field name, readonly: true %> <!-- Good -->
```

# 参考記事
[text_fieldをdisabledにすると、その項目は保存されなかった。- ぶつかるまでムーンウォーク](http://ken73g.blogspot.jp/2011/01/textfielddisabled.html)
tmuxでバッファの履歴を見る

セッション保存のために tmux 内で jupyter notebook とかを走らせていると，パスワード設定をせずに使っている場合アクセストークンの情報が流れてしまって，いずれ見えなくなってしまう．

そういう場合は，
`Prefix + PageUp`
でコピーモードに入って，かつページアップできる．

コピーモードに単純に入るだけなら，
`Prefix + [`
でコピーモード．

抜ける時は Prefix なしで
`q`

ちなみに，デフォルトの設定は知らないけど，
`set-window-option -g mode-keys vi`
としておくと，コピーモードの時にviキーバインドで移動できて便利．
【サルが書く】cakephpのClassRegistry::initってなんだ

コンポーネントやヘルパーからモデルを呼びたい時はClassRegistry::initじゃないとモデルを呼べない。
App:usesとApp::importはコンポーネントやヘルパーでは使えないらしい。
またユニットテストを行いたいときにはClassRegistry::initを使うと、本番DBに繋がずにテストを行いことができるらしい。

ClassRegistryはインスタンスが生成済みであれば、生成済みのインスタンスを返す。シングルトン形式でインスタンスを生成している。なので違う性質のインスタンスをいくつか作る場合は適していないらしい。

- シングルトンとは生成するインスタンスを一つに制限するデザインパターンらしい。
- シングルトンだと指定したクラスのインスタンスが一つだと保証する。
- インスタンスが一つだと表現したい
- このような場合にSingletonパターンを用いてインスタンスを生成します。

インスタンスの状態を保持したかったり、クラス間で共通のメソッド・プロパティにアクセスしたい場合に使われることが多いですね。
会社で少し盛り上がった Project Euler をやってみる 010

# Problem 010
```
10以下の素数の和は 2 + 3 + 5 + 7 = 17 である.
200万以下の全ての素数の和を求めよ.
```
---

# Answer 010 (Python)

遅い... もっと早くしたい。

```python3
import sys


class Problem10:

    PRIME = []

    def main(self, limit):
        for i in range(2, limit):
            if self.isPrime(i):
                self.PRIME.append(i)
        print(sum(self.PRIME))

    def isPrime(self, num):
        for i in self.PRIME:
            if i ** 2 > num:
                return True
            if num % i == 0:
                return False
        return True


if __name__ == '__main__':
    limit = 2000000
    if len(sys.argv) == 2:
        limit = sys.argv[1]
    p = Problem10()
    p.main(int(limit))
```
---

# (参考) Project Euler とは

[Project Euler](https://projecteuler.net/) はプログラミングで数学の問題を解くサイトです。問題は600問以上あるので、勉強に使うのも良し、楽しむのも良しです。

サイトに登録すれば、解答を submit することができ、その場であっているか判定してくれます。

また、問題だけであれば、日本語に翻訳された Wiki もあるのでそちらを見ながらやると捗ると思います。

[Project Euler(日本語訳)](http://odz.sakura.ne.jp/projecteuler/)
ConstraintLayoutでアスペクト比を動的に設定し高さの最大値を設定する

## 動作環境

* `com.android.support.constraint:constraint-layout:1.1.0-beta4`
  * `1.0.2`では期待した動作をしませんでした 

## 実現したいこと

* WebAPIからImageViewに表示する画像のURLを取得し、そのURLの画像を表示する
* WebAPIから画像のアスペクト比を取得し、画像取得前にImageViewの高さと幅をfixさせておく
  * これをしないと画像表示時に画面がかくつく
* 画像の横幅の最大値は画面幅
* 画像の高さの最大値は固定値（今回の例では220dp）

## 実現したコード

### xml

* AndroidのDataBindingを使用しています
* xmlの一部を抜粋しています
* `mainImageUrl`は画像のURLです
* `mainImageSizeRatio`は幅の比率を1とした場合の高さの比率です


```xml
        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal">

            <ImageView
                heightForRatio="@{1}"
                widthForRatio="@{mainImageSizeRatio}"
                maxHeightDp="@{220}"
                imageUrl="@{mainImageUrl}"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:adjustViewBounds="true"
                android:scaleType="fitCenter"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

        </android.support.constraint.ConstraintLayout>
```

### BindingAdapter

* アスペクト比と高さの最大値を設定するコードは以下のとおりです
* `layout_constraintWidth_max`と`layout_constraintHeight_max`を使ってみましたが期待した動きはしませんでした


```kotlin
@BindingAdapter("widthForRatio", "heightForRatio", "maxHeightDp")
fun View.setDimensionRatio(width: Number, height: Number, maxHeightDp: Number?) {

    val ratioString = "$width:$height"
    val constraintLayout = parent as ConstraintLayout
    val constraintSet = ConstraintSet()
    constraintSet.clone(constraintLayout)
    constraintSet.setDimensionRatio(id, ratioString)
    constraintLayout.setConstraintSet(constraintSet)

    val (maxHeightPx, maxWidthPx) = if (height.toInt() == 0) {
        0 to 0
    } else {
        maxHeightDp?.let {
            val h = DpPixelConverter.toPixel(context, it)
            val w = (h * width.toFloat() / height.toFloat()).toInt()

            h to w
        } ?: Int.MAX_VALUE to Int.MAX_VALUE

    }



    constraintLayout.maxHeight = maxHeightPx
    /*
     * maxWidthの設定がないと、maxHeightを超える縦長画像が来た場合（その他のケースもあるかもしません）に、
     * Viewの高さがwidthとrationを元に設定され、maxHeightを無視されてしまいます。
     * その為、widthとrationを元に計算される高さをmaxHeightに収めるためにmaxWidthを設定します。
     */
    constraintLayout.maxWidth = maxWidthPx
}
```

参考までにimageUrlを設定するBindingAdapterも記載しておきます。

```kotlin
@BindingAdapter("imageUrl")
fun ImageView.loadWebImage(imageUrl: String?) {
    Picasso.with(context).load(imageUrl).into(this)
}
```

## 参考にしたページ

* [https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html](https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html)
* [http://speakerdeck.com/yanzm/android-studio-3-dot-0-hanzuon-layouteditor-and-constraintlayout#84](http://speakerdeck.com/yanzm/android-studio-3-dot-0-hanzuon-layouteditor-and-constraintlayout#84)
[Android]Glide Error - java.lang.NoClassDefFoundError



```
implementation 'com.github.bumptech.glide:glide:4.6.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.0'
```

Glide 4.6.0 -- X

```
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/bumptech/glide/gifdecoder/GifDecoder$BitmapProvider;
```

#solution
## Test 
Glide 4.2.0 -- OK
Glide 4.3.0 -- OK
Glide 4.4.0 -- OK

```
implementation 'com.github.bumptech.glide:glide:4.4.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.4.0'
```
(Qiita API v2 活用) Qiita の記事を API 経由で取得する方法

# やりたいこと

Qiita に投稿された記事を確認したい。

# 最新の記事を取得するサンプルコード

``` bash
curl --silent \
  "https://qiita.com/api/v2/items?page=1&per_page=20" \
  | jq .

```

# ユーザーを指定して記事を取得するサンプルコード

``` bash
curl --silent \
  "https://qiita.com/api/v2/items?page=1&per_page=20&qiita+user:kojiro-s" \
  | jq .
```

# (要トークン) 自分の投稿した記事を取得するサンプルコード

``` bash
curl --silent \
  --header "Authorization: Bearer ${QIITA_TOKEN}" \
  "https://qiita.com/api/v2/authenticated_user/items?page=1&per_page=20"
```

# 自分の投稿した記事タイトルといいねの数を抽出するサンプルコード

``` bash
curl --silent \
  --header "Authorization: Bearer ${QIITA_TOKEN}" \
  "https://qiita.com/api/v2/authenticated_user/items?page=1&per_page=20" \
  | jq -c '.[] | [.likes_count, .title]'
```

# 参考情報

  - <https://qiita.com/api/v2/docs#投稿>
      - <https://qiita.com/api/v2/docs#get-apiv2items>
      - <https://qiita.com/api/v2/docs#get-apiv2authenticated_useritems>
GitLabのdiffを一括で折りたたむ [Collapse All]ボタンを追加するsnippet

大量のコードをレビューする際（特に自動生成ファイルや画像ファイルが含まれている場合）には、一旦全てのDiffを折りたたんでからレビューを進めたいと思う事があります。

普通にあっても良さそうな機能ですが、現時点では実装されてません。
Feature Proposalとして、既に以下のページに上がっているのでそのうち実装されるとは思いますが・・。

[Workaround]

この機能が実装されるまでは、以下のページに記載されていた方法で[Collapse All]ボタンをDiffのページに追加する事ができます。

1. Chrome を起動。
2. [F12] をクリック。
3. "Sources" をクリック。
4. "Snippets" タブをクリック。
5. "+ New snippet"をクリック。
6. Snippetの名前を付けた後、以下のコードを貼り付け、保存する。
7. 作成したSnippetを選択し、右クリックした後"Run"を選択する。

```js
/*
* GiblabのDiffページに[Collapse All] ボタンを追加するsnippet
*/

// Collapse All ボタンの作成
function createCollapseAllButton() {
    var button = document.createElement('button');
    button.setAttribute('id', 'collapse-all');
    button.setAttribute('class', 'btn btn-default');
    button.setAttribute('type', 'button');
    button.textContent = 'Collapse All';

    return button;
}

// Collapse All ボタンをクリックした際のイベントハンドラ
function collapseAll(event) {
    $('.diff-file').find('div.nothing-here-block').each(function(i) {
        if (!$(this).is(':visible')) {
            $(this).parents('div.file-holder').find('div.file-title-flex-parent').trigger('click');
        }
    });
}

var buttons = document.getElementsByClassName('inline-parallel-buttons')[0];
buttons.insertBefore(createCollapseAllButton(), buttons.firstChild);

// Collapse All ボタンを有効化
document.getElementById('collapse-all').addEventListener('click', collapseAll, false);

```




[参考URL]
[Button to collapse all diffs (#24679) · Issues · GitLab.org / GitLab Community Edition · GitLab](https://gitlab.com/gitlab-org/gitlab-ce/issues/24679)
PostgreSQLのWALファイル(トランザクションログ)見積もり

# はじめに
PostgreSQLの設計を行うときの、WALファイル(トランザクションログ)の見積もり方法についてまとめました。

## WALファイル(トランザクションログ)
PostgreSQL 9.5 より、WALファイルの設定パラメータ「checkpoint_segments」が、「min_wal_size」と「max_wal_size」に置き換えられた。
「max_wal_size」は、チェックポイントの間にWALが増加する最大サイズであり、 デフォルト値は1GB（WALファイル64個分）になる。
この設定値が小さい場合は障害発生時のリカバリ時間が短くなるが、チェックポイントが頻繁に行われることで性能に影響する。
また設定値を大きくすることで性能への影響を考慮できるが、ディスク容量の増大や障害発生時のリカバリに必要な時間が長くなる。

よって、性能への影響を考慮する場合は、大きいデータ更新などのトランザクション発生時に「max_wal_size」が満たせるように設計する。

## 例
例として以下に示す計算式で見積もる。
(※)WAL領域の枯渇はトランザクションの停止に繋がるため、少し多めを考慮したほうがいいと考える。

データ更新件数：100件/日
トランザクション量：10MB/回

*見積りサイズ = 100 * 10 * 安全率*
→安全率を1.5とすると約1.5GBになるので、切り上げて2GBとする。

## アーカイブログ
アーカイブログはポイントインタイムリカバリ(PITR)時に必要となるファイルで、アーカイブモード有効時に出力される。運用としてデータベースのフルバックアップを週に一回で行い、かつ、差分バックアップとしてアーカイブログを日時でバックアップするときの見積もりについて考える。

アーカイブログは、以前にバックアップした時点から現在までのトランザクションログのアーカイブである。また、バックアップの期間と更新トランザクションの内容によって変動する。そのため、バックアップの期間が長いほど、更新トランザクションが多いほど、アーカイブログの容量は増加する。よって、アーカイブファイルはWALファイルと同一のものになるので、以下に示す計算式で見積もる。

## 例
例として上記WALファイルの見積もりを基に以下に示す計算式で見積もる。

WALファイルサイズ：2GB
バックアップの世代数：7

*見積りサイズ = 2 * 7 * 安全率*
→同じく安全率を1.5とした場合、21GBになる。
【サルが書く】cakephp2.x にgithubからogpプラグインをインストールする

# ogpをプラグインで設定したいよ〜〜

/app/composer.jsonに追加したいプラグインを記述する。

```php

{
	"require": {
		"cakephp/cakephp": "2.*",
		"hogehoge" : "1.4.3",
		"fugafuga": "2.4.0",
		"monsat/ogp": "dev-master" // NEW!!! 	
        },
}
```

追加するときのバージョン指定はpackagistを確認するなり、githubで確認するなりして指定してください。
https://packagist.org/

今回のogpのプラグインに関してはバージョンが開発バージョンしかなかったのでdev-masterという記述にしてあります。

記述後ローカルでcomposer update を行うとこのようなlogが出ると思います。

```bash
$ composer update
```

```bash
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing monsat/ogp (dev-master 89179c4): Cloning 89179c4e0e from cache
Writing lock file
Generating autoload files
```

下から3行目でInstalling monsat/ogpとなっているので、プラグインが入っているのだと確認できますね。
ACFのgoogleMapでエラーが出る時の対処

メモ書き的な感じです。
Advanced Custom Fieldで使ってるgoogle Mapの機能、なぜかエラーが起き、
「なんやこれ！住所で参照できんやんけ！この◯◯！」となり
その時の対処法を書いときます。

#何故起きた？
よくわかりません。

#あせるな、まずはconsole
投稿画面で発生しているエラーを確認。
新規でページ開いただけではエラーは出ておらず、地図を編集しようとすると発生。

#API keyの取得
「おどりゃ◯森、APIkeyが(ry」と出てるので、
諦めてAPIを新規に取得します。

#function.php
function.phpであてがいます。

やればわかるｺﾝﾄﾝｼﾞｮﾉｲｺ!!!
bash > string > ファイル名の先頭文字数を指定して表示 > cut -b "-4"

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
openmpi-1.8.x86_64 とその-devel
mpich.x86_64 3.1-5.el6とその-devel
gcc version 4.4.7 (とgfortran)
NCAR Command Language Version 6.3.0
WRF v3.9を使用。
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
date (GNU coreutils) 8.4 
tmux 1.6-3.el6
```

[bash > bundle_similar_file_180202_exec > 似たようなファイル名の一覧を省略表示するスクリプト v0.1, v0.2 > スクリプトでなく「ls | uniq -w 3」でいい](https://qiita.com/7of9/items/4629d72f78b2a873543b#comment-82cd8399d1da308d944d)
において文字列処理をしていたところ、@tukiyo3 さんに[文字列の切り取り方を教えていただきました](https://qiita.com/7of9/items/4629d72f78b2a873543b#comment-82cd8399d1da308d944d)。

将来の再利用性を考慮して、別記事に切り出します。

### 教えていただいたコード

[こちら](https://qiita.com/7of9/items/4629d72f78b2a873543b#comment-82cd8399d1da308d944d)を参照ください。

```bash
$ ls
AAA01  AAA02  AAA03  BBB01  BBB02  BBB03  BBB04  bundle_similar_file_180202_exec  CCC01
```

```bash
$ bundle_similar_file_180202_exec 3
AAA
BBB
bun
CCC
```

https://explainshell.com/explain?cmd=cut+-b+3
arduinoでターミナル その3

#概要

arduinoでターミナルやってみる。
２０字４行のLCDとps/2キーボードをつないで、シリアル端末を作ってみる。
テストの為、エコーなマスターをC#で書いてみた。


#写真


![echo.jpg](https://qiita-image-store.s3.amazonaws.com/0/18104/8f83b7e6-bfcf-129f-513f-e1b3d540e306.jpeg)


#サンプルコード

```
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication9
{
	public partial class Form1 : Form
	{
		private static string recBuff = "";
		public Form1()
		{
			InitializeComponent();
		}
		private void button1_Click(object sender, EventArgs e)
		{
			try
			{
				if (!serialPort1.IsOpen)
				{
					serialPort1.Open();
					richTextBox1.AppendText("start\n");
				}
				else
				{
					Console.WriteLine("error0");
					richTextBox1.Text = "Failed to open COM port";
				}
			}
			catch (UnauthorizedAccessException ex)
			{
				MessageBox.Show(ex.Message);
			}
		}
		private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
		{
			try
			{
				recBuff = serialPort1.ReadExisting();
				this.Invoke(new EventHandler(DisplayText));
			}
			catch (System.TimeoutException)
			{
				Console.WriteLine("error1");
			}
		}
		private void DisplayText(object s, EventArgs e)
		{
            int buffLen = recBuff.Length;
			int buffPos = -1;
			int c = ' ';
			if (buffLen > 1)
			{
				if ((buffPos = recBuff.IndexOf("\r")) >= 0)
				{
                    richTextBox1.AppendText(recBuff.Substring(0, buffPos));
                    richTextBox1.AppendText("[CR]");
                    richTextBox1.AppendText(recBuff.Substring(buffPos, (buffLen - buffPos)));
				}
				else
				{
                    richTextBox1.AppendText(recBuff);
				}
			}
			else
			{
				c = recBuff[0];
				if (c == 13)
				{
                    richTextBox1.AppendText("[CR]");
                    richTextBox1.AppendText(recBuff);
				}
				else if (c == 7)
				{
                    richTextBox1.AppendText("[BELL]\n");
				}
			}
            Console.WriteLine(recBuff);
			Byte[] dat = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetBytes(recBuff);
			serialPort1.Write(dat, 0, dat.GetLength(0));
		}
	}
}




```

以上。
APIの役割の多様化（メモ）

<h1>APIのリトライ処理</h1>
<h2>ヤフオク</h2>
レイヤー化
Circuit Breaker
Exponential Backoff

<h1>Real World Mercari API</h1>
<h2>メルカリ　佐野さん</h2>
APIフォーク
マイクロサービス

<h1>A/Bテスト機構</h1>
<h2>Gunosy ちまきん</h2>
ルクラアプリ
A/B,A/Aテスト
分析基盤・実施基盤
必ずABのパラメータを含める
Allocation：割合
Experiment：テスト内容
Variant：ケース
A/Bを前提に開発するので常に大胆に検証できる

<h1>デベロッパープロダクトシステム</h1>
<h2>LINE</h2>
UXだけでなくDX
APIはInternalではいけない

<h1>生体認証のAPI化</h1>
<h2>ヤフID</h2>
FIDO
記憶認証・所持認証・生体認証
WebAuthencation(W3C)
bash > bundle_similar_file_180202_exec > 似たようなファイル名の一覧を省略表示するスクリプト v0.1, v0.2 > スクリプトでなく「ls | uniq -w 3」でいい

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
NCAR Command Language Version 6.3.0
for WRF3.7.1, WPS3.7.1
  openmpi-1.8.x86_64 とその-devel
  mpich.x86_64 3.1-5.el6とその-devel
  gcc version 4.4.7 (とgfortran)
for WRF3.9, WPS3.9
  Open MPI v2.1.1
  gcc version 4.9.2 (とgfortran; devtoolset-3使用)
　NetCDF v4.4.1.1, NetCDF (Fortran API) v4.4.4
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
date (GNU coreutils) 8.4 
tmux 1.6-3.el6
```

### 背景

```bash
$ ls
AAA01  AAA02  AAA03  BBB01  BBB02  BBB03  BBB04  bundle_similar_file_180202_exec  CCC01
```

AAA*やBBB*やCCC*など共通のprefixを持つファイルが一つのディレクトリに数百個あると、そのファイルが目立ち、他にどういうファイルがあるか見つけにくい。
他のファイルも含めてみるためのスクリプトを検討した。

- 指定の文字長さでuniq処理する

### 参考

- [bashで変数から部分文字列を取得する](https://qiita.com/koara-local/items/04d3efd1031ea62d8db5)
    - > オフセットと長さを指定して文字列を取得する
- [昨日〜9日前までの日付を空白区切りで返すサンプル](https://qiita.com/tukiyo3/items/97ec3dc0920e5c6a0470)
    - `--max-args=1`の使用例


### code v0.1

(追記 2018/02/02) 
同じ処理は@tukiyo3 さんの[コメント](https://qiita.com/7of9/items/4629d72f78b2a873543b/#comment-82cd8399d1da308d944d)でもっとシンプルに実装されています。

```bash:bundle_similar_file_180202_exec
#!/usr/bin/env bash
set -eu

if [ $# -eq 0 ]; then
	echo "[cmd] [number of common characters]"
	exit 0
fi

CHECK_LEN=$1

RESULT=$(
for elem in $(ls)
do
	echo ${elem:0:$CHECK_LEN}
done
)

echo $RESULT | xargs --max-args=1 echo | uniq
```

### 実行例

文字長さ3での実行例。

```txt:run
$ bash bundle_similar_file_180202_exec 3
AAA
BBB
bun
CCC
```

文字長さ5での実行例。

```txt:run
$ bash bundle_similar_file_180202_exec 5
AAA01
AAA02
AAA03
BBB01
BBB02
BBB03
BBB04
bundl
CCC01
```

使い勝手が良いかは不明。
bunでなくbundle_similar_file_180202_exec と表示されると良いだろうか。

### code v0.2

少し変えてみた。

参考: https://unix.stackexchange.com/questions/201761/search-and-delete-duplicate-files-with-different-names
> answered Nov 30 '15 at 1:25
Tom Zych

```bash:bundle_similar_file_180202_exec
#!/usr/bin/env bash
set -eu

if [ $# -eq 0 ]; then
	echo "[cmd] [number of common characters]"
	exit 0
fi

ls | uniq -w $1
```

### スクリプト不要

つまり、以下だけで良いということ。

```
$ ls | uniq -w 3
AAA01
BBB01
bundle_similar_file_180202_exec
CCC01
```

https://explainshell.com/explain?cmd=uniq+-w+3

リストの改行を取り除きたい場合は

```bash
$ ls | uniq -w 3 | xargs
AAA01 BBB01 bundle_similar_file_180202_exec CCC01
```
arduinoでターミナル その２


#概要

arduinoでターミナルやってみる。
２０字４行のLCDとps/2キーボードをつないで、シリアル端末を作ってみる。

#写真

![CIMG2526.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/dcdc4284-270a-795b-6740-606e900abf2c.jpeg)


#読み込んだデータをLCD表示するサンプルコード

```
#include "Lcd4567.h"
#include "ps2.h"

Lcd4567 lcd;
PS2 kbd(7, 6);

String buf0 = "start";
String buf1 = "";
String buf2 = "";
String buf3 = "";

void disp()
{
	int len;
	char c0[30];
	char c1[30];
	char c2[30];
	char c3[30];
	lcd.clear();
	lcd.setCursor(0, 0);
	len = buf0.length();
	if (len > 0)
	{
		buf0.toCharArray(c0, len + 1);
		lcd.print(c0);
	}
	lcd.setCursor(0, 1);
	len = buf1.length();
	if (len > 0)
	{
		buf1.toCharArray(c1, len + 1);
		lcd.print(c1);
	}
	lcd.setCursor(0, 2);
	len = buf2.length();
	if (len > 0)
	{
		buf2.toCharArray(c2, len + 1);
		lcd.print(c2);
	}
	lcd.setCursor(0, 3);
	len = buf3.length();
	if (len > 0)
	{
		buf3.toCharArray(c3, len + 1);
		lcd.print(c3);
	}
}

void setup()
{
	Serial.begin(115200);
	lcd.begin(20, 4);
	Serial.println("start0");
	disp();
}
void loop()
{
	if (Serial.available() > 0)
	{
		String str = Serial.readStringUntil('\r');
		buf0 = buf1;
		buf1 = buf2;
		buf2 = buf3;
		buf3 = str;
		disp();
		Serial.println(str);
	}
}




```

以上。
Rails で postgresql を使う(インストールからマイグレーションまで)

# はじめに
Rails アプリケーションの開発を進めていくなかで、ついつい sqlite に頼ったままどんどん前に進んでしまうことがよくある。
MySQL か postgreSQL に変えなきゃな〜〜と思いつつ sqlite をそのまま使いつづけるのを防ぐため、まとめておく。

# postgresql の設定
## Homebrew でインストール

```bash
$ brew update
$ brew install postgresql
```

## 起動&接続
以下で実行してみる。

```bash
$ postgres
```
エラーになるはず。

```bash
postgres does not know where to find the server configuration file.
You must specify the --config-file or -D invocation option or set the PGDATA environment variable.
```
コンフィグファイルを指定していないのが原因

postgresql を brew で install したときに、
/usr/local/var/postgres
が作成されている。これを環境変数にセットしておく。
~/.bashrc に以下を追加。

```bash
export PGDATA='/usr/local/var/postgres'
```

もちろん `$ source ~/.bashrc` する。

今度は起動できる

```bash
$ postgres
```
起動した状態で、別プロセスから接続可能

```bash
$psql -d postgres
psql (9.6.3)
Type "help" for help.
postgres=#
```

# Rails の設定とか
## database.yml
config/database.yml を以下のように変える。

```yml:config/database.yml
default: &default
adapter: postgresql
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: user
password: pass
host: localhost
timeout: 5000
 
development:
<<: *default
database: hoge_development
 
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: hoge_test
 
production:
<<: *default
database: hoge_production
```

## 設定に合わせてDB&user作成
便利な createdb/dropdb などのコマンドがあるのでそれを使う。

```bash
$ createdb hoge_production
$ createdb hoge_development
$ createdb hoge_test
$ createuser user
```

## マイグレーション

以下で development 環境の DB をマイグレーション

```
$rails db:migrate RAILS_ENV=development
```
以下で確認可能

```
$ rails db
$ psql -d hoge_development
```
matplotlib.animation.FuncAnimation() で図形のアニメーションを作る

# 概要  
「停止」「再開」「リセット」の各操作がボタンでおこなえるようにする。<br>
<iframe width="560" height="315" src="https://www.youtube.com/embed/qiminBJ5eWs" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


# 完成したPythonスクリプト    
```animation.py3
from math import sin as Sin
from matplotlib import pyplot as plt
from matplotlib import animation
from matplotlib.widgets import Button

class xyAnim:
    def __init__(self):

        # グラフを作って、
        self.fig = plt.figure()
        self.ax  = plt.axes(xlim=(-2,2), ylim=(-1,1))
        self.ax.set_aspect("equal")

        # グラフの中にボタンを作って、
        self.playButton  = self.__createButton(0.6, 0.03, 0.15, 0.1, "play/pause", self.__PlayPause) # (左下 x 座標, 左下 y 座標, 幅, 高さ, ラベル, バインドする函数)
        self.resetButton = self.__createButton(0.8, 0.03, 0.15, 0.1, "reset"     , self.__Reset    ) # (左下 x 座標, 左下 y 座標, 幅, 高さ, ラベル, バインドする函数)

        # 何か図形 (ここでは円) を実体化して、
        self.theta  = 0
        self.circle = plt.Circle((Sin(self.theta), 0), 0.5) # Circle((中心 x 座標, 中心 y 座標), 半径)

        # その図形をグラフの中に投入する。
        self.ax.add_patch(self.circle)

        # 「どのグラフで (self.fig)」「どの函数を (self.__update)」「何ミリ秒ごとに呼び出す (interval=)」のかを設定する。
        self.anim = animation.FuncAnimation(self.fig, self.__update, interval=1000/30)

        # アニメーションの動作/停止状態を示すフラグを立てておく。
        self.isRunning = True

    # この函数を一定時間ごとに呼び出す。
    def __update(self, _):
        self.theta        += 0.1                  # 呼ばれるたびに何かを少しずつ変化させて、
        self.circle.center = (Sin(self.theta), 0) # それに合わせて円の中心座標を少しずつずらす。

    # "play/pause" ボタンがクリックされたら、アニメーションを停止するか再開するかする。動作/停止状態を示すフラグもトグルする。
    def __PlayPause(self, event):
        if self.isRunning:
            self.anim.event_source.stop()
            self.isRunning = not self.isRunning
        else:
            self.anim.event_source.start()
            self.isRunning = not self.isRunning

    # "reset" ボタンがクリックされたら、図形を最初の位置に戻す。
    def __Reset(self, event):
        self.theta         = 0
        self.circle.center = (Sin(self.theta), 0)
        plt.show()

    # ボタンを作るための函数
    def __createButton(self, bottomLeftX, bottomLeftY, width, height, label, func):
        box    = self.fig.add_axes([bottomLeftX, bottomLeftY, width, height]) # ボタン用の枠を描いて、
        button = Button(box, label)                                           # それをボタンとして実体化して、
        button.on_clicked(func)                                               # クリックされたときに実行する函数をバインドする。
        return button

    # グラフを表示する。
    def animate(self):
        plt.show()
        return self

########
# test #
########
if __name__ == "__main__":
    xyAnim().animate()
```
# 課題    
スクリプトを起動したときにすぐにアニメーションが開始されてしまう。最初はとめておきたい。
# 参考
- https://gist.github.com/Seanny123/2c7efd90bebbe9c7bea6a1bd30a2133c     
- 『Python からはじめる数学入門』Amit Saha (著) 、黒川利明 (訳)、オライリー・ジャパン、オーム社、2016 年
インポート元モジュールのパスを取得する

# 理論

* インポート時にはインポートされるモジュールのトップレベルのコードが実行される
* インポート元はスタックトレースの一つ外側のフレーム
* モジュールのパスはモジュールオブジェクトの `__file__` 属性に入ってる

# 実装

```py:main.py
import imported
```

```py:imported.py
import inspect
stack = inspect.stack()
for s in stack[1:]:
    m = inspect.getmodule(s[0])
    if m:
        print(m.__file__)
        break
```

実行結果：

```shell-session
/some/where$ python -m main
/some/where/main.py
```