OmniAICreator/Qiita-1.07M huggingface dataset:
ローカル環境でgRPCをデバッグする方法

## gRPCって難しいですよね

こんにちは、jackです。

最近、業務で gRPC を使う機会がありました。
そもそも [**RPC**](https://www.wikiwand.com/ja/%E9%81%A0%E9%9A%94%E6%89%8B%E7%B6%9A%E3%81%8D%E5%91%BC%E5%87%BA%E3%81%97) ってなんぞやってところから **g** がついて、とっつきにくいなーと思ってしまいがちですよね。

## ローカル開発大変そう

と思った方も結構いるのではないでしょうか。実際少し調べてみるとどうやって手元で動かすのか紹介しているものが少なかったので今回はそちらを共有したいと思います。

結局なにを開発するにもそうですが、**手元で確認できたほうがなんか安心しますし、開発スピードもあがりますよね**。

## *更新：2019年1月
下記で紹介している `grpc_cli` を使わなくても、MacユーザーはBrewでのインストールが**おすすめ**です。

```sh
brew tap grpc/grpc
brew install grpc
which grpc_cli
```
こちらが成功したら「実際にデバッグする」セクションまで読み飛ばしてください。


## 実は意外と簡単！？

一見難しそうですが、やってみると意外と簡単です。
では、早速やっていきます。
まずデバッグには `grpc_cli` というツールを使います。

### **`grpc_cli` をインストールする** 

```sh
~/Desktop
❯ git clone https://github.com/grpc/grpc

~/Desktop
❯ cd grpc/

# dependenciesをダウンロード
~/Desktop/grpc
❯ git submodule update --init

# ビルド実行
~/Desktop/grpc
❯ make grpc_cli

~/Desktop/grpc
❯ cd bins/opt/

# grpc_cli executableを確認
~/Desktop/grpc/bins/opt
❯ ll
total 12336
-rwxr-xr-x  1 masanoriuehara  staff   5.3M Jun 21 23:35 grpc_cli
```

make時にエラーがでたら `protobuf` やら `gflags` やらが入ってない可能性があるので `brew install` しましょう。

`bins/opt` 配下に `grpc_cli` の Executable ができたら成功です。

### **gRPCサーバーを立ち上げる**

それでは実際にデバッグしたいgRPCサーバーを動かしましょう。
先ほどとは別のウィンドウでやってきます。

今回は簡単な例として、公式のこちらを使います。
https://github.com/grpc/grpc-go/tree/master/examples

```sh

~
❯ go get -u google.golang.org/grpc/examples/helloworld/greeter_server

~
❯ cd /go/src/google.golang.org/grpc/examples/helloworld/greeter_server

~/go/src/google.golang.org/grpc/examples/helloworld/greeter_server
❯ go run main.go
```

サーバーが立ち上がりました。
これで下準備は終了。

## 実際にデバッグ方法を紹介していきます


### **まずサービスの存在を確認する**

```sh
~/Desktop/grpc/bins/opt
❯ ./grpc_cli ls localhost:50051
grpc.reflection.v1alpha.ServerReflection
helloworld.Greeter
```
`ls` を使い、`helloworld.Greeter` とサービスが表示されました。
より詳細を見たいときは `-l` オプションを付けます。

### **サービスのメソッドを確認**

特定のサービスメソット詳細を見たい時はこのようにします。

```sh
~/Desktop/grpc/bins/opt
❯ ./grpc_cli ls localhost:50051 helloworld.Greeter -l
filename: helloworld.proto
package: helloworld;
service Greeter {
  rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
}
```

### **messageの定義を確認**
`type` を使うことで message の定義がわかりやすく表示されます。

```sh
~/Desktop/grpc/bins/opt
❯ ./grpc_cli type localhost:50051 helloworld.HelloRequest
message HelloRequest {
  string name = 1[json_name = "name"];
}
```

### **デバッグ Remote Call する**
実際にサービスを叩くには `call` を使います。

```sh
~/Desktop/grpc/bins/opt
❯ ./grpc_cli call localhost:50051 Greeter.SayHello 'name: "jack"'
connecting to localhost:50051
message: "Hello jack"

Rpc succeeded with OK status
```


### 以上
意外と簡単にできましたね！
これで **gRPC** も怖くない :muscle:
TwitterSDKのOAuth認証に失敗する

アプリ開発を始めたばかりですが、TwitterSDKのOAUTH認証で詰まったので、解決方法を共有しておきます。

##発生事象：TwitterSDK for Androidのマニュアル通りに実装するも、OAuth認証で失敗する。

エラーメッセージは以下。
<font color="red">twitter desktop applications only support the oauth_callback value 'oob'</font>

ぐぐったところ、callback URLを入れなければいけないとのこと。
apps.twitter.comで、アプリケーションにcallback URLを設定した。
すると、以下のエラーメッセージ

<font color="red">“The client application failed validation: Not a valid callback URL format.”</font>

さらにググると、2018年6月12日からcallback URLはセキュリティのため
必須パラメータに変更され、apps.twitter.comに登録してあるURLと、
APIコール時に指定するcallback URLは一致していなければならないとのこと。
https://twittercommunity.com/t/action-required-sign-in-with-twitter-users-must-whitelist-callback-urls/105342

###〇解決方法
TwitterSDKを使用する場合、デフォルトでは
twittersdk://
を指定することで解決できる。
今回はAndroidであったが、iOSやUnityも同様ではなかろうか。(未確認)
ElixirからPowerShellを起動する

Fukuoka.exの技術コミュニティで、アドバイザーズを担当してるtwibeeことenpedasiといいます。よろしくお願い致します。

# はじめに

Elixirの[「**System.cmd**」関数](https://hexdocs.pm/elixir/System.html#cmd/3)を使えば、外部コマンドであるOSのコマンドを実行することができます。それは、**Windows環境下**にあっても同じです

**大人の事情**でPowerShellコマンドを実行しないといけない場合は
どのようにすれば良いのでしょうか？

# Powershellも起動できる

いきなり結論ですが、シェルコマンドとしてPowershellを実行します。

```elixir
System.cmd "Powershell", ["pscript.ps1"]
```


# 作業フォルダ

作業フォルダには注意が必要です。

プロジェクトフォルダの直下にps1というフォルダを作成し、Powershellのps1
を置いてpowershellスクリプトを実行する例は、このようになります。

```elixir
System.cmd "Powershell", ["ps1/pscript.ps1"]
```

Powershellのスクリプトで、以下のようなコードを書いた場合はどうなるでしょうか？

```powershell:ps1/pscript.ps1
copy-item a.csv b.csv
```

これは、ps1フォルダの中が対象でなく、プロジェクトフォルダのa.csvを同フォルダのb.csvにコピーする挙動となります。

あくまで、作業フォルダの対象はプロジェクトフォルダということになります。

# おわりに

ElixirとPowerShell。相当異色な組み合わせですが、PowerShellのパイプラインはElixirと本質的に近いものがあり、意外と悪くはないと思います（個人の感想です）。

スケジューラである [elixir-quantum](https://github.com/quantum-elixir/quantum-core) を使えば、Windowsのタスクスケジューラと併用して、スケジューラを起動することも可能です。(fukuoka.exでのquantumの紹介事例は[こちら](https://qiita.com/kobatako/items/d7b404ba53f9a25ac5aa))

大人の事情で仕方がない場合も、華麗にソリューションしてしまいましょう！
JavaScriptでページタイトルとURLを取得（content_scriptsからbackground.js へデータをpost）

#はじめに
何度かQiitaの記事を書いていて、参考サイトのURLを書くのが面倒に思えてきたので、見ているページからQiitaに貼り付ける用のテキストを準備できるようにします。コピーするところまで行きたいところですが、今回は取得までです。

#document.title
JavaScriptでページのタイトルを取るには、document.title でいいのはすぐにわかったのですが、background.js からはどうも取得できない。ページで動作する content_scripts では取れてました。ここから background.js へデータを渡す方法を考えます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/262366/2feba411-92f3-ba83-7edd-c448c4d731a7.png)

#content_scriptsからbackground.js へデータをpost

runtime.Port と runtime.connect というのでやり取りができることが分かったので、右クリックメニュー選択時に、background.js から content_scripts にメッセージを送ると、ページのタイトルをURLを background.js へ戻すという仕組みで取得するようにしてみました。

```javascript:content_scripts
console.log("sample.js is loaded");
var myPort = browser.runtime.connect({name:"port-from-sample"});
var urlForQiita = "[" + document.title + "](" + document.URL + ")"
myPort.onMessage.addListener(function(m) {
	myPort.postMessage({title: urlForQiita});
});
```

```javascript:background.js
browser.contextMenus.create({
	id: "copyUrlForQiita",
	title: "copy url for qiita",
	contexts: ["all"]
});

var portFromSample
var urlForQiita
function connected(p) {
	portFromSample = p;
	portFromSample.onMessage.addListener(function(m) {
		urlForQiita = m.title;
    	console.log(urlForQiita);
	});
}
browser.runtime.onConnect.addListener(connected);

browser.contextMenus.onClicked.addListener((info, tab) => {
    if (info.menuItemId === "copyUrlForQiita") {
    	portFromSample.postMessage({action: "copyUrlForQiita"});
    } 
});
```

もう少し簡単にできるかと思ったのですが、以外と考えないといけないですね。ページのロード直後だと問題ないのですが、別のタブでページをロードするとそちらのデータしか取れなくなってしまっているので、その対応も必要そうです。タブ切り替えた時の対応はまた今度調べてみます。

#参考
[runtime.Port - Mozilla | MDN](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/Port)
加法準同型暗号を使って乗算する

## 加法準同型暗号とは

以下のように暗号化したまま加法が可能な暗号。

$$
E(a) + E(b) = E(a + b)
$$

ただし、$E(a)$は$a$の暗号文。
加法準同型暗号としてはPaillier暗号などが有名。

## Paillier暗号

1999年にPaillierによって発明された公開鍵暗号。[こちら](http://elliptic-shiho.hatenablog.com/entry/2015/12/14/213328)が詳しかった。
加法に加えて減法、定数倍もできる。

$$
E(a) - E(b) = E(a - b) \\\
n * E(a) = E(na)
$$

## Paillier暗号による乗算

Pailler暗号は加法準同型暗号なので通常は乗算を行うことはできないが、以下の等式を用いて秘密鍵をもつBobとデータをやり取りすることでAliceは乗算結果を得ることができる。

$$
ab = (a+r_a)(b+r_b) - ar_b - br_a - r_ar_b
$$

1. Aliceは乱数$r_a, r_b$を生成し、$E(a+r_a), E(b+r_b)$を計算してBob送信する.
2. Bobは$E(a+r_a), E(b+r_b)$を復号し、$(a+r_a)(b+r_b)$を暗号化してAliceへ送信する.
3. Aliceは受け取った$E((a+r_a)(b+r_b))$から$ar_b, br_a,r_ar_b$を引いて$E(ab)$を得る.

$$
\begin{array}{ccc}
Alice & & Bob \\\
E(a), E(b), pk & & sk \\\
 & \xrightarrow{E(a + r_a), E(b + r_b)} & \\\
 & \xleftarrow{E((a + r_a)(b + r_b))} & \\\
\end{array}
$$

一連の操作において、Bobに$a, b$を知られることなくAliceは$ab$を得ている。

## 実装

Paillier暗号は[こちら](https://github.com/mikeivanov/paillier)の実装を参考に少々手を加えた。

```python
import random
from paillier import *

# 準備
sk, pk = generate_keypair(32)

a, b = 3, 5
print(f'(a, b) = ({a}, {b})')

enc_a = encrypt(pk, a)
enc_b = encrypt(pk, b)

print('***** Aliceの処理ここから *****') 
# a, bに乱数を加えてBobへ送信
ra = random.randrange(0, pk.n)
rb = random.randrange(0, pk.n)
print(f'ra = {ra}')
print(f'rb = {rb}')

enc_a_plus_ra = e_add_const(pk, enc_a, ra)
enc_b_plus_rb = e_add_const(pk, enc_b, rb)

print('***** Bobの処理ここから *****') 
# 復号して乗算した結果を暗号化してAliceへ
a_plus_ra = decrypt(sk, pk, enc_a_plus_ra)
b_plus_rb = decrypt(sk, pk, enc_b_plus_rb)

prod = a_plus_ra * b_plus_rb
print(f'prod = {prod}')

enc_prod = encrypt(pk, prod)

print('***** 再度Aliceの処理ここから *****') 
# Bobから受信したデータからa*r_b, b*r_a, r_a*r_bを引く
enc_arb = e_mul_const(pk, enc_a, rb)
enc_bra = e_mul_const(pk, enc_b, ra)
enc_rarb = encrypt(pk, ra * rb)

enc_result = e_sub(pk, enc_prod, enc_arb)
enc_result = e_sub(pk, enc_result, enc_bra)
enc_result = e_sub(pk, enc_result, enc_rarb)

print(decrypt(sk, pk, enc_result))
```

```
(a, b) = (3, 5)

***** Aliceの処理ここから *****
ra = 940245986
rb = 1030728560

***** Bobの処理ここから *****
prod = 969138398988975785

***** 再度Aliceの処理ここから *****
15
```
5ちゃんねるをスクレイピングするライブラリを書いた

## repository
https://github.com/yuki-eto/pot-collector
５ちゃんねる…というより前身の2ちゃんねる…といえば壺のイメージがあったのでこういう名前にしてみました。
テストはまだ書いてません :-p

## 使い方
基本的には `sample/load_thread_articles.go` に書いてある通り書けば使える…はず。
（おわかりかと思いますが、5ちゃんねる側で仕様変更があった場合はその都度修正が必要かもです…）

```go

package main

import (
	"fmt"
	"strings"

	"github.com/yuki-eto/pot-collector"
)

func main() {
	const threadListURL = "https://krsw.5ch.net/idolmaster/subback.html"
	const threadBaseURL = "https://krsw.5ch.net/test/read.cgi/idolmaster/"
	const containsString = "本田未央"

	// *Board を作って
	board := potCollector.NewBoard()
	// *goquery.Document をもらう
	doc, err := board.LoadThreadListDocument(threadListURL)
	if err != nil {
		panic(err)
	}

	// HTML をパースして Board.Threads.List にスレッドを入れる
	if err := board.LoadThreads(doc); err != nil {
		panic(err)
	}

	// *Thread を受け取って bool を返すフィルタリング関数で Threads.List を
	// Threads.List をある程度弄ることが可能
	// 下記はスレッド名に特定の文字列が入ってるスレッドだけを取り出す例
	board.Threads.FilterThread(func(t *potCollector.Thread) bool {
		return strings.Contains(t.Title, containsString)
	})

	if board.Threads.Count == 0 {
		fmt.Println("do nothing...")
		return
	}

	for _, thread := range board.Threads.List {
		// 差分だけを取り込みたいときは、LoadArticleDocument() を呼び出す前に
		// thread.LastReadArticleID に1より大きい数を入れるとそこからの差分を取得できる
		// （何らかの手段で最後に読み込んだ番号を記録しておく必要がある）
		thread.LastReadArticleID = 1

		// スレッドURLを生成してアクセスし、*goquery.Document を受け取る
		// 取得するスレッドが多い場合はこのへんで goroutine とかを使うのもアリかもしれない
		// （節度を守って適切な並列数でやるべし）
		doc, err := thread.LoadArticleDocument(threadBaseURL)
		if err != nil {
			panic(err)
		}

		// HTML をパースして thread.Articles.List に書込内容を入れる
		if err := thread.LoadArticles(doc); err != nil {
			panic(err)
		}

		fmt.Printf("%d: %s (%d)\n", thread.ID, thread.Title, thread.LastArticleID)
		for _, article := range thread.Articles.List {
			if article.IsOver1000 {
				continue
			}
			fmt.Printf("%d: %s %v ID:%s\n", article.ID, article.Name, article.Date, article.UID)
			fmt.Println(article.Text)
			fmt.Println()
		}
	}
}
```

## 苦労した点
### 適切な設計がわからない
処理自体の実装はスラスラ進んだのだけど、ある程度進んでライブラリっぽい体裁を整える段階で、どういう粒度でファイルを分けるとか、どのポインタメソッドにどの処理を当てるかとかで結構悩んだ。

見た感じ golang の小さめのライブラリだと、ルートディレクトリに全部おいて同じ package にして、サンプルでディレクトリ切って package main にするみたいな感じが多そうだったのでそれに合わせた。

golang 書いててどのへんからちゃんと package 分けるとか未だに悩む気がしている（PHP の名前空間での同じような悩みを思い出した）。

とりあえず行き当たりばったりで自分だけが使えればいいやと思って作り始めたので、そもそも設計もクソもないというのはさておき。

### goquery
`*Document.Find()` で jQuery 風なクエリが使えるってだけで、（当たり前だけど）他の部分は完全に golang の世界観なんで、当然 jQuery かじった程度で扱えるというわけではない。
むしろ `Find()` で受け取った `*Selection` を扱うところからが本番で、GoLand なかったら完全に詰んでた。
タグがある場合とそうでない場合のケース分けがけっこう難しく、最終的には HTML を文字列でそのまま受け取り、必殺奥義 `regexp` で解決したところも結構ある。
MimeKitで.mboxファイル読んでみる

[Google Takeout](https://takeout.google.com/settings/takeout)とかでGMailのデータを取得すると、拡張子がmboxのファイルとして落ちてきます。
このmboxファイルは、電子メールのデータ(emlファイル)をそのままつなげたような構造になっていて、プログラムから簡単に読むことができます。
そうは言っても、自分でパースするのはめんどくさいので、[MimeKit](https://github.com/jstedfast/MimeKit)を使います。

## MimeKitのインストール
MimeKitはNuGetからインストールできます。
検索すると何種類か出てきますが、今回は、mboxファイルをパースするだけなので、MimeKitLiteで足ります。
Liteじゃ足りないこともしたいとか、大は小を兼ねると思っている人は、フルセットを入れておくのもよいでしょう。

## mboxファイルを読む
入れてしまえば、あとは公式のドキュメントに書いてあること([Parsing messages](http://www.mimekit.net/docs/html/Parsing-Messages.htm))と同じ感じですが、一応、コマンドライン引数で受け取ったファイルから読み込んで情報を表示するコードを置いておきます。

```cs:Program.cs
using System;
using System.IO;
using System.Linq;
using MimeKit;

namespace MboxRead
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Usage: MboxRead <file>");
                return;
            }

            var inputpath = args[0];
            using (var stream = File.OpenRead(inputpath))
            {
                // パーサを生成
                var parser = new MimeParser(stream, MimeFormat.Mbox);
                while (!parser.IsEndOfStream)
                {
                    // メッセージをパースする
                    var message = parser.ParseMessage();

                    // メッセージを使って何かする
                    Console.WriteLine("[From]");
                    Console.WriteLine(string.Join(Environment.NewLine, message.From.Select(a => a.ToString())));
                    Console.WriteLine("[To]");
                    Console.WriteLine(string.Join(Environment.NewLine, message.To.Select(a => a.ToString())));
                    Console.WriteLine("[Subject]");
                    Console.WriteLine(message.Subject);
                    Console.WriteLine("[TextBody]");
                    Console.WriteLine(message.TextBody);
                    Console.WriteLine("[HtmlBody]");
                    Console.WriteLine(message.HtmlBody);
                    Console.WriteLine("[Attachments]");
                    Console.WriteLine(string.Join(Environment.NewLine, message.Attachments.Select(a => a.ContentDisposition)));
                    Console.WriteLine();
                }
            }
        }
    }
}
```

### サンプルコードの作成環境
- C#
- .NET Framework 4.7.1
- コンソールアプリケーション
- Visual Studio 2017 15.7.3
- Windows 10 Home 64bit
UIStackViewで幅を指定しないでViewを半分にする方法 

**ここで大事なのは中の部品の幅の指定をしないということとViewということです。**
※labelやButtonは均等になると思うので勝手に高さ指定されるので、制約のかけかたにもよると思うのですが…

**何を言っているかというと横の制約、縦の制約変えても半分になるようにするということ。**

今回は縦だけですが…

見た方が早いと思うのでgif載せます。
※これスペース空きすぎと思う方もいるかと思いますが、StackViewのスペースは調節すればいいのでspaceを0にすれば行いたいことも行えるかと思います。

|![StackViewhannbunn.gif](https://qiita-image-store.s3.amazonaws.com/0/133940/d1d9f0da-43f3-b313-a488-a8e08ba3879b.gif)|
|:-:|





※いやいやこれどうせViewだけでしょっととか使い道どうせないでしょうって方に。では一つのViewにすればいいんです。使いたいものをStacViewで包むのです！最終的に均等にしたいもののみ高さを指定しなければできるはずです。

説明:

ViewとViewをStackViewで包んで、StackViewのスペースを開けてその真ん中にViewを入れ、そのViewの高さを今回は1にして中央の指定にすれば:snowman2:


下の高さ変えたりするとこんな感じです。

|![sample1.gif](https://qiita-image-store.s3.amazonaws.com/0/133940/f82cf741-b487-bc5c-d339-9cb5ce83f4a7.gif)|
|:-:|
PythonでNPBのチームデータが取りたい。(選手情報取る。荒削り）

wikipediaからざっくりと選手の名前を取得する。
選手名以外も取れちゃってるからもう少し加工したい。

```get_player.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import bs4
import requests

url = requests.get('https://ja.wikipedia.org/wiki/%E5%8D%83%E8%91%89%E3%83%AD%E3%83%83%E3%83%86%E3%83%9E%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%BA%E3%81%AE%E9%81%B8%E6%89%8B%E4%B8%80%E8%A6%A7')
url.raise_for_status()
if (url.status_code == 200):#htmlのステータスを確認して正常なら実行
    soup = bs4.BeautifulSoup(url.text,'html.parser')
    elems = soup.select('a')
    for elem in elems:
        print(elem.string)
else:#errorだったときにURLが取れてなかったエラーがでる。
    print("URL error!")
```
ボリュームライセンスのMS Officeがアップデートできなかった

# 元々の問題
Word2016で文章校正が上手く動かなかったので調べてみると、どうもOfficeのバージョンが古すぎたらしかった。
じゃあアップデートしようということで設定->アカウントからアップデートしようとしたらアップデートがそもそも無くてできなかった。
どうもボリュームライセンスか何かだと更新経路が違うらしい。
色々調べても分からなかったのでメモしておく。

# 更新方法
Windows Update経由で更新が取得できた。
設定->更新とセキュリティ->Windows Update->詳細オプション->他のMicrosoft製品の更新プログラムをオンにして、更新をチェックするとOfficeの更新プログラムがダウンロードされる。
バージョンが上がり無事文章校正が働くようになった。
Visual Studio Codeで実行時のカレントディレクトリをファイルのあるディレクトリにする

# はじめに

少し特殊な使い方だとは思うのですが、Node.jsの教材を作っていて

- 後から見返しやすいように全部のプログラムをひとつのディレクトリ以下に置く
- 章ごとにサブディレクトリに分ける

というやり方をしていました。
で、fsモジュールを説明する段階になって以下のようなプログラムを書きました。

```js:fs_sample.js
const fs = require('fs');

fs.writeFile('test.txt', 'This is test file', function(err) {
    if (err) throw err;
    console.log('OK');
});
```

fs_sample.jsはchap2ディレクトリに置いています。
![fs_sampleの位置.jpg](https://qiita-image-store.s3.amazonaws.com/0/141091/90447735-62d8-7061-30c5-4bd596c538f9.jpeg)

fs_sample.js実行。test.txtどこだ？
![test.txtの位置.jpg](https://qiita-image-store.s3.amazonaws.com/0/141091/285b23fa-f1cc-461c-ea09-b2af03ef20d2.jpeg)

あれ？なんでルートディレクトリにできてるの？ひょっとしてプログラム実行するときルートディレクトリがカレントディレクトリになってる？
と、まあこの場合なら別にいいのですが、今後Expressに入っていくと非常にまずい。というわけで対策を行いました。

# launch.json設定

多分、launch.jsonで実行するファイルのあるディレクトリをカレントディレクトリにする設定書けばいいんだろうな、カレントディレクトリはcwdだろうから、後はファイルのディレクトリが取れるかと調べてみたところ、
https://code.visualstudio.com/docs/editor/variables-reference

> ${fileDirname} - the current opened file's dirname

はい、ありました。これで勝てます。

というわけで以下のようなlaunch.jsonを作成。実際にはテンプレで作られるものにcwdを付け足しただけです。

```js:launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "プログラムの起動",
            "program": "${file}",
            "cwd": "${fileDirname}"
        }
    ]
}
```

fs_sample.jsを再実行。fs_sample.jsがあるchap2ディレクトリにtest.txtが作成されるようになりました。
![対策後のtest.txt位置.jpg](https://qiita-image-store.s3.amazonaws.com/0/141091/2012dc32-8a77-bed4-4bae-d8f8bbf8ff91.jpeg)

# 余談：requireの動作

fsモジュール、つまりモジュール周りの話を書いてて今回の件に遭遇したわけですが、ふと、「あれ？requireで同じディレクトリにある別ファイル読み込むのもまずい？」と思いましたがそちらはlaunch.json書かなくても大丈夫でした。
何故なら、
https://nodejs.org/dist/latest-v8.x/docs/api/modules.html#modules_file_modules

> A required module prefixed with './' is relative to the file calling require().

というわけで、requireはrequireを呼び出しているファイルとの相対位置でどのファイルかが決定されるようです。
まあ確かにそりゃそうか。node_modulesに入ってる各パッケージは自分のファイルを相対パスで読んでるだろうしな。
タイムスタンプを付与してコマンドを実行

# タイムタイムスタンプを付与
gawk を使用することでタイムタイムスタンプを付与してコマンドを実行可能。

```shell-session
$ <コマンド> | gawk '{print strftime("%F %T"),$0}' 
```
以下はサンプル。

```shell-session
$ vmstat 1 5 | gawk '{print strftime("%F %T"),$0}'
2018-06-21 22:35:31 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
2018-06-21 22:35:31  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
2018-06-21 22:35:31  2  0      0 1607752    948 215280    0    0    41     7   39   65  0  0 99  1  0
2018-06-21 22:35:32  0  0      0 1607752    948 215280    0    0     0     0   36   52  0  0 100  0  0
2018-06-21 22:35:33  0  0      0 1607752    948 215280    0    0     0     0   25   35  0  0 100  0  0
2018-06-21 22:35:34  0  0      0 1607752    948 215280    0    0     0     0   30   37  0  0 100  0  0
2018-06-21 22:35:35  0  0      0 1607752    948 215280    0    0     0     0   27   41  0  0 100  0  0
$
$ while true; do netstat -anpt| grep httpd | gawk '{print strftime("%F %T"),$0}'; sleep 1s; done;
2018-06-21 22:34:59 tcp6       0      0 :::80                   :::*                    LISTEN      1372/httpd
2018-06-21 22:35:00 tcp6       0      0 :::80                   :::*                    LISTEN      1372/httpd
2018-06-21 22:35:01 tcp6       0      0 :::80                   :::*                    LISTEN      1372/httpd
2018-06-21 22:35:02 tcp6       0      0 :::80                   :::*                    LISTEN      1372/httpd
::
```
# おまけで history にもタイムスタンプを付与
```shell-session
$ vi .bash_profile
```
```shell-session
export HISTTIMEFORMAT=' %F %T '★追加
```
```shell-session
$ history |tail -n 3
  391   2018-06-21 22:46:38 date
  392   2018-06-21 22:46:41 pwd
  393   2018-06-21 22:46:44 history |tail -n 3
$ 
```
# 参考情報
How to pass some output of some command to awk via pipe to parse a specific value and redirect it to a file?
https://access.redhat.com/solutions/1992953

How to enable time stamp in history command ?
https://access.redhat.com/solutions/66951
Wordpress のマルチサイト化でハマったところの覚書

# WordPressでマルチサイト化
WordPressで複数サイトを作成し、管理する選択肢はいくつか有りますが、今回はマルチサイト化を選択。

マルチサイト化について、その方法等については以下のサイトを参考にしました。
[株式会社ベクトル：WordPressマルチサイトのメリット・デメリット・設定方法](https://www.vektor-inc.co.jp/post/wordpress-multi/)

マルチサイトって？って方のために上記サイトから引用させていただきますと
>マルチサイトを使って WordPressを運用するとどうなるか？　
>サーバーにインストールした **1つの WordPressを使って複数の Webサイトやブログを運用することが出来る**ようになります。
>これが、WordPressマルチサイトの特徴です。

つまり、Wordpressを何度もインストールしたりせずに、複数のサイトを管理できるようになります。

*ちょっと難しいので初心者向けじゃない、*なんて説明しているサイトも有りますが、設定ファイルをテキストで修正する必要が有るだけなので、（はまらなければ）５分で出来ます。

## でもハマった。
ハマったせいで５分では終わらず。
ですがそれでも先人の皆様のお知恵を拝借して１５分ほどで解決できました。
以下、ハマった部分の覚書。

### １．404になる -> Appiaの設定がおかしかった
設定は出来ているはずなのに、作成したサイトのダッシュボードを開こうとすると404が返ってきてしまう現象が発生。
[WordPressでマルチサイトをやってみた](http://wp-e.org/2015/12/11/6389/)
上記先人様のおかげで解決。

犯人はAppiaの設定ファイルでした。
上記サイト様から引用させていただきますと
>なぜ、404エラーになるのか。
>それは、Apacheの初期設定で「.htaccess」を無効化していることが原因です。

なるほど。

>通常、httpd.confファイルは /etc/httpd/confディレクトリ配下に格納されています。このファイルのWordPressが動いている<Directory "/var/www/html">内の設定を変え「.htaccessを有効化」します。しかし、「.htaccess」はいろいろできてしまうファイルなので、最低限の許可でマルチサイト化を実現したいと思います。
具体的には配下のAllowOverrideディレクティブを「None」から「Fileinfo」に変更します。

これで、httpdを再起動し、アクセスすると見事！！

### 2. リダイレクトループ -> .htaccessの書き換えミス
見事にリダイレクトループになりました。
[WordPress マルチサイト設置のメモ](https://chaika.hatenablog.com/entry/2018/02/01/090000)
上記先人様のおかげで解決。

また引用させていただきます。
>この時 BEGIN WordPress で始まるWordPressが出力していた設定があるとリダイレクトループが発生してサイトが表示されなくなります。
>注意書きにある通り「他のWordPress ルールを置き換えてください」とあるので、これを削除してしまうかコメントアウトします。(コメントアウトの方が万が一の時に戻しやすいかもです)

.htaccessの修正時に、前に有るものは削除（コメントアウト）しなければいけなかったようです。


### 他にもハマりどころは有るみたい。
他にも、.htaccessに[フォルダ名/]が入ってしまっているとリダイレクトループになるみたいなハマりどころも有るらしいですが。（以下先人様が詳しいです）
[WordPressマルチサイト化で重要となる「リダイレクトループの回避方法」
](http://blog.citymarathon.jp/archives/1858)

先人様たちのおかげでなんとか無事に、マルチサイト化が出来ました。
Amazon Elastic Beanstalk Hooks

## Platform Hooks

Place scripts that you want hooks to trigger in one of the subfolders of the `/opt/elasticbeanstalk/hooks/` folder.

Hooks are organized into the following folders:

1. preinit — Scripts run during instance bootstrapping.

2. appdeploy — Scripts run during an application deployment. Elastic Beanstalk performs an application deployment when new instances are launched and when a client initiates a new version deployment.

3. postinit — Scripts run after instance bootstrapping.

4. configdeploy — Scripts run when a client performs a configuration update that affects the software configuration on instance, for example, by setting environment properties or enabling log rotation to Amazon S3.

5. restartappserver — Scripts run when a client performs a restart app server operation.

## Events

#### Deploy New Instance

```
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/preinit.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/pre.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/enact.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/post.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/postinit.
Successfully execute hooks in directory /opt/elasticbeanstalk/addons/logpublish/hooks/config.
```


#### eb deploy

```
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/pre.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/enact.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/post.
Successfully execute hooks in directory /opt/elasticbeanstalk/addons/logpublish/hooks/config.
```

#### Reconfigure Scaling

```
No hooks executed
```

#### Changing Environment Properties (eb setenv)

```
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/configdeploy/pre.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/configdeploy/enact.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/configdeploy/post.
Successfully execute hooks in directory /opt/elasticbeanstalk/addons/logpublish/hooks/config
```

#### Restart App Server

```
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/restartappserver/pre.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/restartappserver/enact.
Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/restartappserver/post.
Successfully execute hooks in directory /opt/elasticbeanstalk/addons/logpublish/hooks/config.
```
cross-originの何がまずいのか

クロスドメインはダメだダメだとよく聞くものの、腑に落ちなかったのでまとめてみました。

## same-origin policy(SOP)とは
同一のドメイン（正確にはオリジン）でしか通信できませんというルール。
世の中のほぼすべてのブラウザはSOPに従っているため、クロスドメインは防がれている。

# SOPって本当に必要？？

Webサイト作成者とブラウザの利用者の視点で考えてみる。

## SOPがない世界
###### サイト作成者
* どこでもアクセスできるので、例えばtwitterとgmail両方を１画面に埋め込んだサイトとか作れて便利！
* 悪意があればgmailの情報を勝手に抜くとかできちゃうけどね。

###### ブラウザの利用者
* 危険なサイトにはアクセスしないよう注意する
* 変なサイト踏んだら自己責任

##### **世の中すべてのWebサイト作成者が善人なら便利な世界**

## SOPがある世界
###### サイト作成者
* 自分で作ったサイト内でしか情報は読めない
* 他サイトと勝手に連携できなくて不便

###### ブラウザの利用者
* 何も考えずにサイトにアクセスしても安全

**若干不便だけど、ブラウザの利用者は安心できる世界**

## どちらの世界を望むのか
というわけで普通のブラウザは利用者を守るためにSOPをつけている。
(デフォルトではSOPはONだが、利用者が自己責任を負うのであれば設定でOFFにもできる。)

# とはいえ、自分のサイト内だけで完結する世界って不便だよね？
なんとかならんのか？
で、考えられた回避策がJSONPという仕組み。

## JSONP
###### サイト作成者
* 他サイトのscriptを自分のページに埋め込むことで他サイトと通信できる。
* ただし、他サイトのscriptに悪意があれば自分のサイトの情報を抜かれる。

###### ブラウザの利用者
* 何も考えずにサイトにアクセスしても安全

##### **Webサイト作成者なら危険な通信先の判断はできるでしょ？だからドメイン跨っても問題ないよね、**という考えかた。

便利だけどリスクある感じ...

いやいやそんな判断したくないし！
ということでCORSが登場する。

## CORS
###### サイト作成者
* 他サイトにうちのサイトと通信を許可してくれとお願いして
* 許可してもらえばそのサイトと通信できるようになる。

###### 他サイト
* 通信を許可していいサイトを判断して登録する。

###### ブラウザの利用者
* 何も考えずにサイトにアクセスしても安全

##### **サイト間でお互いに通信していい相手か判断する健全な世界。**
ただ、許可するサイトを登録したりめんどくさい。

# まとめ
クロスドメインがダメなイメージばかり先行していたけれど、
・実際はいろいろな方法でドメインを跨った通信は行われている。
・誰がリスクを負うのか？と考えると、それぞれの方式が理解しやすい。
JavaScriptの変数とプロパティ

JavaScriptの変数とプロパティについて、「ヘェ〜」と思ったことを共有します。

#変数とプロパティは同じ
変数とプロパティは似ているものではなく、全く同じもの。
変数はグローバル変数とローカル変数の2種類に分けられる(グローバル変数が関数外で宣言した変数で、ローカル変数が関数内で宣言した変数)が、グローバル変数とローカル変数の両者とも実態はプロパティ。

これは、
**グローバル変数 = グローバルオブジェクトのプロパティ**
**ローカル変数 = 関数が呼ばれた時に暗黙に生成されるオブジェクトのプロパティ**
という意味。

##グローバル変数
グローバル変数とグローバルオブジェクトのプロパティが同一であることは以下のように確認できる。

```javascript
js> var x = 'foo'; // グローバル変数xに値を代入
js> print(this.x); // this.xでアクセス可能
foo
```
トップレベルコードのthis参照はグローバルオブジェクトを参照する。このため、上記のコードの```this.x```はグローバルオブジェクトのプロパティ*x*を意味する。

##ローカル変数
ローカル変数のように暗黙に生成されるオブジェクトをCallオブジェクトと呼ぶ。
一般にローカル変数の生存期間は関数が呼ばれてから抜けるまでの間。


以上。
TensorFlow.js の optimizer.minimize が最適化する変数はどれか




[tfjs-examples](https://github.com/tensorflow/tfjs-examples) 内の [polynomial-regression-core/index.js](https://github.com/tensorflow/tfjs-examples/blob/master/polynomial-regression-core/index.js) を読んでいて
`optimizer.minimize` が __弄る対象とする変数__ がどうやって決まるのか分からなかった。

## 結論

`optimizer.minimize` 内で __使用している変数を調べる関数__ を呼んでる。
上記 `index.js` の 103 ~ 107 行目を下記のように変更しても動きは同じ。

```js
optimizer.minimize(() => {
  // Feed the examples into the model
  const pred = predict(xs);
  return loss(pred, ys);
}, false, [a, b, c, d]); // 3 つ目の引数が varList
```

## 読んだコード

`Optimizer` の定義。

[optimizers/optimizer.ts](https://github.com/tensorflow/tfjs-core/blob/master/src/optimizers/optimizer.ts)

## 試したこと

### 44 行目に下記のコードを追加した。

```js
const e = tf.variable(tf.scalar(Math.random()));
```

実行したが `train` 前後で `e` は変化しなかった。

### `optimizer.minimize` の 3 つ目の引数に `[a, b, c]` を指定した。

107 行目を下記に変更。

```js
}, false, [a, b, c]);
```

`train` 前後で `d` が変化しなくなった。
確率論 ~確率測度~

# 確率測度

```math
Ω : \;任意の集合\\
F : \;Ω\;の部分集合からなるσ集合体
```

これらをまとめて

```math
(\;Ω,\;F\;) : 可測空間
```

としたとき、

次の条件を満たす $F$ から実数 $R$ への関数を
確率測度 $P$ とする。

```math
1. \quad P(Ω)=1\\
```

```math
2. \quad 任意の\;A \in F\;に対して、\;P(A)\geq0\\
```

```math
3. \quad A_1,\;A_2,\;...\;\in F,\quad A_i\;\cap\;A_j=\emptyset\;(i\neq j)\quadに対して、\\
P(\bigcup _{n\in N} A_n) = \sum_{n=1}^\infty P(A_n)\quad(可算加法性)\\
```

可測空間 $(\;Ω,\;F\;)$ へ 確率測度 $P$ を導入し、

```math
(\;Ω,\;F,\;P\;) : 確率空間
```

と呼ぶ。
macOS での暗号化ZIPファイルの作成手順

## 改行コード
Windows ユーザーに .txt ファイルや .csv ファイルなどを送付する場合、改行コードが LF だと Windows では改行されずに表示されてしまう。

そのため圧縮前に改行コードを確認して、必要があれば変換する。

### 改行コードの確認
```bash
file example.txt
```
```
example.txt: ASCII text
```
LF のみの場合、改行コードについては何も表示されない。

### 改行コードの変換
```bash
sed -i.org "s/\n/\r\n/g" example.txt
```

### 改行コードの再確認
```bash
file example.txt
```
```
example.txt: ASCII text, with CRLF line terminators
```
LF のみの場合、改行コードについては何も表示されない。


## ZIP 圧縮
```bash
zip example.zip example.txt
```
Finder から圧縮すると余計なファイルを巻き込むことがあるので最初からコンソールで作業するとよい。

ZIP ファイルを先に指定する。


## パスワードの生成
```bash
cat /dev/urandom | base64 | fold -w 20 | head -n 1
```
pwgen コマンドを導入してもいいが、オプション指定が覚えられないので上記コマンドを .bashrc などで alias 指定する方が早いだろう。


## ZIP ファイルの暗号化
```bash
zipcloak example.zip
```
パスワードの指定は zipcloak コマンドを使用する。対話型。
JUnitテストクラスでテストケースの名前を取得する

JUnitテストクラスのテストメソッド名を把握する方法を知りました。
`@Before`でテストケースを把握する際に使えますね。

`org.junit.rules.TestName`に`@org.junit.Rule`を付与してテストクラスのフィールドを定義すると情報が取れます。

```java
/**
 * TestName
 */
@Rule
public TestName testName = new TestName();

// want to know test case name.
System.out.println("[TestName] : " + testName.getMethodName());
```

便利ですね、これから使っていきたいと思います。
参考までに。
Python3 & MacOSで4GB以上のオブジェクトをpickle化するときのエラーと対処法

タイトルそのままですが、Python3でMacOSで4GB以上のオブジェクトをpickle化すると

```py
import pickle

path = "path.pkl"
data_larger_than_4GB = bytearray(2**32)
pickle.dump(data_larger_than_4GB, open(path, 'wb'))
```

次のようなエラーが出ます。

```
OverflowError: cannot serialize a bytes object larger than 4 GiB
```
機械学習の学習データなど4GBとかすぐ超えるのでこれでは使い物になりません。これに対して、

```py
pickle.dump(data_larger_than_4GB, open(path, 'wb'), protocol=4)
```
と`protocol=4`という引数をしてしてやると解決するというStackoverflowの[回答](https://stackoverflow.com/questions/29704139/pickle-in-python3-doesnt-work-for-large-data-saving/29704623#29704623)があります。これはWindowsであればこれで解決するみたいですが、Macの場合はMac特有のバグがあるらしくこれでもエラーがでます。

```
OSError: [Errno 22] Invalid argument
```

これ問題に対する完璧な解決がコード付きで別のStackoverflowに[解決](https://stackoverflow.com/questions/31468117/python-3-can-pickle-handle-byte-objects-larger-than-4gb)があります。



```python:

class MacOSFile(object):

    def __init__(self, f):
        self.f = f

    def __getattr__(self, item):
        return getattr(self.f, item)

    def read(self, n):
        # print("reading total_bytes=%s" % n, flush=True)
        if n >= (1 << 31):
            buffer = bytearray(n)
            idx = 0
            while idx < n:
                batch_size = min(n - idx, 1 << 31 - 1)
                # print("reading bytes [%s,%s)..." % (idx, idx + batch_size), end="", flush=True)
                buffer[idx:idx + batch_size] = self.f.read(batch_size)
                # print("done.", flush=True)
                idx += batch_size
            return buffer
        return self.f.read(n)

    def write(self, buffer):
        n = len(buffer)
        print("writing total_bytes=%s..." % n, flush=True)
        idx = 0
        while idx < n:
            batch_size = min(n - idx, 1 << 31 - 1)
            print("writing bytes [%s, %s)... " % (idx, idx + batch_size), end="", flush=True)
            self.f.write(buffer[idx:idx + batch_size])
            print("done.", flush=True)
            idx += batch_size


def pickle_dump(obj, file_path):
    with open(file_path, "wb") as f:
        return pickle.dump(obj, MacOSFile(f), protocol=pickle.HIGHEST_PROTOCOL)


def pickle_load(file_path):
    with open(file_path, "rb") as f:
        return pickle.load(MacOSFile(f))
```

`pickle.dump` `pickle.load`の代わりに`pickle_dump` `pickle_load`を使ってやれば、バグを回避できます。すばらしい。
ulの左端を揃えたまま中央寄せする

```html:html
<div class="content-txt">
  <p class="txt-center">
    タイトル
  </p>
  <div class="ul-align-center">
    <ul>
      <li>1行目</li>
      <li>２行目２行目</li>
      <li>３行目３行目３行目</li>
    </ul>
  </div>
  <p class="txt-right">
    右寄せ
  </p>
</div>
```

```sass:sass
.content-txt{
  border: 1px solid;
  
  .txt-center{
    text-align: center;
  }
  .txt-right{
    text-align: right;
  }
  ul{
    list-style: disc;
    padding-left: 15px;
  }
  .ul-align-center{
    display: flex;
    align-items: center;
    flex-direction: column;
  }
}
```

結果

![image.png](https://qiita-image-store.s3.amazonaws.com/0/30951/31fa2cb6-1628-4979-839c-c222200c8e25.png)

http://jsfiddle.net/2fsz3xav/9/
Babelなどの追加モジュールなしでnodeコマンドたけでサクッと import/export を動かす

:writing_hand: [ES Mmodules](https://nodejs.org/api/esm.html#esm_enabling)

- ```.mjs``` 拡張子にする
- ```--experimental-modules``` オプションを指定する

```bash:version
node -v
# v8.11.2
```

```javascript:export.mjs
export default () => "🙋";
```

```javascript:import.mjs
import f from "./export";
console.log(f());
```

```bash:ESMフラグを付けて実行する
node --experimental-modules import.mjs
# (node:509) ExperimentalWarning: The ESM module loader is experimental.
# 🙋
```

:moyai: 「...ちょろっとスクリプト書く時ももうrequireしなくてええやん」
Ionic3に入門してみる～その9 Angular4チュートリアル⑦～

#ルーティング
Angular自体のルーティングはIonicでは使用しないため、Angularチュートリアルのルーティングについては割愛します。

## Ionicのルーティング
Ionic2の記事ですが下記をご覧ください。
https://qiita.com/kohashi/items/f424fb5dd897fc6317c9

基本的にIonicではルーティングは不要とされているようです。

しかしもちろんそういった動作もサポートされています。
Ionic3では、IonicPageModuleを使用します！(Ionic2までと情報が混在しててなかなか難しいですが…)

例として今回は新しいサンプルを使用します。
まず下記のコマンドを実行します。

```
ionic start sampleApp
ionic g page second
```

なおsampleAppはblankとしてください。
するとこんな感じのサンプルができるはずです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/196422/22945219-2d45-3a56-db10-4ab46d8362ed.png)


手を加えるところは多くありません。
まず最初にhome.tsを編集します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/196422/fd32d071-5fd2-fc72-d23b-ce7a48b58184.png)

次に、呼び出すボタンをhtmlに作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/196422/a50178b9-e40a-0514-009f-84c9d1731143.png)

手を加えるわけではありませんが、最後にsecondのページを見てみましょう。
pushしているのはsecond.tsで宣言されているSecondPageクラスだとわかります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/196422/14027003-5ea5-145f-badb-6ff9f345c02e.png)

これを動かしてみると下記のように動きます。
![test.gif](https://qiita-image-store.s3.amazonaws.com/0/196422/1e86a58f-7bb7-e765-1242-67292983da2c.gif)

詳細は下記のDocにあります。ぜひ見てみてください。
https://ionicframework.com/docs/api/navigation/IonicPage/
PythonからSQLite3で初めてのデータベース！

個人的な備忘録も兼ねて。
基本的な操作に関しては[公式ドキュメント](https://docs.python.jp/3/library/sqlite3.html)の上側に書いてあるものがとてもわかりやすいのでそちらも参照すると良い

この文章の中ではPythonとSQL文がごっちゃになっているので、Pythonには左上にpythonと書いてあります。


pythonから扱うには基本的には

```python:python
import sqlite3
conn = sqlite3.connect('example.sqlite3')
c = conn.cursor()
c.execute('create table persons(id integer, name text, birthday)')
```

という感じでオブジェクトを作って、
`c.execute()`のカッコ内にSQL文を突っ込めば動きそう。

閉じ方は

```python:python
conn.commit()
conn.close()
```

で閉じる。
**この`conn.commit()`をしないとsqlite3でデータベースに加えた変更が保存されないので注意。**


#SQL文
**テーブルを新しく作成する。**

```sql

create table persons(id integer, name text, birthday)
```

カッコの中身は(カラム名　カラム型)の組み合わせを並べていて、カラム型に使えるものとしては

| カラム型の名前     |       データ型 |
|:-----------------|-------------:|
| text             |   　　　 str |
| integer          |　　　　　int|
| real             |       float |
| numeric          |      binary |
| none             |      none| 

がある。カラム型は指定しなくても特には問題ない（noneが初期値として入っている）
型を指定してあったところでなんでも入るけど、その型に変換できるようであれば勝手に変換してくれるらしいので基本的には指定しておいた方が便利かも？

[ここにわかりやすく書いてあるのでわからなくなったら参照](https://www.dbonline.jp/sqlite/type/index1.html)
（SQLにて使えるデータ型についても記述があります。）


**カラムを追加する**

```sql

alter table persons add column blood_type text
```

*persons*のところにテーブル名、*blood_type text*のところにカラム名とカラム型を入れればよい。

**カラム名を列挙する**

```python:python
for desc in c.description:
    print(desc[0])

#id
#name
#birthday
#blood_type
```


**データを追加する**

一つ追加するとき

```sql

insert into persons values (1, '太郎', '1996-01-04','B')
```

複数追加するとき

```python:python

persons_data = [(2,'二郎','1997-01-04','A'),
                (3,'三郎','1998-01-04',None)]
c.executemany("insert into persons values (?,?,?,?)", persons_data)
```

となる。

**中身を見るとき**
やり方は公式によれば3つほどあるけど、どれも同じらしいので2つ書いておく。

- fetchall()を使うやり方

```python:python
c.execute('select * from persons')
data = c.fetchall()
print(data)

#[(1, '太郎', '1996-01-04','B'),(2,'二郎','1997-01-04','A'),(3,'三郎','1998-01-04',None)]
```

- イテレータとして扱う方法

```python:python
for row in c.execute('select * from persons'):
    print(row)

#(1, '太郎', '1996-01-04','B')
#(2,'二郎','1997-01-04','A')
#(3,'三郎','1998-01-04',None)
```

select文の使い方として、
`select * from persons order by name`などとするとそのカラムにおいて昇順で出てくる。
`select * from persons where blood_type='B'`とすると太郎のデータだけ取り出すことができる。
[tips]スプレッドシートで構成図（サイトマップ）を作成する方法

最近、ページを洗い出すために構成図（サイトマップ）を作成する機会があり、
スプレッドシートで簡単に作成できる方法を見つけたのでまとめてみました。

# 目次

1. なぜ構成図（サイトマップ）を作成するのか？
2. 構成図（サイトマップ）の作成方法

# 1. なぜ構成図（サイトマップ）を作成するのか？

### - まず構成図（サイトマップ）とは
　サイトの全体像を描く見取り図であり、サイト内での情報の分類を定義するものです。サイトマップによってサイトの骨格を設計し、掲載する情報の組織化・構造化を進めていきます。

### - 次に、なぜ構成図（サイトマップ）を作成するのか？
　サイトマップには単なる設計資料としての役割だけでなく、サイトの企画意図をクライアントや他のプロジェクトメンバーと情報共有するためのコミュニケーションツールとしての役割もあるため作成されます。

# 2. 構成図（サイトマップ）の作成方法

### - まずは、どんな感じにできるのか画像をどうぞ！
![https://gyazo.com/b8cf5ca9548b3c677f52b47ce06a12d7](https://i.gyazo.com/b8cf5ca9548b3c677f52b47ce06a12d7.png)

では、手順を説明します

### - シートの1行目に親要素（遷移元）、子要素（遷移元）、備考の項目を書く
![https://gyazo.com/c627b3732546dce2f5c9d2b2e10f2f1e](https://i.gyazo.com/c627b3732546dce2f5c9d2b2e10f2f1e.png)

### - 把握している遷移ページを記述（全て書く必要はない）

![https://gyazo.com/2fa5a8fdbba162b9b5528ebf889ab24a](https://i.gyazo.com/2fa5a8fdbba162b9b5528ebf889ab24a.png)


### - [挿入]　＞　[グラフ]　をクリック
![https://gyazo.com/adbc568b5992c31da4eae3baf982a6ae](https://i.gyazo.com/adbc568b5992c31da4eae3baf982a6ae.png)

### - グラフの種類を[組織図]に設定
![https://gyazo.com/3f7e76fbc54aed387a96442d0be883a5](https://i.gyazo.com/3f7e76fbc54aed387a96442d0be883a5.png)

### - 親を親要素（遷移元）を設定する

|![https://gyazo.com/0834eaf0e1ab9dc6e22abf17ee64804f](https://i.gyazo.com/0834eaf0e1ab9dc6e22abf17ee64804f.png) 
--
![https://gyazo.com/60ac037a3ad2e7a27fdf1e69f55147f0](https://i.gyazo.com/60ac037a3ad2e7a27fdf1e69f55147f0.png) 

### - 識別子を子要素（遷移元）を設定する

![https://gyazo.com/dac4ae490668c2c39c9740b17e4feef9](https://i.gyazo.com/dac4ae490668c2c39c9740b17e4feef9.png)
--
![https://gyazo.com/5b3fc1c671c7794c734b7a97def8afeb](https://i.gyazo.com/5b3fc1c671c7794c734b7a97def8afeb.png)

### - ツールチップを備考を設定する
![https://gyazo.com/9ab665e6288245852a02f452791ef6cf](https://i.gyazo.com/9ab665e6288245852a02f452791ef6cf.png)
--
![https://gyazo.com/34a22b13c4b7b03b5993c3920fa53bda](https://i.gyazo.com/34a22b13c4b7b03b5993c3920fa53bda.png)
--
####　以上！めっちゃ簡単だし、修正もしやすいです！
Python メモリ8GBでkaggleを闘うときに知っておきたいこと

#背景
最近流行のkaggleにチャレンジしてみました
が、特徴量を増やすとデータが巨大になり、「Memory Error！」に悩まされました
それでもkaggleを諦められなかった私は、メモリと上手く付き合う道を模索しました

#[1]環境を変える
そもそもメモリ8GBで挑むことが無謀なので、**「Google Colaboratory」**を利用すると良さそうです

・メモリ : **約13GB**
・無料
・ブラウザ上で動く
・面倒な環境構築は一切不要
・一瞬でpython(Jupyter Notebook)環境が手に入る

使い方に関しては下記のリンクが詳しいです
[Google Colaboratory事始め](https://qiita.com/kouki_outstand/items/cd24dccbaa92274be39e)
[Colaboratoryのデータの入出力まとめ](https://qiita.com/5at00001040/items/d7867974d2fd1d21dbbf)

控えめに言って**素晴らしい**ですね
データの入出力にクセがありますが、慣れてしまえば基本的にはJupyter Notebookをそのまま利用することができます
オマケにGPU環境も無料で手に入るため、使い勝手の良いツールです

#[2]メモリを食っている変数を探し、削除する
変数のサイズは下記で確認できます

```python
import sys
sys.getsizeof(val)
```

メモリを食っている変数を大きいほうから表示してみます

```python
import sys
import pandas as pd

print(pd.DataFrame([[val for val in dir()], [sys.getsizeof(eval(val)) for val in dir()]],
                   index=['name','size']).T.sort_values('size', ascending=False).reset_index(drop=True))


                     name       size
0                    data  570142137
1                    test   90020943
```

最後に、不要な変数を削除してgcを解放してあげます

```python
import gc

del data, test
gc.collect()
```


#[3]DataFrameの入出力に「feather」を使う
pickleによる入出力は高速で便利です
が、メモリをかなり食うのが辛いところで、貧弱環境ではメモリエラーになることがあります
かといって単に```pd.read_csv```は時間がかかりすぎるという問題があり・・・
回避するためのライブラリは色々あるようですが、 [feather](https://github.com/wesm/feather/tree/master/python) を利用すると良さそうです

インストールは下記のコマンドで行えます

```
!pip install feather-format
```

肝心のスピードは下記の通り、pandasと比べるとかなり高速です

##入力
```python
%time df = feather.read_dataframe('test.csv')
```
CPU times: user 78 ms, sys: 49 ms, total: 127 ms
Wall time: 680 ms

```python
%time df = pd.read_csv('test.csv')
```
CPU times: user 846 ms, sys: 25 ms, total: 871 ms
Wall time: 5.8 s

##出力
```python
%time df.to_feather('test.csv')
```
CPU times: user 942 ms, sys: 55 ms, total: 997 ms
Wall time: 16.3 s

```python
%time df.to_csv('test.csv')
```
CPU times: user 6.14 s, sys: 245 ms, total: 6.39 s
Wall time: 1min 11s

#結論
これでkaggleのスタートラインに立てましたね！
(「PC買えよ」というツッコミは、なしでお願いします・・・:expressionless:)
HTC Viveのベースステーションを４つ使う方法

# HTC Viveのベースステーションを４つ使う方法

---
 **※４つ使う方法はメーカーサポート対象外の方法なので、あくまでも自己責任でお願いします**
*（メーカーに問い合わせとかしちゃだめですよ！）*

---

諸般の事情でHTC Vive Proのフルセット版が二つあり、ベースステーション2.0が４つありますので、４つのベースステーションを使ってトラッキングしてみたいと思います

## 1. SteamVRのバージョンを確認

SteamVRのバージョンは以下の通りです
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/17a8b748-1f79-fb37-4ff5-80bb0cdfbb5e.png)

## 2. ベースステーション2.0のチャンネルをバラバラにする
ベースステーションのチャンネルは s-0からs-3まで４つあります。
初期設定は、１セットベースステーションが２つ入ってますので

- s-0
- s-1

この二つのチャンネルが割り当てられてます
Vive Pro フルセットが２セット（ベースステーションが４つ）あるので初期状態は

- s-0
- s-1
- s-0　（←これをs-2に変更）
- s-1　（←これをs-3に変更）

となってますので、２個のベースステーションを s-2、s-3にすれば解決です
チャンネルの変更方法は、ベースステーション2.0の後ろにある穴に先のとがったもの（針金など）を差し込むと、チャンネルが一つづつ増えます（s-3の次 s-0）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/f3ba7dfa-9b37-edee-7e8f-89fbf901c8bb.png)

現在のチャンネルの確認方法が、SteamVRのアプリ上でマウスを合わせてステータスを確認する方法しかしらないので、カット＆トライでがんばってチャンネルを合わせてみてください。

うまくいくと、こんな感じです

![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/4451b792-43af-cfdf-c7cb-0cb53ac6f789.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/6164e9a9-13bc-3fac-b702-3253d168a98d.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/748470b5-52e7-aa98-470a-235c16fda1a2.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/8cf7f51a-f823-5b90-2c91-6d0515caf9be.png)

これで準備OKです

## 3. 正しく認識してるかどうか確認してみる

まずはルームスケールやってみましょう！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/576715d6-0627-9fb0-6870-8623418ef61d.png)
こんな感じで４つ正しく認識されてます

SteamVRの設定からルーム外観を確認してみましょう！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/6f29ca6d-6cda-f484-d915-f57c1a12fd67.png)
こちらもいいかんじで全方位網羅されてるのがわかります

## 4. Vive Tracker 2018を７つ用意してバーチャルキャストで遊んでみる
フルセットはこんな感じです
![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/e8ce82f1-90b0-7bc0-5a85-0b35d5b62486.png)

全方位網羅してるので、けっこう無理な体勢でもいけます
（寝そべったりとかもおｋ）

みなさんも、ベースステーション2.0を４つ＋Vive Tracker 2018を７つでバーチャルキャストを遊んでみてください♪
Pythonの内包記法の練習

プログラムチェックで書いた内容の覚書
##Before
```内包記述前
n=int(input())
rec = {}
for i in range(n):
    r=input().split()
    rec[r[0]]=int(r[1])
```

##After

```after
n = int(input())
rec = dict([[j for j in input().split()] for i in range(n)])
```
##Input
```input
3
foo 1
bar 4
baz 6
```

#メモ
- 何行にもなる記述を1行に書けるのはコンパクトでPythonステキ
- しかし記法を覚えないとまるで読めないので、要練習
- 本当はdict()を使わずに内包記法だけでdictにしたかったが、書き方不明
- また、keyは文字列でいいけどもvalueは数字なので、intに変換しておきたい
GPSの研究　その19

#概要

GPSを理解したかった。
u-centerを調べて　みた。

#u-centerとは。

スイス、u-blox社のGNSSソフト。
入力は、シリアルorファイル。
UBXフォーマットが、ご希望だが、NMEAも読んでくれる。
読んだら、データベースにしまうらしい。

天空図、マップを表示できる。

#凄いとこ。

googl earth serverになるらしい。
KMLを出力できるらしい。

#さらに、凄いとこ。

NTRIP serverになったり、NTRIP　Clientになるらしい。


以上。
Laravelのテストでcookieを設定したはずなのに取得できない場合

Controllerのテストで設定されたcookieの値で処理を分岐させる箇所があったので、
cookieを設定したものの、Controller側ではnullになってしまって取得できなくてハマってしまったので誰かのためにいつか役に立つことを願いつつメモします。

## 環境

|名前|バージョン|
|---| -------- |
|PHP | 7.2.6    |
|Laravel| 5.5.40 |

## 事象

cookieが取得できなかったときのコードは以下です。

```ExampleControllerTest.php
    public function testIndex()
    {
        $response = $this->call(
            'GET',
            '/',
            [],
            ['cookie-name' => 'cookie-value']
        );
        $response->assertStatus(200);
    }
```

```ExampleController.php
    public function index(Request $request)
    {
        $cookie = \Cookie::get('cookie-name');

        if (is_null($cookie)) {
            dump('cookieはnullです。');
            return response('', 400);
        }

        return response('', 200);
    }
```

テストを実行するとcookieがnullになっています。
どうすればいいのでしょうか？

## 解決法

Laravelはミドルウェアでcookieを自動的に暗号化しますので、
テストのときだけ暗号化を無効にします。

```ExampleControllerTest.php
    public function testIndex()
    {
        // テストでcookieが利用できるように暗号化対象から除外
        $this->disableCookiesEncryption(['cookie-name']);

        $response = $this->call(
            'GET',
            '/',
            [],
            ['cookie-name' => 'cookie-value']
        );
        $response->assertStatus(200);
    }

    protected function disableCookiesEncryption($cookies)
    {
        $this->app->resolving(App\Http\Middleware\EncryptCookies::class, function ($object) use ($cookies) {
            $object->disableFor($cookies);
        });

        return $this;
    }
```

これでController側でcookieが取得できるようになります。

## 参考

[[5.2] Cookies sent in test are not present in request.](https://github.com/laravel/framework/issues/12032)
Githubリポジトリ名変更

# 概要
プロジェクト作ってからリポジトリ名やばくね？変えたくね？ってなって、意外と簡単に変更できそうなのでその作業メモ
:beginner:（Githubのリポジトリ名と、ローカルのプロジェクト名を変更する）
:bangbang:（Herokuにデプロイしている場合、**削除**してから再登録の流れになる）

# 作業
## GitHub側の操作
https://github.com

```zsh
GitHubの対象リポジトリ > Setting > 変更後の名称を入力　> Renameで変更
```

<img width="1006" alt="________2018-06-21 19.43.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/23248/771b812f-e289-0e80-0896-8b9ef2753cb5.png">


## ローカル側の操作
プロジェクト名を`hoge-github` → `Hoge-GitHub` にする場合

```rb:.git/config
# url の名称部分を変えるだけ

#[remote "origin"]
#    url = https://github.com/usermay/hoge-github.git
#    fetch = +refs/heads/*:refs/remotes/origin/*

[remote "origin"]
    url = https://github.com/usermay/Hoge-GitHub.git
    fetch = +refs/heads/*:refs/remotes/origin/*
```

### gem使う
[morshedalam/rename](https://github.com/morshedalam/rename)

```zsh:gemインストール
echo -e "gem 'rename'" >> Gemfile
bundle
```
```zsh:リネーム実行
# NewName部分を変更後の名称に適宜書換え
bundle exec rails g rename:app_to NewName
```
```zsh:direnvを設定してる場合は
direnv allow
```

`config/application.rb` の内容（プロジェクト名）が自動で置き換わる。


```zsh
# rename のgemはGemfileから消して再bundleしとく
bundle
```

`app/helpers/application_helper.rb`とかにTITLE設定してたら変更しとく


# デプロイ済みの場合

- 削除 → 再登録 → DB作成 （→ 環境変数設定）

## Heroku側の操作

```zsh:herokuにデプロイ済みのものを削除
# 確認
heroku apps:info

# 削除
heroku apps:destroy --app アプリ名 --confirm アプリ名
```
`.git/config`から
`[remote "heroku"]`の設定が消える
gitの管理情報も全部消えます。

### 再登録
[Herokuにプロジェクト載せてサービス公開](https://qiita.com/ntkgcj/private/8e757c9cce9c53705dfe)

```zsh:herokuに再度アプリ作成
heroku login
heroku create アプリ名
# アプリ名はheroku全体でユニークでないとダメらしい。
# ありがちな名前だと「Name is already taken」とか言われて作成できないので名前に注意

heroku config
# エラーが出なければおkかな

git remote
# 「heroku」が表示されればおk
```
```zsh:デプロイしてリポジトリに登録
# heroku にデプロイ
git push heroku master
```
```zsh:確認
#ウェブアプリをブラウザで開く
heroku open
```
多分、こんな感じのが表示されるので
<img width="604" alt="スクリーンショット 2018-06-21 20.54.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/23248/9a7ee1a6-32f1-df99-a6f3-edf6a3a74557.png">

DBデータを作成する

```zsh:DBのマイグレーション
heroku run rake db:migrate
```
```zsh:タイムゾーンを日本時間に変更
heroku config:add TZ=Asia/Tokyo
```
`環境変数`の設定は適宜おまかせ

```zsh:アプリを開いて再度確認
heroku open
```
意図した通りに動けば作業完了だ:bangbang:


# 参考
>[GitHubのリポジトリ名変更方法](https://qiita.com/hisurga/items/583e8dbe4970bc8c25c8)
[Railsのプロジェクト名と、GitHubのリポジトリ名を変更する - TechBox](http://www.techbox.jp/entry/github-namechange)
[[Rails 4.1] プロジェクト名の変更](https://qiita.com/colorrabbit/items/11e16f323ed36a0cb7ab)
[【herokuコマンド】createからdestroyまで](https://qiita.com/chihiro/items/5c3ff400f6cb99deb945)
tkinterでタスクトレイに常駐させたいそこのあなた。諦めてwxPythonを使って幸せになろう

# 概要
まぁtkinterに固執してたのは私なんですが。

パッケージを追加したくないという理由でtkinterにこだわってタスクトレイに常駐させる方法を探してましたが、どうにも無理そうだったのでwxPythonを使ってみたところあっさりうまくいきました。

まだtkinterで作り込んでいないならサクッと切り替えることをおすすめします。

# 環境
Windows7 64bit
Python 3.6.5
wxPython==4.0.2

# 準備

## パッケージインストール
```python
pip install wxPython
```

# 実データ

## フォルダ構成
root/
　├ gui.py
　├ main.py
　├ logo.ico # 今回はgoogleのGマークにしました

## コード

### gui.py

```python
import wx
import wx.adv

TRAY_TOOLTIP = 'test app'
TRAY_ICON = 'logo.ico'

def create_menu_item(menu, label, func):
    item = wx.MenuItem(menu, -1, label)
    menu.Bind(wx.EVT_MENU, func, id=item.GetId())
    menu.AppendItem(item)

    return item

def open_site():
    print("open site.")
    pass
    # import webbrowser
    # webbrowser.open_new(r"https://www.google.com/")
   

class TaskBarIcon(wx.adv.TaskBarIcon):

    def __init__(self, frame):
        self.frame = frame
        super(TaskBarIcon, self).__init__()
        self.set_icon(TRAY_ICON)
        self.Bind(wx.adv.EVT_TASKBAR_LEFT_DCLICK, self.on_open_site)

    def CreatePopupMenu(self):
        menu = wx.Menu()
        create_menu_item(menu, 'Open Site', self.on_open_site)
        menu.AppendSeparator()
        create_menu_item(menu, 'Exit', self.on_exit)

        return menu

    def set_icon(self, path):
        icon = wx.Icon(wx.Bitmap(path))
        self.SetIcon(icon, TRAY_TOOLTIP)

    def on_open_site(self, event):
        open_site()

    def on_exit(self, event):
        print('exit')
        wx.CallAfter(self.Destroy)
        self.frame.Close()


class App(wx.App):

    def OnInit(self):
        frame=wx.Frame(None)
        self.SetTopWindow(frame)
        TaskBarIcon(frame)

        print('launch App')
        return True

```

### main.py

```python
if __name__ == "__main__":
    import gui
    app = gui.App(False)
    app.MainLoop()
```

# 結果
![tasktray.gif](https://qiita-image-store.s3.amazonaws.com/0/137381/81745551-0fd6-925e-fd49-c511a7ca6670.gif)

# 余談
windowsの右下の領域は日本語でタスクトレイ、通知領域、はたまた英語ではsystem tray、task trayなどと呼ばれるので、その呼び名 x パッケージの数だけ検索をかけないと最適解が得られないのはなかなかに辛い。

# 参考
https://stackoverflow.com/questions/6389580/quick-and-easy-trayicon-with-python