OmniAICreator/Qiita-1.07M huggingface dataset:
The Go Playground で Test & Example がしやすくなった

以前までは、[The Go Playground](https://play.golang.org/) で実行できる Go Command は `go run` のみだったので、テストを書きたい場合

```go:previous_test_description
package main

import "testing"

func Hello(name string) string {
    return "Hello, Emacs!"
}

func TestHello(t *testing.T) {
    if Hello("Vim") != "Hello, Vim!" {
        t.Error("Use Vim!!!")
    }
}

func matchString(a, b string) (bool, error) {
	return true, nil
}

func main() {
	testSuite := []testing.InternalTest {
		{Name: "TestHello", F: TestHello},
	}
	testing.Main(matchString, testSuite, nil, nil)
}
```

といった感じにまわりくどく書く必要がありました。

しかし、先日マージされた[コミット](https://go-review.googlesource.com/c/playground/+/98155)により気軽にテストができるようになりました。

テストのやり方は単純で、

1. ソースコードに `main` 関数を含めない
2. 普段テスト関数を書くように `func TestXxx(*testing.T)` を用意する

の２点を守ることです。

```go:current_test_description
package main

import "testing"

func Hello(name string) string {
	return "Hello, Emacs!"
}

func TestHello(t *testing.T) {
	if Hello("Vim") != "Hello, Vim!" {
		t.Error("Use Vim!!!")
	}
}
```

あとは実行ボタンを押せば、特別な設定なしに自動でテストモードへと切り替わり、テストが実行されます。
なお 2018/3/23 現在、`Bench` と `Example` には対応していないので、実装されるのを気長に待つか Issue を書いちゃいましょう！

## 【追記】2018/4/11
[3月の終わりにマージされたコミット](https://go-review.googlesource.com/c/playground/+/99595) により `Example` にも対応しました。

1. ソースコードに `main` 関数を含めない
2. ソースコードに `func TestXxx(*testing.T)` 関数を含めない
3. `testing` パッケージをインポートしない
4. 普段 `Example` を書くように `func ExampleXxx()` 関数を用意する

の４点を守ることで `Example` を使うことができます。
Slackのチャンネル内のメッセージをnodejsで全削除する

個人Slackのメッセージ量がそろそろ溜まりに溜まって無料プランの限界に近づいてきた。

前までチャンネル内のメッセージ全削除機能がSlackにあったはずだが…
どうやら無料プランからは無くなったらしい。

消す方法を探すと方法がでてきた。

## delete-channel-messages.js

nodejs製のシンプルなプログラムがあり、現在(2019年1月)でも使用できた。

[Deletes slack public/private channel messages\.](https://gist.github.com/firatkucuk/ee898bc919021da621689f5e47e7abac)

## 準備

### トークンの取得
https://api.slack.com/custom-integrations/legacy-tokens

Legacy token generatorあたりでtokenを作成する
（xoxp-ではじまる長いやつ）

### チャンネルidの取得
削除したいチャンネルブラウザで開くと、urlからチャンネルIDが取れる。

URLが
`https://myslackid.slack.com/messages/C49UQAKLP/`
だと`C49UQAKLP`をコピーする

### delete-channel-messages.jsをダウンロードする
[delete-channel-messages.js](https://gist.github.com/firatkucuk/ee898bc919021da621689f5e47e7abac)をダウンロードしてエディタで開き、tokenを書き込む。

<img width="961" alt="スクリーンショット 2019-01-14 9.15.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/52227/bcde8462-2ba6-a088-5faa-22b755c01c5d.png">

## 削除
あとはターミナルでチャンネルIDをパラメータにdelete-channel-messages.jsを実行する。

```bash
node delete-channel-messages.js C49UQAKLP
```

これであとは放っておけばメッセージがモリモリ消えていく。

<img width="423" alt="スクリーンショット 2018-03-23 1.56.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/52227/1dac5fc9-2e2b-93cc-e9e2-068eba48239a.png">

十数分して確認するとチャンネル内のメッセージは全て消えていた、目的達成！
組み合わせ(nCr)をC++で実装して時間計測

タイトルが紛らわしいですが、車輪の再発明をしてみたという話です。
#この記事は
多倍長ができないC++で普通に組み合わせの計算をしようとすると、階乗でオーバーフローするのはよく知られていると思いますが、その上でパスカルの三角形的に計算しようと実装したら、自力では全然速度が出なかったので、次回以降のため、自分用のメモを含めて記録しようという記事です。

#自力コード１
まずは組み合わせの式に基本的に成り立つ漸化式？と、基本の値

```math
{}_nC_r = {}_{n-1}C_{r-1} + {}_{n-1}C_{r}\\
{}_nC_n = {}_nC_0 = 1
```
(漸化式にタイポがあったので修正しました)
を見て、再帰関数にしたらめちゃくちゃ簡単に書けるんじゃないかと思って書いたのがこちら

```.cpp
long long combi(long long n, long long k) {
  if (n == k || k == 0)
    return 1;
  else {
    return combi(n - 1, k - 1) + combi(n - 1, k);
  }
}
```

実際これはnが小さいうちは当然問題なく動作したが、n=30あたりからかなり辛くなってきた。
繰り返し計算している部分が多いはずなので、メモ化したらいいのか？と思って（雑に）メモ化したのが次の自力コード２になる。

##自力コード２

```.cpp
long long combi(long long n, long long k) {
  std::map<std::string, long long> memo;
  if (n == k || k == 0)
    return 1;
  else {
    std::string key = std::to_string(n) + std::to_string(k);
    if (memo.count(key) != 0) {
      return memo[key];
    } else {
      ll out = combi(n - 1, k - 1) + combi(n - 1, k);
      memo[key] = out;
      return out;
    }
  }
}
```

雑なメモ化で早くなった試しがないのでだめだろうなと思いつつも回してみると、案の定大幅な改悪に成功した。(n=25ですでにn=30の自力コード１よりも遅い)実際はkについて計算したらn-kについても計算したことになるので、そちらもメモしたら多少マシになるのかなとも思ったが、すでに改悪されているので手間の割に効果は無いだろうと実装はしなかった。
***
2018/3/23/7:36追記
キーの競合が発生するので実際は

```.cpp
to_string(n)+ ","+ to_string(k);
```

とするべきでした。

2018/3/23/8:58 追記
まさかのmemoがスコープ的に共有されていないというありえないミスをしていたことに気づいたので、修正したところメモ化すれば再帰してもなんとか実用レベルの速さになりました（60C30で4000 microseconds）
***
自力ではもう思いつかなかったので、google先生に頼って最終的に行き着いたのが次のコードになる。
#最終コード
このコードをかくにあたって以下のサイトを参考にさせて頂いた（というかほとんどそのままお借りする形になってしまった。）
caprestのブログ　C++ vectorクラスで二次元配列 & Combination の計算
http://caprest.hatenablog.com/entry/2016/05/29/181102

```.cpp
std::vector<std::vector<long long>> comb(int n, int r) {
  std::vector<std::vector<long long>> v(n + 1,std::vector<long long>(n + 1, 0));
  for (int i = 0; i < v.size(); i++) {
    v[i][0] = 1;
    v[i][i] = 1;
  }
  for (int j = 1; j < v.size(); j++) {
    for (int k = 1; k < j; k++) {
      v[j][k] = (v[j - 1][k - 1] + v[j - 1][k]);
    }
  }
  return v;
}
```

返り値に対して、v[n][r]が${}_nC_r$になる。元プログラムでは余計な代入などを行っていないので、私が書いたものよりも更に高速に動作する（すごい）が、これでも自力のよりものすごく早い。

#時間測定
自力２は測定が不可能なくらい遅いので省略(自力１も死ぬほど遅いけど)

| 式 | 自力１(microsecond) | 最終(microsecond) |
|:-----------|------------:|:------------:|
|30_C_15 | 701192 | 40 |
| 35_C_17 | 20369929 | 24 |
| 60_C_30 | -| 86 |
***
2018/3/23/7:36　追記
元々70C35が表にありましたが、この時点でオーバーフローしているので消去しました。
***
最初に書いた再帰のプログラムも最終的なプログラムも計算しているのはたかだかパスカルの三角形の範囲に収まる節点の数なはずなのだが、こうも差が出ると、最初のプログラムの計算量が考えているよりも多いのか、はたまた関数の呼び出しとif文の判定にかなり時間が取られてしまっているのか。

あとでゆっくり考えてみたい。
トップレベルドメインっていくつあるの？

（この記事は [地平線に行く](http://d.hatena.ne.jp/chiheisen/20180322/1521736109) とのマルチポストです）

.com や .jp などのトップレベルドメイン（ドメイン名の一番右側の部分）っていくつあるのか気になったので調べてみました。

# トップレベルドメインのリスト 

IANA (Internet Assigned Numbers Authority) のページに載っていました。
[IANA — Root Zone Database](https://www.iana.org/domains/root/db)

これによると、現在のトップレベルドメインは**なんと 1576 個。**
（2018年3月23日現在）

## 内訳

|分類|概要|例|個数|
|:---|:---|:---|---:|
|country-code|国別コード|[.jp](https://ja.wikipedia.org/wiki/.jp) / [.uk](https://ja.wikipedia.org/wiki/.uk) / [.eu](https://ja.wikipedia.org/wiki/.eu)|312|
|generic|汎用|[.com](https://ja.wikipedia.org/wiki/.com) / [.gov](https://ja.wikipedia.org/wiki/.gov) / [.mil](https://ja.wikipedia.org/wiki/.mil)|1235|
|generic-restricted|汎用（制限付き）|[.biz](https://ja.wikipedia.org/wiki/.biz) / [.name](https://ja.wikipedia.org/wiki/.name) / [.pro](https://ja.wikipedia.org/wiki/.pro)|3|
|infrastructure|インフラ|[.arpa](https://ja.wikipedia.org/wiki/.arpa)|1|
|sponsored|スポンサー|[.aero](https://ja.wikipedia.org/wiki/.aero) / [.travel](https://ja.wikipedia.org/wiki/.travel) / [.tel](https://ja.wikipedia.org/wiki/.tel)|14|
|test|テスト|.test / [.テスト](https://ja.wikipedia.org/wiki/.%E3%83%86%E3%82%B9%E3%83%88)|11|

なんか generic だけ異様に多いなと思ったら、言語別のドメインが含まれていたり、使われていないものも含まれているようです。
あとは、[.hitachi （日立グループ）](https://www.iana.org/domains/root/db/hitachi.html) や [.dell (DELL)](https://www.iana.org/domains/root/db/dell.html) のような企業ドメインなんかもここに含まれています。

追加履歴を見てみると、まだまだ増えて行っているようです。
[Delegated Strings | ICANN New gTLDs](https://newgtlds.icann.org/en/program-status/delegated-strings)

さすがに全部は覚えられない…。
GitHubで毎回ユーザー名とパスワードを聞かれるのでSSH接続でスキップする

#ユーザー名とパスワードを聞かれる原因
httpsでリポジトリをクローンしてきた場合に、ユーザー名とパスワードを毎回聞かれます。毎回聞かれずにpushをしたいのであれば、SSH接続を設定するか、もしくは認証情報の仕組みを拡張(詳しいことはわからないので[ [7.14 Git のさまざまなツール - 認証情報の保存](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E8%AA%8D%E8%A8%BC%E6%83%85%E5%A0%B1%E3%81%AE%E4%BF%9D%E5%AD%98) ]を参照してください)するなどの対策が必要です。



#秘密鍵・公開鍵を設定
SSH接続では秘密鍵と公開鍵を用いて、鍵交換方式というセキュアな接続を行います。秘密鍵とは自分だけしか見ることの出来ない鍵のことで、公開鍵とは相手に預けるための鍵のことです。この２つの鍵はペアになっており、公開鍵を預けたサイトにアクセスするには必ずペアの秘密鍵を持っているマシンでなければなりません。

>詳しくはこちら
http://nigohiroki.hatenablog.com/entry/2013/08/18/221434

#秘密鍵・公開鍵の生成
```
$ ssh-keygen -t rsa -C email@example.com
```

email@example.com には自分のメールアドレスを入れてください。

鍵を保存するファイル、パスフレーズの入力を求められますが、何も入力せずにエンターを押して構いません。
鍵の生成が完了した後に```$ ll ~/.ssh```とすると```ida_rsa```と```ida_rsa.pub```といファイルが確認できるはずです。

#GitHubに公開鍵を登録
```Settings > SSH and GPG keys```から設定が出来ます。
![GitHub_ssh_setting.png](https://qiita-image-store.s3.amazonaws.com/0/243199/aa6389ac-8c13-ee5d-1db8-d29e5e1ce00a.png)

Titleは自由に入力ができます。Keyには```ida_rsa.pub```の中身をそのままコピペしてください。

#SSH接続できるか確認してみる
最後にSSH接続ができるか確認してみます。

```
$ ssh -T git@github.com
```
このコマンドで以下のように表示されたら接続成功です。

```
Hi username! You've successfully authenticated, but GitHub does not
provide shell access.
```
AndroidでRealmをファイルごと削除する

## 概要

Realmを`削除`したいけど、全てcloseしておかないといけないとか色々な事情でrealmインスタンスを取得できないときがあるかもしれないです。

## 個人的な例

Realmを暗号化した状態で、復号に必要な鍵を紛失したときにRealmが開けなくてクラッシュしてしまいます。
Realm側でサポートしてくれればいいのですが、今現在はサポートされていないみたいです。

> Long term solution is that we add a deleteRealmIfWrongEncryptionKey() option to RealmConfiguration.

[Delete corrupt database and perform a fresh setup](https://github.com/realm/realm-java/issues/3604)

## 解決策

[Delete corrupt database and perform a fresh setup](https://github.com/realm/realm-java/issues/3604) によると、全てのファイルを消すこと = 手動での削除という風に書いてありますので、Realmに関係するファイル・フォルダ毎削除してしまいます。

```kotlin 
fun deleteRealm(context: Context) {
  val dir = context.filesDir
  dir.list().forEach {
    if (it.contains("realm")) {
      File(dir, it).deleteRecursively()
    }
  }
}
```

これで削除されますので、再度初期化処理を行いましょう。
yarnが特定のnodeでしか使えないよと言われたら


**npm配下で管理されているyarnを削除しましょう。**

ローカルマシンでyarnを利用することがあまりないのですが、
`yarn -v`を打ったら特定のnodeにしかyarnないよ。と言われてしまった。
また、自分の環境ではnodeの管理にndenvを利用していることも今回の事象になる原因を作ってしまったかもしれません。

```sh:yarnのバージョン確認
$ yarn -v
ndenv: yarn: command not found

The `yarn' command exists in these Node versions:
  v6.6.0
```

これ多分ですが、これを叩いたせいだろうということ。
（全然、記録にないのですが。。）

```sh:たぶん叩いただろうコマンド
$ npm install yarn
```

公式では[npm からインストールする](https://classic.yarnpkg.com/en/docs/install)は~~非~~推奨
> ~~注意: npm から Yarn をインストールすることは一般的にはお勧めしません。~~

とのことで、たぶんどっかで叩いたせいだろうということ。
なので、npm管理配下にあるyarnを削除します。

どこにあるのか確認します。

```sh:格納先を確認
$ which yarn
/Users/hogehoge/.anyenv/envs/ndenv/shims/yarn
```
続けて。

```sh:削除コマンド
$ rm -rf /Users/hogehoge/.anyenv/envs/ndenv/shims/yarn
```

あとは、すでにbrewでyarnをインストール済みなら正常にバージョンが表示されるはず。

```sh:brewでインストールしたyarnのバージョンが表示される
$ yarn -v
1.5.1
```
＜linux コマンド5.ファイル操作＞

〇長いファイルの表示
$ less ファイル

表示中のコマンド

f,ｽﾍﾟｰｽ　１画面次
b
g	ファイルの先頭
G	ファイルの末尾
/	前方検索
？	後方検索
h	ヘルプ表示

〇並び替え

ファイルのフィールド２番目から４番目で並び替え
$ sort -k 2,4 file

〇文字列検索

行の初めが123のものを検索
$ grep ^123 file
Laravel5 Parse error: syntax error, unexpected '<', expecting end of file (View: 

```
Parse error: syntax error, unexpected '<', expecting end of file (View: 
```

blade.phpを作っていたらこんなエラーが、、、初心者には絶望的でした。

どうやらblae.phpには<?phpはいらないそうです。
外したらエラーが消えました。

参考文献
https://stackoverflow.com/questions/30631635/laravel-5-syntax-error-unexpected-extends-t-extends
＜linux コマンドA.正規表現＞

^文字列		------------(行頭の文字列)
文字列		--------------(行末の文字列)
.		---------------------(任意の１文字)
文字*		---------------(文字の０回以上の繰り返し)
[文字]		---------------([]内のいづれかの１文字)
[文字1-文字2]	------(文字1と文字２の間にある１文字)
Gradleをインストールして「Hello World」を出力するまで

# はじめに
いままでMavenばかりつかっていたので、Gradleを使ってみようと思った。
ここではGradleの導入から「Hello World」の出力までを実施する。

# 動作環境
- Windows10
- jdk 1.7.0

# Gradleの導入
## 最新のGradleを公式サイトから入手
[公式サイト](https://gradle.org/releases)から最新のGradleのzipファイルをダウンロード。
<img src="https://qiita-image-store.s3.amazonaws.com/0/178845/d6b2c728-b5e3-1497-e835-701bdb178932.png" width="50%">

## 任意の場所に解凍して環境変数を設定
下記の二項目を設定。

| 環境変数名 　      |       値  |
|:-----------------|------------------:|
| GRADLE_HOME            |              解凍したフォルダパス |
| Path          |            %GRADLE_HOME%\bin |

## 動作確認
コマンドプロンプトを起動して「gradle -version」と入力。
下記のように応答があれば問題なくインストール完了。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178845/b009c7b5-7771-17bd-af1f-767286f12392.png)

# Javaアプリケーションプロジェクトを作成してHelloWorldを出力する
## Javaアプリケーションプロジェクトを作成
コマンドプロントを起動し、任意のフォルダで「gradle init -type java-application」を実行。
プロジェクトフォルダが作成される。

## HelloWorldを出力
作成したプロジェクトフォルダに移動して、コマンドプロンプト上で「gradle run」を実行。
下記のように「Hello World」と出力されるはず。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178845/55d32136-e555-5c83-b4ea-6e72d6d8432e.png)

以上です。
行儀の悪いphpでのStripe課金の実装方法：

諸事情でStripeのSDKを使えなくて、サクッとStripeでphpで実装する。非常に行儀悪いですが、とりあえず、1000円決済する例。pk_test_YOUR_KEYやsk_test_YOUR_API_KEYはよしなに書き換えてください。

```html:index.html
<html>
<form action="pay.php" method="POST">
<script
  src="https://checkout.stripe.com/checkout.js" class="stripe-button"
  data-key="pk_test_YOUR_KEY"
  data-amount="1000"
  data-currency="jpy">
</script>
</form>
</html>
```



```php:pay.php
<?php

$result=stripe_charge( "sk_test_YOR_KEY" , $_POST["stripeToken"] , 1000 );

if ("succeeded"===$result["status"]){
    echo "<h1>OK</h1>";
}else{
    echo "<h1>FAILED!</h1>";
    var_dump( $result );
}

function stripe_charge(  $apiKey , $token , $amount ){
    
   $p=popen( 
    "curl https://api.stripe.com/v1/charges "
   ."-u ".$apiKey.": "
   ."-d amount=".intval($amount)." "
   ."-d currency=jpy "
   ."-d description=\"Example charge\" "
   ."-d source=".escapeshellarg( $token ) , "r");
   $result=json_decode(fread( $p , 65536 ),true);
   pclose( $p );
   
   return $result;
}


```

Stripe.js と php とcurl_exec使うと上手くいかないらしいって、stackoverflowでゆうてたので、面倒くさくなって、curlを生で打ちました。

https://stackoverflow.com/questions/32430652/errors-when-making-a-stripe-charge-using-custom-curl-and-php-code

#なんでこんな行儀悪いコードがいるの？
昔から使い続けていた、さくらの共有レンタルサーバーでstripeを実装しようとしたけど、phpのバージョンが古すぎて、stripeのSDKが動作しない上に、curl_execでも動作しないのでこうなりました。
Storybookの階層化

Storybookは`storiesOf('src/Button', module)`とすると階層化出来て便利です。

```js
storiesOf('src/Button', module)
  .add('with text', () => (
    <Button onClick={action('clicked')}>Hello Button</Button>
  ))
  .add('with some emoji', () => (
    <Button onClick={action('clicked')}>😀 😎 👍 💯</Button>
  ))
```

しかし、プロジェクトが大きくなると毎回自分でパスを書くのは大変です。

`path.macro`を使うとビルド時に自動的にpathを設定出来ます。
詳しくは公式のサンプルを見るといいでしょう。

https://github.com/storybooks/storybook/blob/master/examples/official-storybook/stories/other-dirname.stories.js
私が今までに読んだ技術本を簡単に紹介する

## はじめに

プログラマーやSEとして成長したく、2017年から技術本を読むようになりました。
Web上で評判のいい本を選択して読んだからか、どれも非常に勉強になるものばかりでした。
まだ数冊しか読めていないですが、簡単に紹介します。

## 技術本の紹介

### リーダブルコード

★★★
基本的なプログラミングの作法を紹介している本。
プログラマーなら絶対に読むべき一冊。
変数の命名やコメントの書き方など、どんな言語にも適用できる内容となっている。
文体もラフで非常に読みやすい。

[O'Reilly Japan - リーダブルコード](https://www.oreilly.co.jp/books/9784873115658/)

### UNIXという考え方

★★★
UNIXの設計思想について書かれた本。
2001年発行だが、今読んでも全く色褪せない名書。どんなシステムにも応用できる。
面白くてページ数も少ないので、一気に読み進めること間違いなし。

[UNIXという考え方 | コンピュータ・一般書,UNIX,UNIX | Ohmsha](http://shop.ohmsha.co.jp/shopdetail/000000000309/)

### Team Geek Googleのギークたちはいかにしてチームを作るのか

★★★
Googleに所属している2人が様々なプロジェクトを経験して学んだ、開発チームでの人との関わり方について紹介している本。
チームで製品を開発している人は必ず読むべき1冊。
リーダー、メンバーのどちらが見ても意味のある内容になっている。
HRT(謙虚、尊敬、信頼)が大事！

[O'Reilly Japan - Team Geek](https://www.oreilly.co.jp/books/9784873116303/)

### エリック・エヴァンスのドメイン駆動設計(Quickly)

★★★
「ドメイン駆動設計(Domain-Driven Design, DDD)」という設計技法についての本。
設計についての考え方が素晴らしく、個人的には一番読んでほしい技術本。ただ、内容が難しい。自分も理解していない部分があるので一緒に議論したい。

Quickly版が無料で読めるので、まずはこちらを読むのがいい。

[Domain Driven Design（ドメイン駆動設計） Quickly 日本語版](https://www.infoq.com/jp/minibooks/domain-driven-design-quickly)

### Clean Code

★★
コードをきれいにするための作法を学べる。 [リーダブルコード] を面白いと感じた人はこちらもハマるはず。
後半はJavaのコードを載せているだけなので読まなくていい。

[Clean Code - アスキードワンゴ](http://asciidwango.jp/post/171118672245/clean-code)

### ハッカーと画家

★★
ベンチャー企業で大きな成功を収めた男、ポール・グレアムが [Web上で公開しているエッセイ](http://paulgraham.com/articles.html) を翻訳してまとめたもの。
システム開発で成功するためのノウハウを学べる。非常に際どいことが書いており、心に深く突き刺さる言葉が多い。
Lispというプログラミング言語の信者でもあり、読むとCommon Lispを触りたくなる。

各章ごとに独立した内容となっているので、つまらないと感じたら飛ばし読みすることもできる。
私の場合、「8章 スパムへの対策」はスパムメールフィルタの話で興味がなかったので飛ばした。

[ハッカーと画家 コンピュータ時代の創造者たち | コンピュータ・一般書,プログラミング・開発,その他 | Ohmsha](http://shop.ohmsha.co.jp/shopdetail/000000001697/)

### SQLアンチパターン

★★
SQLの悪いパターン(アンチパターン)とその解決策を25つ紹介している本。
アンチパターンには「闇雲ショットガン」や「外部キー嫌い」など面白い名前が付いていてとっつきやすい。
SQLの設計技法についての最初の1冊におすすめ。
悪いパターンだけでも良いパターンだけでもなく、どちらも紹介しているのがいい。

[O'Reilly Japan - SQLアンチパターン](https://www.oreilly.co.jp/books/9784873115894/)

### プログラミング作法

★
C言語のプログラミング作法について紹介している本。
もちろん他言語にも流用できる内容はあるが、C言語ならではの知識が多い。普段C言語を扱っているなら ★★★ だが、オブジェクト指向の言語を扱っているなら [リーダブルコード] や [Clean Code] を読む方がためになる。

[プログラミング作法 - アスキードワンゴ](http://asciidwango.jp/post/155982762075/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E4%BD%9C%E6%B3%95)

## おわりに

Scrapboxではもう少しだけ詳細に紹介しています。
https://scrapbox.io/uhooi-books/技術本

書評を書いたことがないのであまりわからないのですが、転載してはいけない情報がありましたら、すぐに削除するので教えていただければ幸いです。

本の画像を直接リンクで表示しているのですが、これも調べた限りでは大丈夫とのことでしたが、問題がありましたら教えていただきたいです。

## 参考リンク

- [新人プログラマに正月休み中を使って読んでみてほしい技術書をセレクトしてみた。 - Qiita](https://qiita.com/hirokidaichi/items/d30714f0698dcff1200f)
なぜGKEのノード自動アップグレードでアプリケーションサービスが停止するのか

## 概要
GKEに用意されている[ノードの自動アップグレード](https://cloud.google.com/kubernetes-engine/docs/node-auto-upgrade?hl=ja)は便利ですが、インスタンスの再起動を考慮していない構成・設定だとアプリケーションサービスが停止します。
解決している問題は少ないですがアプリケーションサービスが停止するケースと解決方法をまとめました。

## 環境
- Kubernetes(GKE): >= v1.6

## アプリケーションサービスが停止するケース
### Podの配置が偏っている
`spec.replicas: 2`のDeploymentを`apply`すると、以下の図のように1つのインスタンスに偏るケースが発生します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/62029/ad6aa7b2-5f01-656d-f206-5243d788f5b0.png)


ノードのアップグレードは1台づつ`kubectl drain`するため、`PodA`が同じタイミングで`terminate`されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/62029/ff6419dc-5e70-6fbe-b8aa-f52238683ae7.png)


この状態になると`PodA`と通信ができないので、アプリケーションサービスの停止につながります。

#### 解決方法
- [PodDisruptionBudget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/)を設定する
    - `kubectl drain`実行時に`maxAvailable`を設定することでPodの起動数を調整可能
    - `minAvailable`を利用する場合、`spec.replicas`の数値が小さいと`ALLOWED DISRUPTIONS`の数値が0になるので注意

    ![image.png](https://qiita-image-store.s3.amazonaws.com/0/62029/60aefcc4-2d71-b80f-2f25-93cfd7857a04.png)


- [PodAffinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity)を設定する
    - 必須ではないがアップグレード時間が短縮し、耐障害が向上

### Podの配置が偏っている（kube-dns）
`namespace=kube-system` のkube-dnsについても同様の問題が発生します（GKE v1.6で確認）。
前の問題と同様に`PodDisruptionBudget`を設定することは可能です。
しかしEvict処理で別インスタンスに移動したPodがなぜか`terminate`され、`kubectl drain`の処理がタイムアウトするまで処理が停止します。
これは`kube-dns-autoscaler`が独自に`kube-dns`のPodをコントロールしているためだと思います。

#### 解決方法
解決できていません。
kube-dnsに[`PodDisruptionBudget`の設定するIssue](https://github.com/kubernetes/kubernetes/pull/56059)もあるので将来的には解消されると思います。
kube-dnsの起動は数秒なので、10秒程度のダウンタイムを許容できるアプリケーションサービスであれば問題になりません。
`kube-dns`を`delete pod`することで、インスタンスを移動させる事も可能ですが、アップグレード中に再び偏る可能性があるので効果は薄いです。

### Statefulなアプリケーションの再起動処理が考慮されていない
これは単純に永続化が必要なデータにPersistentVolumeの設定がされていないミスや、`StatefulSets`なアプリケーション、ミドルウェアの初期化スクリプトが漏れているケースです。
例えばRedisClusterの場合、init-containersの処理でクラスターに復帰したり、リシャーディングするスクリプトが必要となります。
解決方法も個々の対応となるので本記事には記載しません。

### ノード数が3未満になっている
クラスターを作るときにノード数が3未満だと以下の警告がでます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/62029/cd2b851f-b10b-2fce-f2fd-0bad9d13dd2b.png)
理由が記載されいませんが、`n1-standard-16`のなどの高いリソースを持つマシーンタイプ2台でも同じ警告がでるため、リソース以外の理由が考えられます。

#### 解決方法
深く考えることをやめて、ノード数を3以上にする。

### その他のアプリケーションサービスが停止するケース
- ネットワーク関連のエラーが発生してしまう
    - Golangアプリで`getsockopt: no route to host`のエラーが発生
        - 名前解決まではできていたが詳しくは未調査

## 備考
- [Kubernetes: 複数の Node を安全に停止する (kubectl drain + PodDisruptionBudget)](https://qiita.com/tkusumi/items/946b0f31931d21a78058)
- [Use pod anti-affinity in kube-dns](https://github.com/kubernetes/kubeadm/issues/128)
- [kube-dns should be replicated more than two times](https://github.com/kubernetes/kubernetes/issues/40063)
- [[addons] Add PodDisruptionBudget for kube-dns pods](https://github.com/kubernetes/kubernetes/pull/56059)
[Java10]varとジェネリクスの併用に注意

# 0.はじめに

Java10で導入されたvar。
便利ではありますが、場合によってはハマる可能性もあり。

```java:サンプルコード
var list = Set.of(BigDecimal.ZERO, BigDecimal.ONE);
// このCollectorの型は？
var toList = Collectors.toList();
var list2 = list.stream().collect(toList);

// list2の型は何でしょう？ 正解：list<Object>
System.out.println(list2.get(0));
```
# 1.なぜこうなってしまう？

下記の条件を全て満たす場合、型が確定できないためにObject型になってしまいます。
①引数がない、または引数によって総称型の型が確定しない
②型引数を指定していない

# 2.ではどうする？

もっとも、回避自体は難しくないもので、検知が難しいわけではありません。
・型引数を指定する
・従来通り、varを使わないようにする

```java:サンプルコード1(型引数を指定する)
var list = Set.of(BigDecimal.ZERO, BigDecimal.ONE);
// このCollectorの型は？
var toList = Collectors.<BigDecimal>toList();
var list2 = list.stream().collect(toList);

// list2の型は何でしょう？ 正解：list<BigDecimal>
System.out.println(list2.get(0));
```

```java:サンプルコード2(従来通り、varを使わないようにする)

var list = Set.of(BigDecimal.ZERO, BigDecimal.ONE);

Collector<BigDecimal, ?, List<BigDecimal>>  toList = Collectors.toList();
var list2 = list.stream().collect(toList);

// itemの型は何でしょう？
System.out.println(list2.get(0));
```

ただし、このケースは「単にどう回避する？」という点ではなく
新しいvarという要素に対して「取り込むか？取り込まないか？どういう対応方針で統一するか？」という点が難しいところだと思われますが、はてさて。
WordPressをプラグインなしでAMP対応させる試み【その2:改良編】

[前回](https://qiita.com/Fujix/items/95119d00c34a0f19d448)はWordPressにプラグインを使わずAMPを導入するための試行錯誤をまとめましたが、そのままではなにかと表現力が低下したままのですので、改良をほどこしていきたいと思います。

##画像のクラスを保持する
前回は失われていたWordPress側で画像に付加されるクラスを保持する試みです。

テストしてわかったことはAMPで展開される画像```amp-img```は、同レベルの要素があるとそれを巻き込んで**画像が縦に伸び、テキストは裏側に回る**という動作をするということです。これは```figure```に対する```figcaption```でも例外ではありません。

そこですべての```amp-img```をラッパーに入れ、```figcaption```はそのラッパーレベルに持ち上げ、全体のラッパーにWordPressが付与するクラス（```.aligncenter```など）をそのまま移動します。

```php:amp-single.php
    ...省略...

    $content = preg_replace(
      '/<figure.*?class="(.*?)".*?><img(.*?>)<figcaption .*?>(.*?)<\/figcaption><\/figure>/i',
      '<div class="amp-figure \1"><div class="amp-img-wrapper with-caption"><amp-img layout="responsive"\2</div><div class="amp-caption wp-caption-text">\3</div></div>', $content);
    $content = preg_replace(
      '/<img class="(.*?)"(.*?)\/>/i',
      '<div class="amp-figure \1"><div class="amp-img-wrapper"><amp-img layout="responsive"\2></div></div>', $content);
    echo $content;
```

本文書き出しの前処理を少し変更し、```figure```と```img```を加工しています。
これにより、処理前は

```html
<figure class="wp-caption aligncenter" />
  <img src="ほにゃほにゃら"... />
  <figcaption class="wp-caption-text">はにゃらはにゃら</figcaption>
</figure>

<img class="aligncenter  wp-image-715" src="あにゃらあにゃら".../>
```

だったソースが、処理後

```html
<div classs="amp-figure wp-caption aligncenter">
  <div class="amp-img-wrapper with-caption">
    <amp-img layout="responsive" src="ほにゃほにゃら"... >
  </div>
  <div class="amp-caption wp-caption-text">はにゃらはにゃら</div>
</div>

<div classs="amp-figure aligncenter  wp-image-715">
  <div class="amp-img-wrapper">
    <amp-img layout="responsive" src="あにゃらあにゃら"... >
  </div>
</div>
```

となり、WordPressのレイアウト用クラスが有効かつamp-imgもくずれない構成になりました。あとはスタイルを当てるだけです。

##Search Consoleから強制クロールさせた方がよい？
公開から4日経過。実は昨日テストとして、AMP対応ページをSearch Consoleから強制クロールさせたページ群と、何もせずに放置する群に別けてみました。すると、どうやらクロールさせたものの方が早くインデックスに登録されている**雰囲気**。対象ページ数17のうち「インデックスに登録された AMP ページ数」は現在7となっています。もう少し様子をみてみます。

##公開から7日
おととい対象AMPページが全てインデックス登録されたことを確認。細かな更新を行って、やはりSearch Consoleからクロールされると反映は早い傾向はあるけども、そうじゃないページもほどなく更新されるので、ページ数も多いので今後は放置することに決定。

### 検索順位は？
今のところ変わらない。すでに食べログ直下まで行ってたし、結局大手もどんどんAMP対応しているのでね。もちろんアクセスも横ばいです。費用対効果ってどうなんでしょうか？
フロントエンド屋の商品の幅が広がるという意味ではよいかも。

##公開から約1ヶ月
一部のページで蓋をされていたサイトの上位にくることがある。ただし不安定。
価格.comの性能比較ページをスクレイピングする

[価格.com - ノートパソコン スペック検索・性能比較](http://kakaku.com/specsearch/0020/)
このページの情報をまるっと取得して、DataFrame化したい。

## 単純なテーブルの場合
```python
import pandas as pd

dfs = pd.read_html('http://kakaku.com/specsearch/0020/')
```

でDataFrameのlistを簡単に取得できる。
が、このページの場合はtableタグの中にtableタグが使われていたりしてうまく取得できない。

## Selenium + Beautiful Soupでスクレイピング
Seleniumでページ遷移しながら、Beautiful SoupでHTMLをパースして情報を取得していく。

```python
import time

from bs4 import BeautifulSoup
import pandas as pd
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless')

driver_path = 'path/to/chromedriver.exe'

driver = webdriver.Chrome(executable_path=driver_path, chrome_options=options)

url = 'http://kakaku.com/specsearch/0020/'

product_list = []

while True:
    data = driver.page_source

    # HTMLをpythonのリストへ変換
    product_list = product_list + convert_list(data)
    
    # 次ページへのリンクをクリック
    driver.find_element_by_class_name('paging').find_elements_by_tag_name('a')[-1].find_element_by_tag_name('span').click()

    # 適切な待ち時間    
    time.sleep(1)
    
df = pd.DataFrame(product_list)
```

```python
def convert_list(data):
    html = BeautifulSoup(data, 'lxml')

    # table部分の取得
    table = html.find_all('table', attrs={'class': 'tblBorderGray02'})[0]

    # 商品レコードのみを抽出
    # 商品レコード行はclassがない
    records = table.find_all('tr', class_=False)

    product_list = []
    for record in records:
        record_dict = {}
        try:
            record_dict['id'] = record.select('input[type=checkbox]')[0].attrs['value']
            record_dict['manufacturers'] = record.find('td', class_='textL').find('strong').text
            record_dict['product_name'] = record.find('td', class_='textL').find('a').text
            record_dict['screen_size'] = record.find('label', attrs={'title': '液晶サイズ'}).text
            # その他必要な情報を取得する

        except:
            # 本来は適切なエラー処理を書く
            break
            
        product_list.append(record_dict)

    return product_list
```

||id|manufacturers|product_name|screen_size|...|
|:---|:---|:---|:---|:---|:---|:---|
|0|J0000025028|ASUS|ASUS VivoBook E203NA E203NA-232|WXGA (1366x768)|...|
|1|K0000980972|FRONTIER|FRT103(/KD) 2in1 PC 着脱式キーボード搭載/Win10 価格.com限定モデル|WXGA (1280x800)|...|
|2|K0000829506|Acer|Aspire One Cloudbook 11 AO1-131-F12N/KK|WXGA (1366x768)|...|

色々と粗はあるが、ひとまず目的は達成できた。
もしかしたらもっと簡単にできるかも……
状態遷移を用いたソケット通信ライブラリ

前回、状態遷移ライブラリについて書いてみました。

今回はその応用で作っているソケット通信ライブラリです。

以下にあります。
https://github.com/kumokumocc/WORK_/tree/master/classlib/cs/Sock



基本的にフォームになっていて、ログが表示されたり手入力でデータ送信できたりします。
右の方に空きスペースを用意していて、軽くボタン操作してデバッグという使い方もできます。

製品に載せる場合は、このフォームを非表示で作成して常にバックグラウンドで走らせ、何かあったときはViewしてログを見たり状態を確認します。
基本は継承するクラスを用意して、OnConnectとか、OnReceiveとかをオーバーライドして処理します。複数Createすることが可能なので、通信相手がいくつかあっても処理できます。

以下のプロジェクトで簡単な処理を書いてます。
https://github.com/kumokumocc/WORK_/tree/master/Projects/Projects/TCPIP

こんな感じでオーバーライドして作ります。

        public override void OnConnectSocket(bool IsConnect)
        {
            base.OnConnectSocket(IsConnect);
            if(IsConnect)
            {
                SetEvent(new Sock.SocketForm_Client.Event.ToNextStatus(new IDLE(this)));
                timer_STATUSSEND.Enabled = true;
            }
            else
            {
                timer_STATUSSEND.Enabled = false;
            }

さて、今回は状態遷移の話なので。

状態遷移図はこんな感じです。
![状態遷移図.png](https://qiita-image-store.s3.amazonaws.com/0/244460/8a76bbbc-9c80-4c2b-8887-2adc0632740c.png)



クライアント側の処理で、Close、Connecting、Connected状態。詳細な実装は省略しますが、基本的にググってすぐ出てくる程度のものです。

ポイントは破線で囲った部分。

このステータスは継承先で用意します。アプリケーション開発するときに作成します。
OnConnectのオーバーライドでToNextStatusというイベントをSetして、継承先で定義したステータスに遷移させることができます。

通信インターフェースは、みんなテキトーに作ってしまうので、だいたいおかしくなります。
通信確立まで3回くらいコマンド、レスポンスを繰り返したり、定周期でヘルスチェックコマンドを送ることになっていたり、コマンドA→コマンドB→コマンドCの順に送らないといけないことになっていたり。
とにかく滅茶苦茶なのがほとんど。

また、実装するとき一番面倒なのは、クローズ処理です。
アプリケーション側からクローズするだけでなく、相手側から切られる場合や、突然ケーブルを抜かれる場合。
悪意はなくても通信が不安定になって切れてしまう場合など、いろいろ起こります。

普通はどうするかというと、ソケットの接続状態とは別に接続状態を作ります。
すると、ソケット通信全体で２つのステータスを持ちます。
これは、2度手間な上に動作不安定な要因になりやすいという欠点があります。
2つのステータスをつなぐツギハギ部分を作る必要があるので、継ぎ目の部分が不具合を起こしやすくなります。

このライブラリでは、ToNextStatusというイベントを介してアプリケーションレベルでも１つのステータスで処理できます。シームレスな処理が可能になるため、動作が安定します。

もう１つ面白いのは、ConnectedBaseクラスを継承さえしておけば、クローズする処理が走ると自然な形でソケットを閉じて、勝手にClosed状態に戻ります。状態遷移図の赤い矢印のところを、放っておいても勝手にやってくれます。

シーケンスの途中でケーブルを引っこ抜いても安心です。

コードの再利用性を高めるポイントだと思いますが、シームレス、つまり、ライブラリ同士をつなぐ継ぎ目がないのが大事です。
製品は継ぎ目から壊れるものですが、ソフトウェアの不具合も同じです。

次回は、inifileでもやってみましょう。
canvasで複数のfont-familyを指定するとき

## 前置き
canvasのfont-familyの複数指定が一瞬わからなくなったので、自分用メモ程度に置いておきます。

##  説明
canvasでfontの指定をするときは以下のような指定をします。

```js
context.font = '600 10px sans-serif';
```
font-familyを複数指定しようと思ったのですが、、ふと、どう書けばいいんだろうと手が止まりました。
以下が正解のようです。

```js

context.font = '600 10px "游ゴシック体", "Hiragino Kaku Gothic ProN",sans-serif ';  
```
普通にcssのfont-familyの書き方まんまですが、一応共有しておきます。
Officeの色をRGBに分解する PowerShell編

COMのAPI経由でMS Office関連の操作を行う場合、色の設定に注意する必要があります。

Officeの場合、色は32bit整数で表現されるのですが、中の赤と青を示すビットの順番が、一般的なものと逆になっています。

```text
Officeの色の16進数表記
__BBGGRR
一般的な色の16進数表記
__RRGGBB
```

この記事では、Officeの色をRGBに分解して`System.Drawing.Color`等に変換してみます。

# 確認

まず、本当に中のビットの順番が異なるのか確認してみます。

今回はOfficeから色を取得する代わりに、VBAのRGB関数互換のVBのRGB関数で色の整数を作成し、`[Drawing.Color]::FromArgb`に渡してみます。

```posh
Add-Type -AssemblyName Microsoft.VisualBasic, System.Drawing

# Officeで使われている色
[int]$offceColor = [Microsoft.VisualBasic.Information]::RGB(240, 160, 80)

# intをそのまま受け取るオーバーロードはあるが……
# static System.Drawing.Color FromArgb(int argb)
[Drawing.Color]::FromArgb( $offceColor )
<#
R             : 80  # RとBが逆
G             : 160
B             : 240 # RとBが逆
A             : 0
IsKnownColor  : False
IsEmpty       : False
IsNamedColor  : False
IsSystemColor : False
Name          : 50a0f0
#>
```

結果からもわかるように、そのままだと赤と青が逆になってしまいます。

# 分解して.NETの色に変換する

本題のRGBに分解→変換をしてみます。

intをbyte単位に分解したい場合、地道に数値演算する手もありますが、System,BitConverterのGetBytesメソッドを使用すると簡単にbyte配列に変換できます。

PowerShellの記法も利用すると以下のように記述できます。

```posh
Add-Type -AssemblyName Microsoft.VisualBasic, System.Drawing, PresentationCore

# Officeで使われている色
[int]$offceColor = [Microsoft.VisualBasic.Information]::RGB(240, 160, 80)

# byte配列に変換[R,G,B,A] => 0,1,2番目を変数に代入（3番目以降は破棄）
[byte]$drwR, [byte]$drwG, [byte]$drwB, $null = [BitConverter]::GetBytes($offceColor)

# static System.Drawing.Color FromArgb(int red, int green, int blue)
[Drawing.Color]::FromArgb($drwR, $drwG, $drwB)
<#
R             : 240
G             : 160
B             : 80
A             : 255
IsKnownColor  : False
IsEmpty       : False
IsNamedColor  : False
IsSystemColor : False
Name          : fff0a050
#>


# static System.Windows.Media.Color FromRgb(byte r, byte g, byte b)
[Windows.Media.Color]::FromRgb($drwR, $drwG, $drwB)
<#
ColorContext : 
A            : 255
R            : 240
G            : 160
B            : 80
ScA          : 1
ScR          : 0.8713671
ScG          : 0.3515326
ScB          : 0.08021983
#>
```
Tilemapで期待しないのColliderのエッジが生じてしまった時の回避策

Unityの`Tilemap`において、`Tilemap`に`TilemapCollider2D`・`CompositeCollider2D`を付与したとき、次の画像のように予想外の`Collider`のエッジが生じてしまうことがあります。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/4125/577a687b-5115-db15-949f-56b89724e010.png)

![ss0.PNG](https://qiita-image-store.s3.amazonaws.com/0/4125/1da16663-83d2-1a07-f1a3-bd1f2a86fed7.png)


詳しい発生条件はわかっていませんが、私は次の環境で再現しました。

* Unity 2017.3.1p4
* Windows
* [2d-techdemos](https://github.com/Unity-Technologies/2d-techdemos)の次のTileを使ったとき
    * RuleTileのDungeonTile
    * TerrainTileのPBricks

この期待しない`Collider`のエッジが生じてしまった時の回避策を紹介します。

対象の`Tilemap`の親オブジェクトの`Grid`ゲームオブジェクト、その`Grid`コンポーネントの`CellGap`の値を調整します。

多くの場合、`CellGap`は、x,y,zすべて0に設定することが多いと思われますが、次の図のように非常に絶対値の小さな負の値を設定します。

![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/4125/feb4747d-de3a-57cd-240f-a15e569a9acd.png)

このように`CellGap`を設定することで、発生してしまった期待しないCollderのエッジを消すことが可能です。


おそらく、期待しないのColliderのエッジが生じてしまうこの現象は不具合かと思われますが、暫定的にこのように対処することで回避することが可能です。
読書メモ: xv6 book - Chapter 0: Operating System Interfaces

https://pdos.csail.mit.edu/6.828/2017/xv6/book-rev10.pdf

system call がインターフェースを決める。system call が発行されると、user space から kernel space への切り替えが起きて、操作を実行してまた user space にもどる。user space にいるときは、そのプロセスがアクセスできないメモリはCPU レベルの hardware protection によって保護される

xv6 のサービスは、
- process
- memory
- file descriptor
- pipe
- file system
からなる

## process

process は、memory (instruction, data, stack) と、kernel private な状態からなる。各プロセスには pid が割り当てられる

- fork: メモリをコピーして子プロセスを作る　fd table はコピーされ、file offset は共有される
- exit: プロセスを終了させ、リソースを開放
- wait: 子プロセスのどれかの exit を待ち、その pid を得る
- exec: ELF binary を実行. fd table はそのまま

- sbrk: メモリを n bytes 広げる

## file descriptor

- Refer to a kernel managed object, a process may read from or to.
- Abstracts files, pipes, devices

fd table は per process. fd -> resource

- read - fd から読む。file offset は、dup, fork で共有
- close - fd を後の open で再利用可能にする
- open - 使われてない一番小さい fd になる. 0 が closed なら 0 -> I/O redirection
- dup - duplicates an existing fd, and returns new one refering to the same underlying I/O object. Shares file offset.

`2>&1` は、2 は 1 の dup であるということ

## pipe

pipe とは small kernel buffer. 
pipe() は (read end fd, write end fd) を返す

read on a pipe は、write end に書かれるか、write end が close されるまで待つ

`A | B | C` というシェルコマンドは、

```text
  X
 / \
A   Y
   / \
  B   C
```
みたいな親子関係のプロセスになる。Y は B, C の終了を待って exit する

## file system

- chdir - change process's current directory. 相対パスのルートを変える
- mkdir - directory を作る
- open(..., O_CREATE) - data file を作る
- mknod - device file を作る device file かは file metadata で区別
- fstat - file 情報. stat.h は以下からなる
    - type - ファイルタイプ
    - dev - disk device
    - ino - inode. ファイルの実体に対応。パスは複数持てる
    - nlink - #links to file. 複数のパスをもつ場合 > 1
    - size - size in bytes
- unlink - 名前を消す。link count が 0 かつそれを指す fd がないとき実体を消す
VCCW3.18.0 に、MySQL5.6 を入れる

- 整形は後日

# 環境
- Mac OS X 10.13.3
- Vagrant 2.0.1
- VirtualBox 5.2.6
- VM内での話だし、この情報いらなくね？

# Commands
- '#'で始まるコマンド行はホストでの作業
- '$'で始まるコマンド行はゲストでの作業

## Vagrant up
```
# cd <vagrant_dir>
# vagrant up --no-provision # このprovisionは、msyql5.7向けなので、現時点では実行しない
# vagrant ssh
```

## mysql5.7削除
```
$ sudo /etc/init.d/mysql stop
$ sudo apt-get remove --purge mysql-server* mysql-common
$ sudo apt-get autoremove --purge
$ sudo rm -r /etc/mysql
$ sudo rm -r /var/lib/mysql
```
## mysql5.6インストール
```
$ sudo add-apt-repository 'deb http://archive.ubuntu.com/ubuntu trusty universe'
$ sudo apt-get update
$ sudo apt-get install mysql-server-5.6
$ sudo service mysql start
$ sudo apt-get install python-mysqldb # 入れておかないと、Provision実行時に 'The MySQL-python module is required.' というエラーが出て止まる
```
## provisionファイル修正
mysqldの設定ファイルの位置が、5.6以前と5.7以降とで異なっているようなので、provisionファイルを書き換える

```
# vi <vagrant_dir>/provision/playbooks/middleware.yml
-
line11:
  dest: "/etc/mysql/mysql.conf.d/mysqld.cnf"
    ↓
  dest: "/etc/mysql/my.cnf"
```
## provision実行
```
# vagrant provision
```

# 結果
たぶんこれで動いてる

# 参考記事
- [Ubuntuでmysql\-serverを完全に削除する方法 \| あずみ\.net](https://a-zumi.net/ubuntu-mysql-server-purge/)
- [Ubuntu14\.04 に mysql 5\.6 を再インストールした \- てしりこじり](http://tesiri.hateblo.jp/entry/2016/04/08/162118)
- [Ansible の mysql\_variables モジュールのメモ \- Qiita](https://qiita.com/raki/items/b7f1c47d004ef0fd8ed9)
- [Ubuntu 16\.04へMySQL 5\.6をインストールする方法 \- Qiita](https://qiita.com/tabimoba/items/cfa20294390e58ff478f)
AWSのEC2でAmazonLinux2を使ったときのメモ

#はじめに
ＥＣ２インスタンスを作る時に新しくAmazonLinux2が選択出来るようになりました。
今までのAmazonLinuxは現行が最終バージョンとなりアップデートは無いみたいです。
ので、今から新規でインスタンスを作るときはこちらを選択していくことになると思います。

#どう変わったの？
基本的に同じくcentosベースなのですが、仕様や使い勝手の面で変わってます。

###その1、Centos7ベースになった
7ベースなのでsystemコマンドもsystemctlになってます。
yumで入ってくるリポジトリとかも基本的に7準拠。

###その2、リポジトリが変わった
個人的に一番変わったところなのですが、amazon-linux-extrasリポジトリで管理するものが出てきました。

```console:example
[ec2-user@ip-xxx ~]$ amazon-linux-extras list
  0  ansible2   disabled  [ =2.4.2 ]
  1  emacs=latest  enabled  [ =25.3 ]
  2  memcached1.5   disabled  [ =1.5.1 ]
  3  nginx1.12=latest  enabled  [ =1.12.2 ]
  4  postgresql9.6   disabled  [ =9.6.6 ]
  5  python3=latest  enabled  [ =3.6.2 ]
  6  redis4.0   disabled  [ =4.0.5 ]
  7  R3.4   disabled  [ =3.4.3 ]
  8  rust1   disabled  [ =1.22.1 ]
  9  vim   disabled  [ =8.0 ]
 10  golang1.9   disabled  [ =1.9.2 ]
 11  ruby2.4   disabled  [ =2.4.2 ]
 12  nano   disabled  [ =2.9.1 ]
 13  php7.2   disabled  [ =7.2.0 ]
 14  lamp-mariadb10.2-php7.2=latest  enabled  [ =10.2.10_7.2.0 ]
```

というようにamazon-linux-extrasのリストにあるものはここからパッケージを入れる感じです。（自分のＥＣ２なのでいくつか入れてますが・・・14番enableにするだけでlamp環境イッパツで構築出来るの楽。ただしdbはagentだけ入るという・・・RDS使えということか）
入れるときはenableに。

```console:example2
[ec2-user@ip-xxx ~]$ amazon-linux-extras install ruby2.4
```

これで11番のrubyがインストールされます。
詳しい情報とかは

```console:example3
[ec2-user@ip-xxx ~]$ amazon-linux-extras info ruby2.4
ruby2.4 recommends ruby                       # yum install ruby
ruby2.4 recommends ruby-irb                   # yum install ruby-irb
ruby2.4 recommends rubygem-rake               # yum install rubygem-rake
ruby2.4 recommends rubygem-json               # yum install rubygem-json
ruby2.4 recommends rubygems                   # yum install rubygems
```

てな感じでセットになっているパッケージが分かるわけです。
ちなみにここにないものは今まで通りyumなり何なりで普通に入れます。

###その他ちょっとひっかかった所

タイムゾーン合わせが変わっていて手間取りました。

```console:example4
[ec2-user@ip-xxx ~]$ timedatectl set-timezone Asia/Tokyo
```

これだけで日本に合わせられます。今まではclock開いて編集してた感ありますが、より簡単になりました。

#おわりに
とりあえずまだまだ相違点ありそうだ・・・じっくり触っていこう。
jest内でassertを使う

```js
const assert = require('assert');

test('expect', () => {
  expect(1 + 1).toBe(3)
})

test('assert', () => {
  assert.equal(1 + 1, 3)
})
```

以下のようにexpectと同じように正しくエラーが表示され、エラー数も同様にカウントされる。

![スクリーンショット 2018-03-22 22.54.01.png](https://qiita-image-store.s3.amazonaws.com/0/15319/f6421cd0-1a44-5d59-44e4-33b913c49c4b.png)

正しく修正すると以下。

![スクリーンショット 2018-03-22 22.55.14.png](https://qiita-image-store.s3.amazonaws.com/0/15319/60febc40-6813-e21a-8d59-4c1957c09f3a.png)

## 参考

https://github.com/facebook/jest/blob/0580b5bbd5cdf5eff8cd2e793c5bcbe7a2396de1/integration-tests/failures/__tests__/node_assertion_error.test.js
MariaDB の Maxscale のライセンスについて

# MaxScale のライセンスについて

パフォーマンスもよく設定も簡単なMaxscaleですが、残念ながらライセンスで利用に制限があります。
＃オープンソースではなく無制限に使えるわけではありません。

ライセンスの原本はこちらです。
https://github.com/mariadb-corporation/MaxScale/blob/2.2/LICENSE.TXT

注意が必要なのは、以下の部分です。

```
Additional Use Grant: You may use the Licensed Work when your application
                      uses the Licensed Work with a total of less than three
                      server instances for any purpose.
```
サーバー(ここではMySQLやMaxscale)が3台未満の場合にのみ無料で利用できます。

しかし、この制限には期限があります。

```
Change Date:          2020-01-01
```

2020年1月1日以降は、この制限はなくなりGPLとして利用が可能になります。
Go の入れ子の配列の構造体をポインタにするか、値渡しにするか？

業務でGoプログラミングをする必要があった。過去にTerraform に貢献をしたこともあったが、ちゃんと理解しているかはとても怪しいものだ。この際しっかりと理解して生産性を高めたい。

業務では、複数の構造体が入れ子構造になったもので、頻繁に出てくるタイプのものだ。

```go
type Team struct {
	Id         string
	Challenges *[]Challenge
}
type Challenge struct {
	Id        string
	Histories *[]History
	Logs      []Log
}
type History struct {
	Id string
}
type Log struct {
	Message string
}
```

大抵のインターネットのコードでは、`Challenge` の `Histories` のようにポインタ渡しになっている。どういうときに値渡しとポインタ渡しを使うのだろう？　また、コードを書く時の注意点はなんだろうか？

# 構造体のポインタと値渡しの違いと使い分け

ポインタと値渡しの違いと使い分けは明確で、ポインタだとアドレスが渡る。値渡しだと、データがコピーされて渡る。だから、関数の引数として、ポインタ渡しにすると、関数の方で変更されたら、変更が反映される。値渡しだとコピーが渡されるので、関数で値を変更しても、元のアドレスにある構造体の値に変化がない。

構造体が大抵はポインタ渡しになるのは、構造体なのでサイズが大きいのでコピーのコストが馬鹿にならないから。ポインタなら、参照が渡るだけなので、コストが大したことないと言える。だから、たいしてコストのかからない string や int は大抵は、ポインタではなく、参照渡しになっている。string でサイズがもし馬鹿でかかったらポインタでもよいのだろう。

# 構造体の初期化と値の変更

構造体の初期化はこんな感じで書ける。

```go
	challenge := &Challenge{
		Id: "1",
	}
	challenges := []Challenge{
		*challenge,
	}
	team := &Team{
		Id:         "1",
		Challenges: &challenges,
	}

```

ちなみに、Challenge の部分を変更したい場合、例えば新しい要素を追加したい場合は、`append` 関数が使える。

```go
	newChallenge := append(*team.Challenges,
		Challenge{
			Id: "2",
		})
	team.Challenges = &newChallenge
```

ちなみにChallenge の中にもさらに入れ子でHistory があるのでこれも更新する必要があるが基本的に同じ。
range で回して、特定の History を更新したい場合のロジック。一つ重要なポイントは、`*[]History` つまり、ポインタの属性は、初期値がnil になる。通常の型は、初期化の場合それぞれの型の ZERO の値がセットされる。例えば int なら 0 とかになる。ポインタの場合はそれがnilなので、例えば、`append` を使うときに引数がnilだったらパニックになるので、nil チェックをしてあげる必要が生じる。参考までに、Log の方は、値渡しの[]Log の型にしてみたので、nilチェックは不要だ。ただし、構造体が大きいと、コピーの負荷が大きくなる。

```go
	currentChallenges := *team.Challenges
	for i, v := range currentChallenges {
		if v.Id == "2" {
			var newHistories []History
			if v.Histories != nil {
				newHistories = append(*v.Histories,
					History{
						Id: "1",
					})
			} else {
				newHistories = []History{
					History{
						Id: "1",
					},
				}
			}
			// newHistories = append(*v.Histories, History{Id: "1"})  // This code cause null pointer panic
			newLogs := append(v.Logs, Log{
				Message: "New Message",
			})

			currentChallenges[i].Histories = &newHistories
			currentChallenges[i].Logs = newLogs
		}
	}
	team.Challenges = &currentChallenges
```

# 結論

構造体の入れ子の場合、統一性、コピーの手間を考えると、ポインタ渡しを基本にしたほうがよさげだ。ただ、nilチェックは必要になるので、忘れないようにしよう。

これで、構造体で配列で入れ子などのややこしい構造であっても、ポインタと値渡しを使い分ける方法が理解できた。

# 参照

* [今回のサンプルコード](https://github.com/TsuyoshiUshio/structspike/blob/master/main.go)
* [配列、スライス（と文字列）：'append'の動作原理 (Arrays, slices (and strings): The mechanics of 'append')](https://www.ymotongpoo.com/works/goblog-ja/post/slices/)
* [Range](https://github.com/golang/go/wiki/Range)
* [Go言語　スライスのappendについて ](http://kobegdg.blogspot.jp/2013/01/goappend.html)
* [Append: The build-in function](https://blog.golang.org/slices)
TensorFlowで機械学習を試してみた

# 1. TensorFlow導入

## 1-1. Python 3.6
まずはTensorFlowが動く環境を整えるため、
Python 3.6をインストールする。

ダウンロードするためのリポジトリを準備。
`sudo yum install ius-release-1.0-15.ius.centos7.noarch.rpm`

Python 3.6をインストール。
`sudo yum install python36.x86_64`

TensorFlowをダウンロードするためのpipをインストール。
`sudo python3.6 -m ensurepip`
`sudo python3.6 -m ensurepip --upgrade`

## 1-2. TensorFlow
本体を入れていきます。

```
sudo python3.6 -m pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.6.0-cp36-cp36m-linux_x86_64.whl
```


# 2. 動作確認
下記コマンドを打ち込んでpython入力モードへ切り替える。
`python3.6`

```
import tensorflow as tf
hello = tf.constant('Hello World')
sess = tf.Session()
print(sess.run(hello))
```
Hello Worldと表示される。
WindowsでChainerを導入するための Visual Studio Build Tool 2015 が見つからず困ったときは

# 本日は

GPU環境下でChainerを導入する（Cupyが有効になる）ときに出てくる Visual Studio ないしは Visual Studio Build Tools ですが，書籍・参考書を含め 2015 で説明している内容が多いです．

ところが，この記事を書いているときはすでに２０１８年．Visual Studio，Build Tools の２０１５年版のダウンロードサイトはいつの間にか２０１７の案内になっています．インストールのUIも変わってしまい，Chainer の導入の際に困惑してしまいますね．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/135978/269e5346-36cf-abe5-72e5-db359fe31c9c.png)

本日は２０１５年版で書かれている記事などを２０１７年版でのものに読み替える方法について紹介します．ここでは Build Tools を用います．

# 前提

GPUがついたWindows 10 の PC で CUDAとかcuDNN とかは導入・インストール出来たんだけれどもBuildTools周りがわかっていない状態．

# Build Tools の導入

1. http://landinghub.visualstudio.com/visual-cpp-build-tools に飛びます．そうすると上で張り付けたサイトがでてきます．この時点で不安になってしまいますが，英語をよく見ると次の文言が書いてあります．

>  The installer includes most updates of the MSVC compiler toolset from Visual Studio 2017. The installer also includes the MSVC compiler toolset from VS 2015 Update 3.

どうやら VS 2015 のツールセットが入ってるっぽいです．希望の光が見えてきました．
2. 紫色ででっかく書かれている https://aka.ms/BuildTools をクリック．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/135978/fabee018-e4ad-2d2a-e251-09ab9a57048a.png)
3. Build Tools for Visual Studio 2017 をダウンロード
![image.png](https://qiita-image-store.s3.amazonaws.com/0/135978/5185a8ae-4280-7d8a-bb6d-07facc683ccc.png)
いろいろダウンロードの候補がありますが，ページ全体の後半に上の画像で示した部分が見つかるはずです．
4. ダウンロードしたインストーラーを起動
何もかんがえず無心にインストーラをたたきます．ここで「たたく」というのは物理的にたたくのではなく，起動するという意味です．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/135978/5b2dc1ab-8d7f-4a54-ba79-389133d3fccb.png)
5. インストーラのUIが出てきたら画面左上にあるVisual C++ Build Toolsを選択します．
 ![image.png](https://qiita-image-store.s3.amazonaws.com/0/135978/9513afe3-fe29-06fd-b1c9-5782db268c94.png)
6. デスクトップ用のVC++ 2015.3 v140 ツールセット (x86 x64) にチェックを入れる．
 ![image.png](https://qiita-image-store.s3.amazonaws.com/0/135978/cfc2773f-d2bf-dc5b-ff07-ef50597b1398.png)
7. 右下のインストールボタンを押します．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/135978/aecbeff5-8dd9-e124-beb0-ebd900a7af19.png)

これで準備が整ったはずです．そのはずです．

# 必要なものを確認

`C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin`

が存在するかを確認．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/135978/15dbd28d-6f80-72a1-6f0d-2ca2772796cd.png)

見つかればおめでとうございます．あとは環境変数のPathで `C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin` を追加すればOKです．

# Cupy導入

CUDA cuDNN は導入しましたか？

Cupy，Chainerを導入しましょう．コマンドプロンプトを起動して次を実行します．

```shell-session
> pip install cupy
```

最新版のCupyはインストールに時間がかかります．不安な気持ちを抑えて待ちましょう．

# Chainer導入
あと一歩です．

```shell-session
> pip install chainer
```

ここまでエラーメッセージがなかったら正常にインストールされていると思います．
では皆さん．よいChainerLifeを．
ktlintに入門してみた（LT会資料）

# ktlint？
<img width="100" alt="05311367c073c20fba1801b528655d74.png" src="https://qiita-image-store.s3.amazonaws.com/0/995/32310e45-0573-8542-705e-e0118d442620.png">

・Kotlinの静的コード解析（Linter）
　https://ktlint.github.io/

コードのフォーマットをいい感じに整えてくれるやつ

---
# 例: 1

```kotlin
if (condition){
 // do something
}
```

↓ :relaxed:

```kotlin
if (condition) {
 // do something
}
```

---
# 例: 2

```kotlin
val count = 10
Log.d("count", "count: ${count}")
```

↓ :blush:

```kotlin
val count = 10
Log.d("count", "count: $count")
```

---
# Standard rules
https://github.com/shyiko/ktlint#standard-rules

EditorConfig
→独自の設定も可能！
https://github.com/shyiko/ktlint#editorconfig

---
# 導入方法
```groovy:app/build.gradle
+ configurations {
+    ktlint
+ }

+ dependencies {
+   ktlint "com.github.shyiko:ktlint:0.20.0"
+ }

+ task ktlint(type: JavaExec, group: "verification") {
+    description = "Check Kotlin code style."
+    classpath = configurations.ktlint
+    main = "com.github.shyiko.ktlint.Main"
+    args "src/**/*.kt"
+    // to generate report in checkstyle format prepend following args:
+    // "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/ktlint.xml"
+    // see https://github.com/shyiko/ktlint#usage for more
+ }

+ check.dependsOn ktlint

+ task ktlintFormat(type: JavaExec, group: "formatting") {
+    description = "Fix Kotlin code style deviations."
+    classpath = configurations.ktlint
+    main = "com.github.shyiko.ktlint.Main"
+    args "-F", "src/**/*.kt"
+ }
```

参考 : https://github.com/shyiko/ktlint#-with-gradle

---
# 導入後

`./gradlew ktlint`
→ スタイルのチェック

`./gradlew ktlintFormat`
→ スタイルをフォーマット

---
# ビルド時にフォーマットが走るように

```groovy:app/build.gradle
android {
  ...
 
 applicationVariants.all {
    ktlintFormat.execute()
  }

  ...
}
```

※デバッグビルド時だけ実行するようにしたほうがいいかもしれない。

---
# DEMO

![3626451a73e26a9e3455daeafa4d7d86.png](https://qiita-image-store.s3.amazonaws.com/0/995/f5a5a039-70ab-ab7c-80ac-bb8c7e64ca88.png)

↓ ビルド実行後

![e50d57c27e0455c0ee9c68e4e72f446f.png](https://qiita-image-store.s3.amazonaws.com/0/995/3987e2aa-3e64-3e0f-4759-d79cf96578da.png)

---
# まとめ
- フォーマットが整うとレビューなども楽になって、捗るかもしれない :relaxed:
- Dangerと組み合わせられるといいかもしれない :rocket:

- Android Studioのコードフォーマットとあまり違いがわからなかった :sweat_smile:



---
# 参考資料 :bow: 
https://ktlint.github.io/

https://qiita.com/kafumi/items/1a9f59d6f845808604df

https://speakerdeck.com/kaelaela/what-i-talk-about-when-i-talk-about-ktlint
iCloudバッチを作ろう 2-(2): 複数のチェック項目をall(list)で取る

# iCloudバッチを作ろう 2-(2): 複数のチェック項目をall(list)で取る

## 経緯・理由

- [こちら](https://qiita.com/urahito_solution/items/74bf543e85231e06a25d#%E7%B5%8C%E7%B7%AF%E7%90%86%E7%94%B1)を参照

## 目的・実装予定の機能

### 目的

- [こちら](https://qiita.com/urahito_solution/items/74bf543e85231e06a25d#%E7%9B%AE%E7%9A%84%E5%AE%9F%E8%A3%85%E4%BA%88%E5%AE%9A%E3%81%AE%E6%A9%9F%E8%83%BD)を参照

### 機能

目次用記事を立てました→[こちら](https://qiita.com/urahito_solution/private/1af6c7543f2b95983fd5)

[＜＜ 最初の記事](https://qiita.com/urahito_solution/items/74bf543e85231e06a25d) | [＜ 前の連載記事](https://qiita.com/urahito_solution/items/0cbe0a5c49be7371cebe) | 次の連載記事 ＞ 

（※免責：上記の順番は記事の順番とは一致しない可能性が高いです。あらかじめご了承下さい）

## 今回の機能の解説

- ```all(list)```で「すべてのAND」を取りたいif文を削減する
- チェック内容も書きたいなら、```dict['item']=result```→```all(list(dict.values()))```で取る
- 応用編：```dict(key, bool)```の組み合わせで、「何に対しての条件か」を読みやすくする
- 補足編：逆に「すべてにOR」をかけたいなら、```any(list)```で解決

## ソースコード

### 「すべてのAND」を取りたいif文を削減する

```Python:すべてのAND.py
def is_file(self):  
	results = [] 
	results.append(self.org_path.exists()) 
	results.append(self.org_path.is_file()) 
	results.append(self.file_size > 0)  
	return all(results) 
```

#### all(list(dict.values()))を使った例

```Python:dictとall.py
def allow_file_copy(self, days_before, past_ng):     
	# チェック内容をdictとして記述（ログ用） 
	checks = {} 
	checks['past_ng_check'] = (not past_ng) 
	checks['valid_file_check'] = (self.is_file()) 
	checks['days_range_check'] = (self.is_target_day(days_before)) 
	
 
	# 結果のみ取り出し 
	results = list(checks.values()) 
	
 
	# すべてTrueでなければ対象外 
	if all(results) == False: 
		return self.file_size 
	
	self.allow_copy =  True 
	return self.file_size 
```

### 「何に対しての条件か」を読みやすくする

```Python:応用編.py
def make_parent_dir(path_obj, sub_dir=''): 
	path_sub = path_obj / sub_dir 
	results = {} 
	results['parent_exist'] = path_obj.exists() 
	results['sub_exist'] = path_sub.exists()         
	
	if results['parent_exist']:             
		if not results['sub_exist']: 
			path_sub.mkdir(exist_ok=True) 
	else:  
		path_sub.mkdir(exist_ok=True) 
	path_obj = path_sub 
	return path_obj 
```

#### 書いていてようやく気付いたのですが

この場合は以下の書き方で済むので、参考までに。

```Python:応用編-修正.py
def make_parent_dir(path_obj, sub_dir=''): 
	path_sub = path_obj / sub_dir 
	
	if not path_sub.exists(): 
		path_sub.mkdir(exist_ok=True) 
	path_obj = path_sub 
	return path_obj 
```

## まとめて解説

### list(bool)ならそのまま、dict(key, bool)ならvalues()で取り出してから

1つめ、2つめの例のように、単にすべてのAND/ORを取るだけなら、```all(list(bool))```/```any(list(bool))```で取ることができます。

- 参考： [要素の一括真偽判定 (all / any) | Python-izm](https://www.python-izm.com/advanced/all_any/)

念のため対応表を。

|チェック項目|すべてTrue|1個以上len(list)未満|0個|
|:---|:---|:---|:---|
|all(list)|True|False|False|
|any(list)|True|True|False|

### 「何に対しての条件か」を読みやすくする

上に当てはまらない、複雑な条件を書いたものが3つめの例です。
この時はdictで定義し、どの条件かをkeyで指定する形にしました。
これなら、日本語をkeyにおいても大丈夫だと思いますが、**バグの温床になりそうなので、取扱いには十分ご注意を。**