OmniAICreator/Qiita-1.07M huggingface dataset:
Dappの習作としてURL短縮サービスを作った

![image.png](https://qiita-image-store.s3.amazonaws.com/0/273713/39b0f983-4a18-6e82-a12f-bd07f6b1ba32.png)


[github.com/stsysd/urlshortener](https://github.com/stsysd/urlshortener)
[URL登録ページ](https://urlshr.tk/)
[短縮URLデモ](https://urlshr.tk/#TCScAkgf)

EthereumのブロックチェーンをDB代わりに利用したURL短縮サービス。
今のところtestnet(ropsten)にしかデプロイしてない。
短縮URLにアクセスするだけなら誰でも使えるけど、新しく短縮URLを作る場合はMetaMaskでropstenにログインしてgasを払ってもらう必要がある。
GitHub Pagesそのままだとドメインが長すぎて全然URLが短縮された感じがしないので、[Freenom](https://freenom.com/)からドメインももらってきた。

# なぜ作ったか
[CryptoZombies](https://cryptozombies.io)でざっとDapp開発の概要が分かったので一回自分で作ってみたくなったから。
まず練習として環境を整えて一から動くものを作りたかったのでとにかく簡単なものにした。

ブロックチェーン上に記録することで書き換えられたり失効したりしない短縮URLに！という技術的動機もなくはなかったんだけど、よく考えるとブロックチェーンにアクセスする部分(html/js)は普通に変更できてしまうのであんまり意味がなかった。
むしろ、URLはブロックチェーンで公開されてしまうせいで、他人に知られたら困るURLは登録できないという足かせがある。
ブロックチェーンを使ってうれしい部分は、DBのためのサーバをわざわざ用意しなくて済むことぐらいしかないな？

まあ習作ということで一つ。

# 使ったライブラリとか
- [truffle](https://truffleframework.com/truffle): Ethereum開発フレームワーク
- [ganache](https://truffleframework.com/ganache): テスト用のローカルブロックチェーン構築
- [GitHub Pages](https://pages.github.com/): ホスティング・独自ドメインの設定・SSL証明書の発行
- [Vue.js](https://jp.vuejs.org/index.html): フロントエンドライブラリ
- [web3.js](https://github.com/ethereum/web3.js/): ブラウザでEthereumとやり取りする


# ひっかかったところ
## Solidity
- ブロックチェーン抜きでローカルに動かすことができない
- 構造体や配列は保存場所でstorage/memoryの区別がある
- 乱数などの外部リソースを利用するのが難しい
- 他の誰かに見られたら困るようなデータのやり取りはしてはいけない
 
などなど、ブロックチェーン上で動作するが故の独特の制限が慣れるまで大変だった。今回は全部自分で書いたけど、今後トークンのやり取りを含むContractを作るなら素直にOpenZeppelinみたいなライブラリを使うべきだろう。

## truffle-hdwallet-providerのインストール
というより多分Windows上でのnpmのネイティブな拡張のインストール全般の問題。
truffleでHDウォレットを使うためのパッケージであるtruffle-hdwallet-providerはnpm経由でダウンロードするんだけど、これにはネイティブライブラリが使われているらしく、それをビルドするためにgyp(とそのためのwindows-build-tools)が必要になる。
自分の環境では、はじめWarningを出しつつビルド自体は完了するのだが、ライブラリを読み込もうとすると何のメッセージも残さずプロセスが終了するという現象が起きた。

原因はnodeを公式のインストーラからではなく、msys2のpacmanからインストールしていたせいだった。一回アンインストールして公式のインストーラでインストールしなおしたら、普通に動くようになった(Warning)も消えた。
開発環境はできるだけchocolateyかpacman経由で入れようと思ってたのだが、よく問題の原因になるので公式が用意してくれているなら素直にインストーラを使ったほうがよさそう。


## web3.js
web3.jsの現在の安定バージョンは0.20.xだけど、今1.0の開発が進められているらしい。
ググってすぐ出るドキュメントは1.0のものなので注意。
目についた大きな違いは非同期関数の扱いで、1.0だと今風に全部Promiseになっているのでasync/awaitで書けるが、0.20.xはコールバック関数を渡してやらなければならない。
ただしtruffle consoleのwe3のバージョンは0.20.6だが、Contract Methodsが返すのはPromiseになっている。ややこしい。

## web3.jsの"new BigNumber() not a base 16 require string"
ブロックチェーンとのやり取りしているコードで何かにつけて上記のエラーが出た。
おそらくsolidityでstringとして定義された文字列がクライアント側に渡される際に、型情報が失われて数値としてパースされてるのが原因なんだと思う。
contractのaddress/abiが何かの手違いで損なわれてたりするとよく起こる印象がある。


# もうちょっと頑張りたかったところ
- keyには62種類の文字しか使ってないのに1文字1byte使ってるのでもっと詰めたい
- せっかくだからトークンのやり取りもしたかった
- URLを登録するにはMetaMaskをインストールしてもらわないといけないのは不便
- 短めのURLの登録に70000unitぐらいのガス、ざっくり数円かかるというのはつらい

# 最後に
ものすごく簡単なDappだけど、実際に作ってみて分かったことはいろいろあった。
特に印象深いのはgasの値段で、思ってたよりずっと高かった。
本当に最低限の機能しかないので、原因はコードにあるというよりはethの相場にあるのだと思う。
これくらいのTransactionで数円かかるとなると、チャットや掲示板みたいなばんばかDBを更新するサービスで使うのは無理っぽい
やっぱりブロックチェーンの基本は台帳であって、ある程度価値のある取引を記録するものなのかもしれない。
PlasmaとかRaidenとかのプロジェクトがうまくいったらもっと安くなんだろうか。
その辺を踏まえて、次は独自トークンをやり取りするDappを作ってみたい。

あと、GitHub Pagesのドメイン設定も初めてやった。
ちょっと前はhttps対応するためにCloudflareでリバースプロキシを使ってなんやかんやする必要があったみたいだけど、最近GitHub側がsslの証明書を発行してくれるようになって簡単になったらしい。
実際すごい簡単で助かった。
スコープと列挙型 (三週目の学習)

<font color="limegreen">モチベーションも大事だと思うので覚書として使用します。
<details><summary><font color="DarkSlateGray">三週目の感想</summary><div>
<font color="DarkSlateGray">　一週目に端折っていた変数(自動実装プロパティやコンストラクタ、配列とか)の理解に努め更新しました。
クラス,プロパティ,コンストラクタ,最後関数の流れに苦戦したけど、最終的に理解できたと思います。
そのままにしておかなくて良かった…。New演算子でインスタンス化や配列の種類もある程度できました。<br>
　まだ早いけど一ヶ月経って感じたのは、思ったよりプログラミング楽しいという事です。
理解が深まる程新鮮な発見が増えるし、何より最新の技術に触れられていられるのは楽しいです。
ただのめり込み過ぎず、やりたい事に対するツールという事を頭において学習したいと思いました。
他、ご指導頂いた所の修正をしたり、いくら覚書でもC#を１つの投稿に収めるのは現実的ではないので、
新しい学習項目は成果として、編集でなく投稿していこうと思います。
(識別子ならユーザー定義型のあたりに書き込みたいといった関連性は犠牲になるけど…)
今日余った1日でスコープとenum学習。また、極力見やすく書けるといいなーと思いました。</details></div>





#<font color="SlateGray">スコープ {識別子を囲うブロック}

<b>{}の範囲<font color="Crimson">内</font>の変数や関数は通常、識別子だけで参照できる
(=見える=依存性ある=スコープ内)private

<b>{}の範囲<font color="Crimson">外</font>の変数は関数は通常、識別子だけで参照できない
(=見えない=依存性ない=スコープ外)public</b>


##例. 識別子のスコープ
(同じブロック内は識別子重複NG。呼出は引数を<font color="Crimson">値渡し・参照渡し</font>で)

```c#

using System;
class ByReferenceTest
{
  static void Main()
  {
    int a = 100;
    Console.Write("{0} → ", a);// 100 (ref無し)値渡しではstatic関数内でのみ換わる//100.10
    Test(ref a);
    Console.Write("{0}\n", a);// 10
  }

  static void Test(ref int a)// (ref)参照情報を渡せばMainメソッドの識別子の値も変換できる//10.100→10
  {
    a = 10;

  }
}
```

##例外. メンバ変数とローカル変数
(メンバ変数(Field)とローカル変数{入れ子}は同じ名前OK、逆に同じブロック内はNG)

```c#

public class Sample
{
    int x = 20;// Field(メンバ変数)

    public void M()
    {
        int x = 10;//public void M()(ローカル関数、入れ子)

        Console.WriteLine(x);      // ローカル変数の方の x = 10(あとから書いたのでローカル優先)
        Console.WriteLine(this.x); // フィールドの方の x = 20(参照必要this.~)
    }
}
```

[参考:++C++; // 未確認飛行 C](https://ufcpp.net/study/csharp/start/st_scope/)





<br>
<br>






#<font color="SlateGray">列挙型enum

<b>0から複数の定数を割り当てて列挙できる。</b>

>通常、列挙型は名前空間内に直接定義して、名前空間内のすべてのクラスが共通の利便性でアクセスできるようにするのが最も適切です。 

(enumの定数はグローバルに属するから<font color="DarkCyan">スコープ内</font>の定数重複はエラー。 
そのためclassやnamespaceでわけて定義すべき)
<br>

>基になる型は、列挙子ごとに割り当てるストレージの大きさを指定します。 ただし、 enum 型を整数型に変換するには、明示的なキャストが必要です。

(型名は範囲の事で既定intなので十分大きい。
またenum型を整数型として扱いたい場合キャストで変換`int x = (int)Day.Sun;`

[引用:MSDN](https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/enum)

##例. キャストで変換
enum 列挙名:型名{列挙子リスト};// 型名intが既定
enum WcScoreRank{Honda, Inui, Okazaki};// Pascal
既定値オーバーライド可能。`{Honda=1, Inui, Okazaki}`

```c#

public class WcTopScorersJP
{
    enum Rank { Honda, Inui, Okazaki, Kagawa, Osako, Haraguti };
     // global属性なので重複注意(namespaceで分ければ理想)

    static void Main()
    {
        int x = (int)Rank.Honda;// 'キャスト'しないとエラー
        int y = (int)Rank.Osako;
        Console.WriteLine($"Honda = {x}");// Honda = 0
        Console.WriteLine($"Osako = {y}");// Osako = 4
    }
}
```

<br>
abc 066

B
同じ文字列を 2 つ並べてできる文字列のことを偶文字列と呼ぶことにします。 例えば、 xyzxyz や aaaaaa は偶文字列ですが、ababab や xyzxy は偶文字列ではありません。
アルファベットの小文字からなる偶文字列 S が与えられます。 S の末尾の文字を 1 文字以上消して作れる偶文字列のうち、最も長い偶文字列の長さを求めて下さい。 与えられる入力では、条件を満たす 1 文字以上の文字列が存在することが保証されています。

```
#include<iostream>
#include<string>
using namespace std;
int main() {
	string S;
	cin >> S;
	for (int i = 1; i < S.size(); ++i) {
		if ((S.size() - i) % 2 == 0) {
			if (S.substr(0, (S.size() - i) / 2) == S.substr((S.size() - i)/2, (S.size() - i) / 2)) {
				cout << S.size() - i;
				break;
			}
		}
	}
	return 0;
}
```
S.pop_back()を使ってもよい

C
長さ n の数列 a1,…,an が与えられます。 空の数列 b に対して、以下の操作を n 回行うことを考えます。
i 回目には
数列の i 番目の要素 ai を b の末尾に追加する。
b を逆向きに並び替える。
この操作をしてできる数列 b を求めて下さい。
制約
1≤n≤2×105
0≤ai≤109
n,ai は整数である。

シミュレーションはきついか？
実験するとaを1個飛ばしに出力して残りを前から出力すればよいことがわかる。

```
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<map>
#include<math.h>
#include<queue>
#include<deque>
#include<stack>
#include<cstdio>
#include<utility>
#include<set>
#include<list>
#include<cmath>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int INF = 1e9;
int main() {
	int n;
	cin >> n;
	vector<int>a(n);
	for (int i = 0; i < n; ++i) {
		cin >> a[i];
	}
	for (int i = n - 1; i >= 0; i -= 2) {
		cout << a[i] << " ";
	}
	int k;
	if (n % 2 == 0)k = 0;
	else k = 1;
	for (int i = k; i < n - 1; i += 2) {
		cout << a[i] << " ";
	}
	cout << endl;
	return 0;
}
```
実装するとこうなる。
dequeを使えばシミュレーションもできるっぽい
1,後ろに入れる
2,上下逆転させる
を繰り返す操作は後ろに入れる→前に入れる→後ろに入れる→前に入れる,,,
に相当する。dequeで後ろ、前、後ろ、前でやっていく。取り出すときはNが偶数なら上下は普通に戻っているので先頭から、そうでないなら上下逆転している状態で終わっているので後ろから取り出す。以下簡単なdequeの説明と問題の解答

```
std::deque<int> dq{3, 1, 4, 1, 5};
    std::cout << dq.front() << "\n";      //  最初の要素（3）を表示
    std::cout << dq.back() << "\n";      //  最後の要素（5）を表示

```

```   
 std::deque<int> v{1, 2, 3, 4};
    std::deque<int>::iterator itr = v.begin();   // 最初の要素を指すイテレータ
    std::cout << *itr << "\n";      // 最初の要素の値を表示
    ++itr;   // 次の要素に移動
    *itr = 9;    // 二番めの要素の値を 9 に変更
```

```
 std::deque<int> v;       // 空の両端キューを生成
    v.push_front(123);     // 先頭に 123 を追加

std::deque<int> v;       // 空の両端キューを生成
    v.push_back(789);     // 末尾に 789 を追加
```
```
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<map>
#include<math.h>
#include<queue>
#include<deque>
#include<stack>
#include<cstdio>
#include<utility>
#include<set>
#include<list>
#include<cmath>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int INF = 1e9;
int main() {
	int n;
	cin >> n;
	int a[200010];
	for (int i = 0; i < n; ++i) {
		cin >> a[i];
	}
	deque<int>deq;
	for (int i = 0; i < n; ++i) {
		if (i % 2 == 0)deq.push_back(a[i]);
		else deq.push_front(a[i]);
	}
	if (n % 2 == 0) {
		for (int i = 0; i < n; ++i) {
			cout << deq.at(i) << " ";
		}
	}
	else {
		for (int i = n-1; i >=0; --i) {
			cout << deq.at(i) << " ";
		}
	}
	cout << endl;
	return 0;
}
```
GitHubのOrganizationsって何？

初めてGitHubにアカウント登録するときに、organizationを登録しろって言われて分からずに調べたので備忘として残します。
※間違ってたら指摘してください

**まずそのOrganization画面に行った時点で入力しなくてもアカウント登録は一旦完了しています**
ホームに戻るとそのままアカウント登録そのものは完了しています。

しかしここではOrganizationsの解説をしましょう。
きっとここへ飛んできたあなたは以下の画面の状態でしょう
![github.png](https://qiita-image-store.s3.amazonaws.com/0/297910/24e368aa-5df0-b64e-26ba-4a3544770b0d.png)

Organizationsとは所属チームのことと思っていいと思います。
つまりチーム名を決めてそこに追加された人のみが、該当ブランチに対する操作をすることが可能になります（マージ権限等）
もちろん同じOrganization内でマージ権限をもたせる持たせないなどの権限付与が出来る。（それぞれの役割の詳細は省きます）
・Owner permission
・Admin permission
・Write permission
・Read permission

※ちなみにプルリクエスト自体は誰でも可能です（公開されている場合）。
開発者組織のブランディングに使われたりしているらしいです。
<<続編>>「MapAPI を研究したら1週間でWebサービスをリリース」

# 【 それからどうなったか？ 】
１週間でインプット＆１週間でアウトプット、その後の展開をご報告させていただきます。


前回の投稿記事：「MapAPI を研究したら1週間でWebサービスをリリースした話」
https://qiita.com/daisu_yamazaki/items/3158ad20cb1290ea6901

## 【 アクセスユーザー数（Googleアナリティクス） 】
Qiita記事投稿日： 2018-09-25（現時点で１０日間程）。
結果：
- Qiitaページを閲覧したユーザー： 1,365名
- Qiita いいね！数：189
- Webサービスを閲覧したユーザー数： 1,103名
- 勢いでドメインも取得（ mapapi.org ）
- 大手IT企業からの沢山のアクセス


#  報告 『 Bing Map APIの本』を書きました。
特にMapAPIは基本さえ理解すれば使い方がわかってくるので基本をメインに書きました！！
「 Kindle Unlimited 」の加入者は、是非無料で読んでくださいm(__)m 
https://www.amazon.co.jp/dp/B07J1RZ5HJ/
<img width="400" alt="Kindle_Previewer.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/104530/8dc2a58e-4b8c-29cd-52f0-8c24253a5bb5.jpeg">








# 【 結果 】
- Qiitaへ投稿したのは良かった！
これだけのユーザーに知っていただくことができたのは驚きです。
- そして、やはりインプットした以上は、アウトプットは必定。
- みなさんが初めて「 BingMaps API」を使うときの取っ掛かりになる本として役にたてば良いなーと思ったので書きました。
（ニーズは多くないことは分かってます、しかし、これから学生やスタートアップがMapAPIを使う場合にはクレカ登録がいらず、さらにGoogle並に機能がそなわっているBingMapの選択をするケースも増えるのでは・・・など考えると、最低限の情報は誰かしらが書いていかないと行けないわけです。誰もがいろんな人の記事に助けられたように、私もその一人でありたいと思い書きました。


# 【 感想 】
理解して使えるようになる、制作力を上げるには、最もOUTPUTが重要だと再認識です(これは前回と同じ)。
この１ヶ月で 「Webサービス」「本」「MapAPIの知識」と素晴らしい資産が残りました。
※但し、トントン拍子ではなく、その前にVue.jsを始めて基本的な理解まで進んだ時点で、MapAPIの魅力にハマり、MapAPIしか頭に残らず・・・知識の散財した時期も１〜２ヶ月ありました。やってみないとわからない、けど進めば何かしらが起きる！思ったら行動でした。
最高の学び、最高のアウトプットにつなげるのは「やれることを集中して”やり切る！”」ことなのかなと体験しました。
結果、３週間程でのインプット・アウトプットでしたが、とても全力の熱い日々を過ごせました！！
睡眠時間は１日３時間程度の３〜４週間でしたが、充実してました。
作りたいことを一生懸命やる！！みなさんも情熱プログラミング！！！
是非、Webサービスを作ってみたい人の少しでも参考になればと思います。
以上

# 【 謝辞 】
これも最高の学習環境/研究環境を提供してくださっている、
ジーズアカデミーTOKYO、デジタルハリウッド大学院 に感謝です。 
もちろん得た知識＆経験などは「学生に還元」していきます。
※環境は大事！

# 【 その後の展開もありました 】
https://qiita.com/daisu_yamazaki/items/f9c51f341065aac63719
Visual Studio CodeでER図作成

# 準備
## Visual Studio Code
これはもちろん必須。

## Graphviz
http://www.graphviz.org/
こちらからダウンロード。UML描画のために必要らしい。

## PlantUML
拡張機能「PlantUML」をインストールする。

# ER図の作成の仕方
拡張子「.puml」でファイルを作成して、中身を記述する。

```text:sample
@startuml erdiagram
entity "app" {
    + app_id [PK]
    ==
    app_cd
    app_type
}

entity "app_detail" {
    + app_detail_id [PK]
    ==
    # app_id [FK(app.app_id)]
    app_cnt
}

app --o{ app_detail
@enduml
```

## エンティティ
```
entity "entityA" {
    + id [PK]
    ==
    # element_id [FK(element,element_id)]
    valid_flg
    create_date
}
```

## リレーション
- 1:1

``` 
entityA ||--|| entityB
```

- 1:0orN

```
entityC --o{ entityD
```

- 1:0or1

```
entityC --o| entityD
```

- 1:1orN

```
entityC --|{ entityD
```

- N:N

```
entityC }--{ entityD
```

## ラベルをつける
```
entity "entity_name"<ラベル> {
```


## プレビュー
「Alt + D」でプレビュー表示できる。

## 出力
「Ctrl + Shift + P」で、「PlantUML：カーソル位置のダイアグラムをエクスポート」を選択。
形式を選択してエクスポートする。


# リンク
- [Visual Studio Code で UML を描こう！](https://qiita.com/couzie/items/9dedb834c5aff09ea7b2)
- [PlantUMLでER図を書いて、githubで管理してみた](https://qiita.com/2ndponpu/items/23210cd080d358780d79)
react-native-firebaseで import { database } from 'react-native-firebase'が可能になった。

タイトルの通り。
react-native-firebase 5.0.0で
import { database } from 'react-native-firebase'
が可能になった。

これからは
import Firebase from 'react-native-firebase'

FIrebase.database()
などとしなくていい。
やったね。

リリースノートは以下
https://rnfirebase.io/docs/v5.x.x/release-notes
Scrapboxで選択した範囲をTodoistに追加

# 概要
Scrapboxで書き散らした内容を片っ端からTodoistにタスクとして追加していくためのプログラム。なお、本手法はTodoistTokenをUserScriptに記載する必要があるため、クローズドなプロジェクトかつ、信頼できる場所で利用するのが望ましい。
実装にはGoogleAppsScriptとScrapboxのUserScriptを利用する。

# 下準備
本記事で説明するコードは事前に以下の準備が必要である。本記事での説明は省略する。

- [Incoming WebHooksの設定](https://qiita.com/vmmhypervisor/items/18c99624a84df8b31008)
- [Outgoing Webhooksの設定](https://qiita.com/chike0905/items/58222a99be460f325ab8)
- Todoist tokenの取得
   - Todoistの[設定]>[連携機能]>[APIトークン]
- [GoogleAppsScriptをWebアプリケーションとして導入](https://tonari-it.com/gas-web-application-beginner/#i-2)

# 実装
GAS側のコードを以下に示す。

```js
function doGet(e) {
  var params = e.parameter;
  var url = "https://todoist.com/API/v7/sync",
      uuid = Utilities.getUuid(),
      tempId = Utilities.getUuid(),formData, response;
  if(e.parameter==undefined){
    Logger.log("error");
  }else{
    var token=params.token;
    var projectId = searchProject(params.projectName,token),
        formData = {
          "token": token,
          "commands": 
          JSON.stringify([{
            "type": "item_add",
            "temp_id": tempId,
            "uuid": uuid,
            "args": {
              "priority" : params.priority,
              "content": ""+decodeURIComponent(params.text),
              "project_id": projectId, 
              "due": {
              "string": params.limit,
            },
          }
                          }])
        };
    response = UrlFetchApp.fetch(url, {
      "method" : "post",
      "payload" : formData
    });  
    return response.getResponseCode();
  }  
}
function searchProject(projectName,token){
  var projectName="test",
      url = "https://todoist.com/API/v7/sync",
      formData,options,response;
  var headers = {
    "Accept": "application/json",
  };
  formData ={
    "token": token,
    "sync_token":"*",
    "resource_types":'["projects"]',
  };
  response = UrlFetchApp.fetch(url,{
    "contentType": "application/json",
    "headers":headers,
    "method":"post",
    "payload":JSON.stringify(formData)
  });
  var array = JSON.parse(response.getContentText());
  for(var i = 0; i < array["projects"].length; i++){
    if(array["projects"][i]["name"]===projectName){
      return array["projects"][i]["id"];
    }
  }
  return 000000;
}
```


Scrapbox側のコードを以下に示す。tokenとGASで発行したウェブアプリケーションをコード内の該当箇所に入力する必要がある。

```js
scrapbox.PopupMenu.addButton({
title:'Todo',
 	onClick: text =>{
      const lines = text
        .split(/[\r\n]/)
        .map(line => line.replace(/[\[\]]/g, '').replace(/^\s+/, ''))         
    	const param = {
    		'text': lines,
      		'priority':1,
        	'limit':'',
         	'projectName':'',
          'token':"<<自分のTodoistToken>>",
    	}
     console.log(lines)
     	const query = Object.keys(param)
      						.map(key => `${key}=${encodeURIComponent(param[key])}`)
            				.join('&')
                  
        const url = `<<GASで発行したウェブアプリケーションURL>>?${query}`
     window.open(url)
   }
})

```

# 雑記
ScrapboxのUserScriptで期限や登録するプロジェクトや期限、優先度などを変更できる。片っ端から放り込むという割にはポップアップが多少うざったいかもしれない。
DockerのPostgresで初回起動時にpg_restoreをする

#起きたこと

Postgres コンテナの初期化処理のときに、 `pg_restore`コマンドを使い、リストアをしたかったが何故か`pg_restore`終了時にコンテナが落ちた。

※通常初期データを入れる方法は
https://qiita.com/kashi0001/items/8d8f9055cbc3ef719127
を参照

# docker-compose

``` yaml
  postgres:
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: test
    volumes:
volumes:
      - ./postgres_init:/docker-entrypoint-initdb.d
      - ./postgresql/data:/var/lib/postgresql/data
    environment:
      - TZ=Asia/Tokyo

```

# create.sh (./postgres_init)配下
``` sh
~いろいろ処理~
pg_restore -c -d test -U test ./test.dmp &>/dev/null
echo "ここで落ちる"
~いろいろ処理~ 
```

# 修正

# create.sh (./postgresql/data)配下
``` bash
bash << EOS
#!/bin/bash
echo "リストア開始"
pg_restore -c -d test -U test ./test.dmp &>/dev/null
echo "リストア終了"
EOS
```

# 原因
おそらく`pg_restore`が終了したときに exitコードをなげそれをDockerコンテナのメインプロセス上で受け取ってしまっている。
よって bash で明示的に実行することにより、別プロセス実行し、そのプロセスがエラーで落ちても、メインプロセスに影響が及ばないようにする。
Intel Compute Stick をサーバ化

# Intel Compute Stick を Ubuntu Server に
x86_64 で，ある程度の処理をこなせる安価な小型 PC が欲しくて [Intel Compute Stick](https://www.amazon.co.jp/dp/B00W7KAABK) を購入．
しかしデフォルトで入っている Ubuntu 14.04 LTS は GUI しか無くて，
8GB しかないストレージを圧迫しているし，Wi-Fi のレイテンシがやたら高くて不安定．
そこで Ubuntu 18 を導入し，サーバとして動かすまでの初期設定をメモ．

# Intel Compute Stick の Wi-Fi 問題
Ubuntu 18 はデフォルトでは Wi-Fi モジュールの RTL8723BS を認識しない．
しかしインターネット無しでインストールを進めるのは色々と困難があるので，
[有線 LAN ポートの付いた USB ハブ](https://www.amazon.co.jp/dp/B01N8OHX08/)を使って有線ネットワーク接続を行い，
Ubuntu 18 を USB メモリからブートしてインストール．

# RTX8723BS 用のドライバをインストール
[Intel Compute StickでUbuntu16.04 を使う](https://qiita.com/trkbt10/items/ab45e90c363fb75759b7)を参考に，以下のコマンドを実行．
これもインターネット接続があればこそできることなので，
有線 LAN ポート付きの USB ハブは偉大．

```shell
$ sudo apt update
$ sudo apt install build-essential linux-headers-generic git
$ git clone https://github.com/hadess/rtl8723as.git
$ cd rtl8723as
$ make
$ sudo make install
$ sudo depmod -a
$ sudo modprobe r8723bs
```

# Wi-Fi の設定
Ubuntu 17 からはネットワーク管理に netplan が採用されたので，せっかくなので使ってみた．
複数の SSID (hoge, piyo) にそれぞれのパスワード（fuga, hogera）を設定しておけば，
自動でつなぎ変えてくれるようになる．
昔は wpa-roam でやっていたなぁ．
optional: true とすることで，ブート時にネットワーク構成に失敗しても待たない設定になる．

```shell
$ sudo vim /etc/netplan/interfaces.yaml

+ network:
+     version: 2
+     renderer: networkd
+     ethernets:
+         eth0:
+             addresses: []
+             dhcp4: true
+             optional: true
+     wifis:
+         wlan0:
+             addresses: []
+             dhcp4: true
+             optional: true
+             access-points:
+                 "hoge":
+                     password: "fuga"
+                 "piyo":
+                     password: "hogera"

$ sudo netplan apply
```

# HDMI モニタ無しでの起動
GRUB の設定などで対応する方法もあるようなのだが，試したが上手く行かず．
[HDMI のモニタとして認識されるデバイス](https://www.amazon.co.jp/dp/B07BBP8YVY/)を挿すことで対応．
しかし一般的にこのデバイスは HDMI のオス端子なので，[HDMI のメスメスコネクタ](https://www.amazon.co.jp/dp/B00CIQL3MI/)で接続．

# apt のゴミを削除
ストレージを圧迫しがちな不要なパッケージは適宜削除する．

```shell
$ df
$ sudo apt autoremove
```

# できあがり
あとは ssh や systemd あたりの設定をしておけば，USB mini type C で電源を与えればどこでもサーバとして起動する PC のできあがり．
ラズパイとの比較は以下．

|  Item  | ComputeStick | Raspberry Pi 3B |
|:--------:|:-------------:|:---------------:|
| CPU | Intel Atom Z3735F | ARM Cortex-A53 |
| Core | 4 | 4 |
| Clock | 1.33~1.83GHz | 1.2~1.5GHz |
| RAM | 1GB | 1GB |
| Storage | 8GB | N/A |
| USB | 2.0x1 | 2.0x4 |
| Size | 10.3 x 3.8 x 1.3 cm | 8.5 x 5.6 x 1.7 cm |
| Weight | 54.5g | 45.4g |
| w/ | Fan, MicroSD, Cover | Ethernet, φ3.5cmOutput,... |
| w/o | Audio | Storage, A/C Adapter, Cover |
| Custom | Difficult | Easy |
| Price | 5,740 JPY | 5,220 JPY |

見た目の性能，価格はほとんど変わらないが，処理は Intel Compute Stick の方が速い気がした．
BogoMips で比較するのも恥ずかしいが，Intel Compute Stick は 2665.60，Raspberry Pi 3 は 38.40 なので速度に影響が出る程度の差はある．
そこは Intel x86 と ARM Cortex やら CPU キャッシュ・ストレージ速度の違いか．
特にハードのカスタマイズをしない用途ならば，Intel Compute Stick も悪くないと思う．
Angular でアコーディオンを実装

## 背景
Angularで、"「詳しい情報を表示・・・」を押すと、にゅるっとアコーディオンが開く"みたいな機能を実装したく、Animationsを使って実装してみました。
当初、ngx-bootstrapのAccordionModuleを使おうと思ったのですが、イマイチやりたいことができなかったので、こちらの方法をとりました。

## 前提
@angular/animationsを使用しています。
Angular4以降は設定方法が変わったらしく、導入の際は以下の記事が参考になりました。
[Angular2からAngular4に移行してうまく動かなかったところ[Animation]](https://qiita.com/tebakane/items/a3090124607a432e26bb)

また、詳細の表示時と非表示にプラスとマイナスのアイコンを出したかったので、Font Awesomeから適当にアイコンとってきてます。なくても問題ないです。

## 実装
それでは実装箇所です。
[ソースコードはこちら](https://github.com/hiropon33/angular-accordion-example.git)

```app.module.ts
// import for animations
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports: [
    BrowserAnimationsModule,
  ],
})
```
```accordion.html
<!-- アコーディオンを開く閉じるのボタン -->
<div class="pointerCursor" (click)="onAccordion($event)">
  <i [ngClass]="showDetail ? 'fa fa-minus-circle' : 'fa fa-plus-circle'"></i>
      &nbsp;詳しい情報を{{showDetail ? '隠す' : '表示する'}}
</div>

<!-- アコーディオンの中身 -->
<div *ngIf="showDetail" [@accordion]>
    〜アコーディオンで表示したい内容〜
</div>

```


```accordion.component.ts
import { trigger, style, animate, transition } from '@angular/animations';

@Component({
  selector: 'sample-app',
  templateUrl: './accordion.html',
  styleUrls: ['./accordionStyle.scss'],
  animations: [
    trigger('accordion', [
      transition(':enter', [
        style({ height: '0', opacity: 0, overflow: 'hidden' }),
        animate('500ms', style({ height: '*', opacity: 1 }))
      ]),
      transition(':leave', [
        style({ height: '*', opacity: '1', overflow: 'hidden' }),
        animate('500ms', style({ height: '0' }))
      ])
    ])
  ],
})

export class AccordionTest {

  public showDetail: boolean;
  
  constructor(){
  }

  // アコーディオン開閉時に呼ばれるイベント
  onAccordion($event) {
    this.showDetail = !this.showDetail;
  }
}
```

クリックできる感を出したかったので、以下のCSSを適用しています。

```accordionStyle.scss
// マウスポインターを指マークにする
.pointerCursor {
    cursor: pointer;
}
```

## 最後に
こんな感じに仕上がるかと思います。
![angular-accordion-example.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/157350/4e98068b-84f1-778d-96ff-5747ceb5c54a.gif)

### 参考
[Angular2からAngular4に移行してうまく動かなかったところ[Animation]](https://qiita.com/tebakane/items/a3090124607a432e26bb)
[angular 6 animation *ngIf, transition not work](https://stackoverflow.com/questions/50300442/angular-6-animation-ngif-transition-not-work?noredirect=1&lq=1)
[CSSだけでアコーディオンを作る方法](https://saruwakakun.com/html-css/reference/accordion)
コマンドプロンプトでcurl実行するときは、”（ダブルクォート）使う

windowsのコマンドプロンプトでcurlを実行した際、

```
curl: (1) Protocol "'https" not supported or disabled in libcurl
'xxx' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
```
とエラーが出た。

##原因
curlコマンドは、シングルクォーテーションでくくられた文字列は無視してしまう。

##解決策
引数をダブルクォーテーションでくくる


「内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。」とググると、
プロキシの設定が出来ていないだとか、環境変数を設定すると解決する、パスが通っていないだとかしか出てこなかったので、
プロキシの設定が間違っているとばかり思っていましたが、違いました。

windowsユーザーは、ハマりやすいみたいです。
気を付けます。
[Ruby] moduleをSwiftのenumみたいに使ってみる 

## 環境関連
```
$ ruby -v 
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin17]

$ rails -v
Rails 5.2.0
```
## 参考にしたサイト
@yuch_i さんの記事↓
https://qiita.com/yuch_i/items/fa823a5ee3d569859137

## やりたいこと

Swiftだとこんなイメージ

```
enum Type {
  case typeA
  case typeB
  case typeC
}

class Hoge: UIViewController {
  
  //.....
  
  func hogeeee(type: Type) {
    switch type {
    case .typeA:
      // typeAの時にしたい処理
      print("typeA !!")      
    case .typeB:
      // typeBの時にしたい処理
      print("typeB !!")
    case .typeC:
      // typeCの時にしたい処理
      print("typeC !!")
    default:
      // 例外とか
    }
  }  
  
  //.....  
}
```

んー、美しい。

## 何がしたいのか整理してみる

- 引数の値が、決められた値の中のどれかを判別し、該当の処理を行いたい
- 決められた値、が変動する際に修正が容易になるようにしたい
- 見た目を***スタイリッシュ***にしたい(固定文字列とか使いたくない)

## 元々のRubyでの処理

```
# name ==> 'hoge', 'huga', 'foo' の3種類
# location ==> 'japan', 'usa', 'italy' の3種類

class xxxUtil
  def send_url(name, location)
    # TODO: nameのパターンが増えたらどうする!?
    case name
    when 'hoge' then
      # TODO: locationのパターンが増えたらどうする!?
      case location
      when 'japan' then
        # 'hoge' かつ 'japan'の時の処理
      when 'usa' then
        # 'hoge' かつ 'usa'の時の処理
      when 'italy' then
        # 'hoge' かつ 'italy'の時の処理
      end
    when 'huga' then
      # 同上
    when 'foo' then
      # 同上
    else
      # 例外の時の処理
    end
  end
end
```

こんな感じに、固定文字列をそのまま記載していた感じ。
name/locationのパターンがずっと固定ならば、***イケてはいないですが***、まだ許せるかもと思って見て見ぬ振りをしてました...
ただ、今回パターンが増えることになってしまい、今後のことも考えるとやはり不便だったので、整理してみようと思ったのが経緯です。

## 最終的に

```
module Name
  HOGE = 'hoge'
  HUGA = 'huga'
  FOO  = 'foo'
end

module Location
  JAPAN = 'japan'
  USA   = 'usa'
  ITALY = 'italy'
end

class xxxUtil
  def send_url(name, location)
    # TODO: nameのパターンが増えたらここ増やす
    case name
    when Name::HOGE then
      # TODO: locationのパターンが増えたらここ増やす
      case location
      when Location::JAPAN then
        # 'hoge' かつ 'japan'の時の処理
      when Location::USA then
        # 'hoge' かつ 'usa'の時の処理
      when Location::ITALY then
        # 'hoge' かつ 'italy'の時の処理
      end
    when Name::HUGA then
      # 同上
    when Name::FOO then
      # 同上
    else
      # 例外の時の処理
    end
  end
end
```

## これに変えると何がうまいのか
- Name/Locationの既存の各値が変更になった時に容易(特に複数箇所から参照されて同じような判別処理が必要になる場合)
- Name/Locationに項目が追加になった時、case文も修正することになるが、修正箇所を追いやすくなる('Location'で検索して、対応のcase文を直せば良くなる)

※ 今回は、似たような判別式が複数箇所に必要になる場合だったので、特にありがたみを感じました。

## 注意点
・moduleの記載が別ファイルの場合、moduleを記載しているファイルをrequire_relative(インポート)しないと参照出来ないっぽい

## まとめ

今回のアプローチが正しいのかは、わかりませんが....
なんとなく見やすくなって、コードも気分もスッキリしました。
この修正後、項目追加しても修正範囲がわかりやすくて、作業しやすくなった気がします。
GooglePlayからアプリが削除されたけど異議申し立てたら復活した

対象のアプリ
----
- ローカルに大量の画像を生成するだけのデバッグ用アプリです。

https://play.google.com/store/apps/details?id=jp.shts.android.sampleimagecreator

事の経緯
----
- 8/21 ポリシー違反で公開停止＆アプリ削除
- 9/29 異議申し立て
- 10/5 再開

詳細
---

### ポリシー違反で公開停止＆アプリ削除

内容は**なりすまし**に関するポリシー違反でした。

思い当たる節が無さ過ぎます...。
が、個人アプリだしすぐに困る人もいないと思ったのでしばらく放置していました。

### 異議申し立て

１ヶ月後にアプリのアップデートする必要あるかもしれないことがわかり、慌ててポリシーを読んでみたけどやっぱりわからん。

なので異議申し立てをしました。というよりただの質問ですが、丁寧な言葉で「どこ？ダメっすか？」と聞きました。

### 再開

回答があり、あっけなく再開。

「お客様のアプリを再度詳しく検討し、アプリXXXを元に戻しましたのでお知らせいたします。」

後から思ったことなんですが、ランチャーアイコンがデフォルトのままなのが、影響しているのかなと思いました。つまりドロイド君のなりすましと判定されたのかと。可能性は０じゃない気がします。

詳しく検討の内容について記載がないのでこれ以上はわかりませんが気をつけたほうが良さそうです。

以上です。
abc 065

B
筋力をつけたい高橋君は、AtCoder 社のトレーニング設備で、トレーニングをすることにしました。
AtCoder 社のトレーニング設備には N 個のボタンがついており、ちょうど 1 個のボタンが光っています。 ボタンには、1 から N までの番号がついています。 ボタン i が光っているときにそのボタンを押すと、ボタン i の明かりが消え、その後ボタン ai が光ります。i=ai であることもあります。 光っていないボタンを押しても、何も起こりません。
最初、ボタン 1 が光っています。高橋君は、ボタン 2 が光っている状態で、トレーニングをやめたいと思っています。
そのようなことは可能かどうか判定し、もし可能なら最低で何回ボタンを押す必要があるかを求めてください。

wakaran

```
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main() {
	int N;
	cin >> N;
	vector<int>a(N);
	vector<bool>c(N, true);
	for (int i = 0; i < N; ++i) {
		cin >> a[i];
	}
	int i = 0, count = 1;
	while (a[i] != 2) {
		if (!c[i]) {
			cout << "-1";
			return 0;
		}
		c[i] = false;
		i = a[i] - 1;
		count++;
	}
	cout << count;
	return 0;
}
```
賢い！まだまだやな、、

すぬけ君は、犬を N 匹と猿を M 匹飼っています。すぬけ君は、この N+M 匹を一列に並べようと思っています。
文字通り犬猿の仲の犬たちと猿たちを仲直りさせたいすぬけ君は、犬同士、または猿同士が隣り合うところができないように並べようと思っています。
このような並べ方は何通りあるでしょうか。犬と猿は 109+7 以上の数を理解できないので、並べ方の個数を 109+7 で割ったあまりを求めてください。 ただし、犬同士、また猿同士は互いに区別します。また、左右が反転しただけの列も異なる列とみなします。
制約
1≦N,M≦105

```#include<iostream>
#define x 1000000007;
using namespace std;
typedef long long ll;
int main() {
	int N, M;
	cin >> N >> M;
	ll ans = 1;
	if (abs(N - M) >= 2) {
		cout << 0 << endl;
		return 0;
	}
	else {
		for (int i = 1; i <= N; ++i) {
			ans *= i;
			ans %= x;
		}
		for (int i = 1; i <= M; ++i) {
			ans *= i;
			ans %= x;
		}
		if (N == M) {
			ans *= 2;
			ans %= x;
			cout << ans << endl;
		}
		else
			cout << ans << endl;
	}
	return 0;
}
```
簡単な数学
住所から緯度経度を取得するpythonスニペット

## この記事について

位置情報分析をしていると、住所から緯度経度を取得したくなるケースに遭遇する。
アドホック分析においては、各種無料で利用できるAPIを叩くのが一般的である。
毎回手で書くのもいい加減めんどくさかったので、備忘録がてらメモを残しておく。

## 利用するAPI

[geocoding.jp](https://www.geocoding.jp/)のAPIを利用する。API提供元に迷惑をかけないようにアクセス間隔は10秒あける。

## コード

本体はこんな感じ。利用方法はdocstringに書いたとおり。
なお、コメントに@shiracamus様がキレイに整えてくれた実装が有るので、実用上はそちらをおすすめします。

```.py
import requests
from bs4 import BeautifulSoup
import time
from tqdm import tqdm


def get_lat_lon_from_address(address_l):
    """
    address_lにlistの形で住所を入れてあげると、latlonsという入れ子上のリストで緯度経度のリストを返す関数。
    >>>>get_lat_lon_from_address(['東京都文京区本郷7-3-1','東京都文京区湯島３丁目３０−１'])
    [['35.712056', '139.762775'], ['35.707771', '139.768205']]
    """
    url = 'http://www.geocoding.jp/api/'
    latlons = []
    for address in tqdm(address_l):
        payload = {"v": 1.1, 'q': address}
        r = requests.get(url, params=payload)
        ret = BeautifulSoup(r.content,'lxml')
        if ret.find('error'):
            raise ValueError(f"Invalid address submitted. {address}")
        else:
            lat = ret.find('lat').string
            lon = ret.find('lng').string
            latlons.append([lat,lon])
            time.sleep(10)
    return latlons
```
社内Proxy環境下にDocker for Windowsを入れてみた（Kitematicも含めて）

# やりたいこと
自身の端末にDocker for Windowsを導入し、
Elasticsearch+KibanaでRedmineのチケット解析をしたい

# 環境
* Windows10Pro
* Proxy環境下
* Docker for Windows

# やったこと
## 1.Docker for Windows の インストール
### 1.Windows 10で仮想化プラットフォーム「Hyper-V」を有効にする
- [参考URL](http://www.atmarkit.co.jp/ait/articles/1806/25/news026.html)

### 2.Docker for Windowsのインストールの実行
- Docker for Windowsのサイトからインストーラーをダウンロードし、実行します。
- インストールには特に設定項目はなく、Insallボタンをクリックすると自動でインストールが行われます。
- [Docker for Windowsのサイト](https://docs.docker.com/docker-for-windows/)

### 3.Dockerの動作確認
以下のコマンドでDockerのインストールを確認
```docker --version
```

### 4.Dockerのプロキシを設定
任意のプロキシサーバを設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/138392/3281ca2e-9f1c-d9e6-209c-d26f463b02a6.png)

## 2.kitematic の 実行

### 1.kitematic の ダウンロード
Dockerのメニューからkitematicを選択し、以下の画面からダウンロード
![image.png](https://qiita-image-store.s3.amazonaws.com/0/138392/3c4308aa-09f0-2906-e333-24b2b9f0f174.png)

### 2.kitematic の 起動
任意のプロキシサーバのアドレスを設定し、kitematic.exeを起動
※本バッチはkitematic.exeが存在する階層で実行
![image.png](https://qiita-image-store.s3.amazonaws.com/0/138392/14e9a7d8-8642-b57d-64ef-7a4190e49db0.png)
起動！！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/138392/92affc00-81d8-6a13-9e4a-79a99f2d2321.png)
SJISでコーディングしてはいけない、たった一つの理由

ダメ文字を意識しながらコーディングしなければならないからです。

# ダメ文字とは？
[Shift_JISのダメ文字](https://sites.google.com/site/fudist/Home/grep/sjis-damemoji-jp)
[ダメ文字一覧表](https://sites.google.com/site/fudist/Home/grep/sjis-damemoji-jp/table)

# 例

```C:a.c
#include <stdio.h>

void func(int x){
    // 与えられた変数を表示するだけの機能
    printf("%d\n", x);
    return;
}

int main(void){
    // ビット表
    int bitmap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

    func(bitmap[0]);
}
```

このプログラムをSJIS（Shift-JIS）で保存しコンパイルすると、エラーが発生します（UTF-8で保存してコンパイルすると、エラーは発生しません）。

```console
$ gcc a.c
a.c: 関数 ‘main’ 内:
a.c:13:10: エラー: ‘bitmap’ が宣言されていません (この関数内での最初の使用)
     func(bitmap[0]);
          ^
a.c:13:10: 備考: 未宣言の識別子は出現した各関数内で一回のみ報告されます
```

変数bitmapは宣言されているにも関わらず、「‘bitmap’ が宣言されていません」というエラーが発生します。


## 原因は「表」
「// ビット表」というコメントがありますが、**「表」はダメ文字です。**この「表」という文字の2byte目は「\」です。つまり行の終わりに「\」と書かれていることと同じになります。これはC言語においては**次の行までコメントアウトされてしまいます。**

しょうがないので修正してなんとかしましょう。

```C:a.c
#include <stdio.h>

void func(int x){
    // 与えられた変数を表示するだけの機能
    printf("%d\n", x);
    return;
}

int main(void){
    // ビット表
    // 「このコメントを削除するとなぜかコンパイルエラーが起きる」という現象が起きる
    int bitmap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

    func(bitmap[0]);
}
```

さて、上記のように修正したプログラムを再度コンパイルします。今度はコンパイルエラーは発生しません。コンパイル成功です！プログラムを実行してみましょう。

```
$ gcc a.c
$ ./a.exe
(何も表示されない)
```

本来なら「1」を出力するはずですが、何も表示されませんでした。

## 原因は「能」
「// 与えられた変数を表示するだけの機能」というコメントがありますが、**「能」もダメ文字です。**この「能」という文字の2byte目は「\」です。つまりさっきと同じ現象で、**次の行までコメントアウトされてしまっている（printf文がコメントアウトされてしまっている）ので、何も表示されなかったわけです。**

しょうがないのでプログラムを修正しましょう。

```C:a.c
#include <stdio.h>

void func(int x){
    // 与えられた変数を表示するだけの機能.
    printf("%d\n", x);
    return;
}

int main(void){
    // ビット表
    // 「このコメントを削除するとなぜかコンパイルエラーが起きる」という現象が起きる
    int bitmap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

    func(bitmap[0]);
}
```

「能」の後ろに適当に「.」を付けました。これで次の行までコメントアウトされることはなくなります。再度コンパイルして実行してみましょう。

```
$ gcc a.c
$ ./a.exe
1
```

これでOKです！

# 「これでOKです！」じゃない
このままだとダメ文字を意識しながらコーディングをし続けないといけません。
そもそもSJISでコーディングせず、UTF-8でコーディングするようにしましょう。
git-secretsを使って、誤ってgitでawsの鍵情報を公開しないようにする

# git-secrets
awsを使っているとaws-cliやsdkを使い鍵情報が必要になり、鍵の管理がとても大事になる。
誤ってgitで公開しないように対策するためにgit-secretsを導入した。

## インストール
- install
  - 環境: MacOS ( High Sierra )

```
$ brew install git-secrets`
$ curl -O https://raw.githubusercontent.com/awslabs/git-secrets/master/git-secrets`
$ chmod +x ./git-secrets
$ git secrets --register-aws --global
```

- .gitconfigを確認
  - `~/.gitconfig`
  - 許可するAWSの鍵が定義されている(ここに公開したくない鍵情報を定義する)

## 方法1 ( 手動スキャンでチェックする )
- `$ git secrets --scan --no-index`

```
[ERROR] Matched one or more prohibited patterns
```

## 方法2 ( commit時に自動チェックする )
- `$ git secrets --install`

```
✓ Installed commit-msg hook to .git/hooks/commit-msg
✓ Installed pre-commit hook to .git/hooks/pre-commit
✓ Installed prepare-commit-msg hook to .git/hooks/prepare-commit-msg
~/hoge ❯❯❯ ls
test-key
~/hoge ❯❯❯ git add test-key
~/hoge ❯❯❯ git commit -m "test key check"

[ERROR] Matched one or more prohibited patterns
```
【読解】Unsupervised Pixel-Level Domain Adaptation with Generative Adversarial Networks (PixelDA)

# 0. 概要
いわゆるDomain Adaptationの論文。他の論文と異なるのは、今までの論文はDomain AとDomain Bの画像の分布（それとない形やテクスチャ）を似せるところにあったが、これはPixelレベルで似せようとしている。あまりちゃんとした解説がないので、読解していく。

Unsupervised Pixel-Level Domain Adaptation with Generative Adversarial Networks (PixelDA): 
https://arxiv.org/pdf/1612.05424.pdf

論文の趣旨を理解したいので、Related research等は飛ばす。

# 1-2. Introduction
CNNはあらゆるタスクで非常に有用である。一方で、伝統的な方法では教師を必要とする。しかし、実世界のタスクでは教師が足りないことが多い。このため、CGなどのレンダリングに頼ることがあるが、実世界の画像と全く同じにすることは出来ない。この欠点を解決するために、PixelDAを開発した。Domain A(教師ありシミュレーションデータ)とDomain B(実世界データ)が与えられたときに、ドメイン間に関わらない不変的な特徴量を抽出するように学習させる。

<b>ようはDomain A及びDomain Bから共通的な特徴を抽出するということ</b>


# 3. Model
教師ありSource Domain (Domain A)と教師なしTarget Domain (Domain B)が与えられたとき、Source DomainをTarget Domainに変換して識別機を学習させる。

ドメイン間の違いの多くは、オブジェクトの種類、幾何学的な変形ではなくノイズ、解像度、照明、色などであると考えられる。


$X_s$をSource Domainから$N_s$個サンプルされたラベル付きデータとする。
$X_t$をTarget Domainから$N_s$個サンプルされたラベルなしデータとする。
Source Domain $X_s$はGenerator function $G$からノイズや$X_t$によって$X_f$に写像される。
すなわち$G$によって新たなデータセット$X_f$(任意のサイズになる)が生成される。この$X_f$を用いて識別機を学習させると、あたかもTarget Domainと同じ分布として学習させることができる。

多分$f$はFakeのfかな？？

<b> すなわち、Source DomainをまずはTarget Domainに写像する </b>

# 3.1. Learning 
学習モデルにはAdversarialを用いる（ようはGAN）。入力は$X_s$及びノイズ$z$である。これらから$X_f$を生成する。

この学習機はDiscriminator $D$によって効果的に学習させられる。$D$はTarget Domain $X_t$とSource Domain $X_s$から生成された$X_f$を比較し、RealかFakeを判定する。

<b> GANによってSource DomainからTarget Domainぽい画像を作り出す</b>

この$D$はClassifier $T$によって効果的に学習させられる。

最適化は以下のように行われる。
$\alpha L_d(D, G) + \beta L_t (G,T)$
この時、$\alpha$及び$\beta$はパラメータである。$L_d$はドメインの損失を表している。$L_d$は以下のように定義される。
$L_d(D, G)=E_{x_t}[\log(D)] + E_{x_s, z}[\log(1 - D)] $

$L_t$はタスク特有の識別問題の損失を表している$L_t$は以下のように定義される。
$L_t(G, T)=E_{x, y, z}[-y_s \log T(G)] -y_s \log T(X_s) $

ここで、$y_s$はone-hot vectorとする。
また$T$は$G(X_s)$すなわち$X_f$で訓練もするし、$X_s$だけでも訓練をする。前者だけでも問題ないが、両方を合わせることで安定性が増すそうだ。

これをまとめると以下のような図になる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/95636/22d04abe-0d96-e745-ede8-d62039bdb5e7.png)

Pixel Levelなので、解像度を落とさないためにResNetの構成を$D$及び$G$で用いている。

# 3.2. Content-similarity loss
加えて、背景とオブジェクトをより区分けしやすいように、罰則項を追加して以下のように損失関数を設計している。

$\alpha L_d(D, G) + \beta L_t (G,T) + \gamma L_c (G) $

$L_c$はコンテンツの類似性損失（PMSE）である。
ようは、ソースに対して生成したものがあまりにも異なったものにならないようにしている。PMSEは以下のように与えられる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/95636/932a29ff-0fa1-f007-6983-e6972064df17.png)


因みにピクセルレベルでの損失関数となっている。普通の$D$であればSoftmaxによる2値の0, 1判定であるが、この損失関数は画素単位での0, 1判定である。

<b>DiscriminatorとGeneratorはセットで1つの損失関数</b>
<b>GeneratorとClassiferはセットで1つの損失関数</b>
<b>ようはGeneratorはDiscriminatorを騙しつつも、Classiferの精度が高くなるような画像の変換手法を学習しなければならないということ</b>

# 4. Evaluation
![image.png](https://qiita-image-store.s3.amazonaws.com/0/95636/e5a17e6b-8281-b5c2-2dff-8a534a84117e.png)


# 5. 感想
全体の仕組み的には簡単だけれども、各要素が濃い。工夫が凄い。これら工夫がちゃんと精度に結び付いているのが流石Google。しかし、少し複雑にしすぎている感は否めない。あらゆるタスクに適用させるには、調整するパラメータが多いような気がする。
Anaconda環境でPyTorch 〜株価予想〜 #04 予測(リベンジ)編

## はじめに
[株式会社クリエイス](http://creaith.jp/)の[モトキ](https://qiita.com/pickles)です。  
[前回](https://qiita.com/creaith/items/710405db451577ae1580)、pandasでグラフを表示しました。

[Anaconda環境でPyTorch 〜株価予想〜 #01 環境構築編](https://qiita.com/creaith/items/f47c33e78fb97349b4c8)
[Anaconda環境でPyTorch 〜株価予想〜 #02 基礎知識・学習編](https://qiita.com/creaith/items/2d606a7f0effd5d839d5)
[Anaconda環境でPyTorch 〜株価予想〜 #03 予測編](https://qiita.com/creaith/items/710405db451577ae1580)
Anaconda環境でPyTorch 〜株価予想〜 #04 予測(リベンジ)編 (今回)
[Anaconda環境でPyTorch 〜株価予想〜 #05 表示編](https://qiita.com/creaith/items/54c1666682210d8cbce3)


## やったこと
とりあえず**分からなくてもいいから動かそう**ということで新たにソースをお借りしました。
https://github.com/melissa135/mlp_stock
文字コードが中国語のものだったり、スペースタブが混じっているので修正してから始めます。

このソースではCSVから取得しています。しかもpandasで取り込んでおりquandlに変えても同じ様に扱えます。

```csv:sz_train.csv
date,open,high,low,close,volume,close_change,volume_change
"2005-01-04,二",3051.24,3051.24,3016.26,3025.42,435050970,0,0
...
```
### 学習
前回同様に、Appleの株価を拾ってくるようにsample_set.pyを修正します

```python:Sample_set.py
import torch
import torch.utils.data as data
import quandl


class SampleSet(data.Dataset):
    def __init__(self):
        quandl.ApiConfig.api_key = "xxxx" # quandlのAPIKEY
        df = quandl.get("WIKI/AAPL")
        self.df = df
        self.w1 = 1
        self.w2 = 0.1

    def __getitem__(self, index):
        index = index + 5

        array_data = [self.df['Adj. Close'][index - 1] * self.w1,
                      self.df['Adj. Close'][index - 2] * self.w1,
                      self.df['Adj. Close'][index - 3] * self.w1,
                      self.df['Adj. Close'][index - 4] * self.w1,
                      self.df['Adj. Close'][index - 5] * self.w1,
                      self.df['Adj. Volume'][index - 1] * self.w2,
                      self.df['Adj. Volume'][index - 2] * self.w2,
                      self.df['Adj. Volume'][index - 3] * self.w2,
                      self.df['Adj. Volume'][index - 4] * self.w2,
                      self.df['Adj. Volume'][index - 5] * self.w2]

        target = [self.df['Adj. Close'][index]]

        ret_data = torch.Tensor(array_data)
        target = torch.Tensor(target)
        return ret_data, target

    def __len__(self):
        return len(self.df) - 5

```
これで、同じように学習結果が保存できます。
あとは呼び出し元で引数を与えないように修正してやります。

### 実行 
```shell:terminal
% python test_net.py
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/240629/416ff3d3-132c-de17-b9a7-f99508011df9.png)
な…なんだこれは…
やはり「どう学習させるか」「どう予測させたいか」などを明確にして、
ソースコードを直す必要があるようです。
今回はここでギブアップ。

## 次回について
学習と予測それぞれの方針を決定、ソースコードに反映させます。
牛歩ですが、がんばります！

## 別チーム
[別チームでもPyTorchの記事](https://qiita.com/creaith/items/09d140f215748e3ff887)を書いています。
[Docker環境でPyTorch 〜画像解析〜 #04 セクシー女優学習データ作成編](https://qiita.com/creaith/items/09d140f215748e3ff887)

## Creaithメンバー
この記事の著者：[曽宮](https://qiita.com/ryosomiya)、[モトキ](https://qiita.com/pickles)
その他メンバー：[志村](https://qiita.com/naoto1222)、[上田](https://qiita.com/uedashuhei)
シュミレータを立ち上げた時から画面が真っ暗な時

[コードで画面遷移を行う方法](https://qiita.com/Simmon/items/6c3d6bcd6bfffbfd970d)を試していて、
何故かシュミレータをいざ立ち上げようとした際に画面が真っ暗になってしまったので
きっと同じような経験をする方へ。
注) 今回はstoryboard1つに対して1つのファイルで管理している場合
# 「Is Initial View Controller」にチェック入っとるやんけ。
色んな記事を参考にさせてもらったのですが「Is Initial View Controller」にチェックが入ってないのでは？というのが殆どでした。

大抵は解決にいたらず困っている時に
教えていただいたのが、以下の「General」タブのMain Interfaceを一番はじめに起動したいstoryboardに設定するということでした。
<img width="750" alt="スクリーンショット 2018-10-05 17.30.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/254495/1f7ec2fe-2028-b2c1-7a16-ac99f7d407b9.png">

「Is Initial View Controller」にもチェック入っているし、
遷移先のビューの「Is Initial View Controller」にもチェックは入っている。

なんでじゃーーーーーーーーーー！
となっている時に参考になれば良いです。
git branch が less や more っぽい pager で表示されるのをやめる

``Ubuntu 18.04 LTS, git 2.17.1, bash 4.4.19 ``で確認しています。

いつの頃から、手元の環境で `` git branch `` を実行した際に、単にターミナルに出力されるのではなく、pager内で表示されるようになりました。
大量にブランチがあれば便利なんでしょうが、pagerを抜けるために ``q``とタイプする必要があるし、抜けたら抜けたで``git branch``の表示が消えてしまう。
だいぶ耐えていましたが、もう我慢ならないのでggってみました。

啓示をくれるのはいつだって **Stackoverflow**。

> Git branch command behaves like 'less'
https://stackoverflow.com/questions/48341920/git-branch-command-behaves-like-less


git config すればいい模様

```sh
git config --global pager.branch false
```

これで以前のbranch表示が戻ってきました！
それにしてもデフォルトの挙動がなんで変わっちゃったんだろう？

謎ぃ....。
PHPで公開鍵&秘密鍵を使用してSFTP接続する方法

# PHPで公開鍵&秘密鍵を使用してSFTP接続する方法

phpseclib というライブラリを使うこともできますが、
ライブラリを入れるほど複雑なことをしたい訳ではなく、
単純にファイルをアップロードするだけなら、
PHPの標準関数を使用して、以下のように実装できます。

```php
    $conn = ssh2_connect($host, $port);
    $ret = ssh2_auth_pubkey_file($conn, $user, $pubkey, $privkey);
    // $pubkey と $privkey は、ファイルパスを指定する

    $sftp = ssh2_sftp($conn);

    $fp = fopen("ssh2.sftp://". (int)$sftp. $todir. $tofile, 'w+');
    $contents = file_get_contents($file);
    fwrite($fp, $contents);
    fclose($fp);

    ssh2_exec($conn, "exit");
    unset($conn);

```
(エラー処理などは割愛してます)

password認証を使用したサンプルはネット上にありましたが、
鍵認証のサンプルは見つからなかったので、誰かの参考になれば。

# 追記: SFTPコネクションのクローズ処理について

私の環境では、ssh_disconnectを実行するとSegmentation Faultになりました。
私以外にも同じような現象を報告している方がいます。
https://bugs.php.net/bug.php?id=73438

ssh_disconnectを使わない場合、以下のようにすることが多いようです。

```
    ssh2_exec($conn, "exit");
    unset($conn);
```

このようにした場合でも、プログラム終了時までセッションは張られたままですので気を付けましょう。

私はこの問題により、SFTPサーバのコネクション数を使い果たして、
だれもSFTPサーバに接続できなくなるという事態を引き起こしたことは秘密です。
はじめてのdynamic VCL Snippets

目的
dynamic VCL Snippetsを手軽に作成したい

├ create.sh
├ delete.sh
├ vcl(この下にアップロードするvclを保存する。)


```create.sh
SERVICE_ID=$1
VERSION=$2
FILE=$3
VCL_TYPE=$4

content=`cat vcl/${FILE}.vcl`

curl -X POST -s "https://api.fastly.com/service/${SERVICE_ID}/version/${VERSION}/snippet" -H "Fastly-Key:${FASTLY_API_TOKEN}" -H 'Content-Type: application/x-www-form-urlencoded' --data $"name=${FILE}&type=${VCL_TYPE}&dynamic=1&content=${content}"
```
```delete.sh
#!/bin/bash

SERVICE_ID=$1
VERSION=$2
NAME=$3

curl -X DELETE -s "https://api.fastly.com/service/${SERVICE_ID}/version/${VERSION}/snippet/${NAME}" -H "Fastly-Key:${FASTLY_API_TOKEN}"
```

使い方

1.FASTLY_API_TOKENを.bashrcなどに設定

``` .bashrc
export FASTLY_API_TOKEN="xxxxx"
```

2.Fastlyの管理画面からcloneして編集可能なバージョンを作成する

3.vclディレクトリの下にアップしたいvclを保存(vcl/sample.vclを作ったと仮定)

``` vcl/sample.vcl
if ( req.url.path ~ "^(/sample/.*)$") {
    set beresp.ttl = 86400s;
    return(deliver);
}
```

4.upload実行

``` 
./create.sh <YOUR SRVICE ID> <2で作った編集可能なバージョン番号> <3で作ったファイル名> <実行したいサブルーチン>
 ```

この例の場合はこんな感じ

```
./create.sh xxxxx 2 sample fetch
```

vcl/sample.vclはオリジンから持ってきたときにttlを設定したいのでfetchを指定。
この辺りは[この記事](https://qiita.com/AtsushiFukuda/items/db26ce0f75998e7e4385#%E3%82%B5%E3%83%96%E3%83%AB%E3%83%BC%E3%83%81%E3%83%B3)が詳しいです

削除したい場合

```
./delete.sh <YOUR SRVICE ID> <2で作った編集可能なバージョン番号> <3で作ったファイル名>
```

今回の場合は

```
./delete.sh xxxxx 2 sample
```

一度つくればあとはcloneしなくても更新できるので便利そう。
Firebase プッシュ通知 で複数行の表示 （Android, Xamarin, Azure）

Firebaseのプッシュ通知(FCM)で通知領域に複数行表示させるメモ。
通知はAzureから送信している。
Xamarinで開発しているので言語は、C#（関数が大文字で始まってるので、Javaなら小文字に変換が必要）
Android8以上では、NotificationChannelが必要。

```c#
SendNotification(title, body);

void SendNotification(string title, string body)
{
    const string CHANNEL_ID = "MY_CHANNEL_ID";
    CreateNotificationChannel(CHANNEL_ID);

    Intent intent = new Intent(this, typeof(MainActivity));
    const int pendingId = 0;
    PendingIntent pendingIntent = PendingIntent.GetActivity(this, pendingId, intent, PendingIntentFlags.OneShot);

    if (Android.OS.Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.O)
        title = new Models.Settings().NotifTitle;

// 複数行表示するには、BigTextStyleを作成する
    NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle()
        .SetBigContentTitle(title)
        .BigText(body);

// 作成したBigTextStyleをSetStyle()でセットする
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .SetContentIntent(pendingIntent)
        .SetSmallIcon(Resource.Drawable.ic_stat_ic_notification)
        //.SetContentTitle(title)
        //.SetContentText(body)
        .SetStyle(bigTextStyle)
        .SetDefaults(-1)//NotificationDefaults.Sound | NotificationDefaults.Vibrate | NotificationDefaults.Lights);
        .SetAutoCancel(true);


    NotificationManagerCompat manager = NotificationManagerCompat.From(this);
    const int notifId = 0;
    manager.Notify(notifId, builder.Build());
    //StartForeground(id, builder.Build());
}

void CreateNotificationChannel(string channelId)
{
    if (Android.OS.Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.O)
    {
        // Notification channels are new in API 26 (and not a part of the
        // support library). There is no need to create a notification
        // channel on older versions of Android.
        return;
    }

    var set = new Models.Settings();
    var channel = new NotificationChannel(channelId, set.ChannelName, NotificationImportance.Default)
    {
        Description = set.ChannelDescription
    };
    // 通知チャンネルの設定のデフォルト値。設定必須ではなく、ユーザーが変更可能。
    //channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
    channel.EnableVibration(true);
    channel.EnableLights(true);
    //channel.SetLightColor(argb);
    //channel.SetSound(uri, audioAttributes);
    channel.SetShowBadge(false);

    var notificationManager = (NotificationManager)GetSystemService(NotificationService);
    notificationManager.CreateNotificationChannel(channel);
}

```
macOSのターミナル(bash)でGitを使うためにブランチ表示やTABキー補完の設定をした

Androidアプリ開発環境を整えるべく、まずはバージョン管理「[Git](https://backlog.com/ja/git-tutorial/ "ギット")」を準備した。

* 通常はGUIで使える「[SourceTree](https://ja.atlassian.com/software/sourcetree) "ソースツリー"」を使うだろうけど、ターミナル(bashとも呼ばれる)からコマンドを打ちたいときもある。
* しかし、そのままのターミナルでは結構不便
 * Windows版のGitみたいにTABキーで補完しない。
 * 現在のブランチ名が表示されないのでわかりづらい

など。

#Linuxのように.bashrcにPATHを通す
PATHとは、コマンドを実行するときに、検索するディレクトリリストのようなもの。

ターミナル(bash)を起動して、viで設定ファイルを作成する。
「~ $ 」とか出ているプロンプトの後に、以下に挙げるコマンドを打つ。

```bash
~ $ vi ~/.bash_profile
```

viの画面になる。iキーでInsertモードにして以下の3行を追加する。空白も含めて正確に。
※ 「~/.bashrcが存在し、通常ファイル (regular file)であれば実行」を意味する。

```vim:~/.bash_profile
if [ -f ~/.bashrc ]; then
  . ~/.bashrc
fi

```
ESCキーでCommandモードにしてから「:wq」と入力してからEnterキー↩️で、上書き保存してviを終了する。（取り消すなら「:q!」で編集を保存しないでviを終了。）

#Homebrewのインストール
ソフトウェア導入をやりやすくするために「Homebrew」をインストールした。

* [macOS用パッケージマネージャ Homebrew](https://brew.sh/index_ja.html) の通りにインストール

```bash
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

###コマンド補完ツール(bash-completion)をインストール
brewコマンド(Homebrew)を使ってインストールする。

```bash
$ brew install bash-completion
```
インストールしたら、.bashrcを編集する。

```bash
~ $ vi ~/.bashrc
```

以下を追記して、上書き保存する。(ESCキー後、:wq↩️）

```vim:~/.bashrc
# for bash_completion
if [ -f $(brew --prefix)/etc/bash_completion ]; then
  source $(brew --prefix)/etc/bash_completion
fi
```

続いて、gitもHomebrewからインストール。

```bash
$ brew install git
```

これで、TABキーのブランチ補完ができるようになります。

###コマンドプロンプト上に現在のブランチを表示させる

* [Macでgitを利用した開発する際にやっておきたい準備](https://qiita.com/NorsteinBekkler/items/a0622ee6a39d08d61b72)
の「[.bashrcのカスタマイズ](https://qiita.com/NorsteinBekkler/items/a0622ee6a39d08d61b72#bashrcのカスタマイズ)」の通りに記述すると、良い感じに色分け表示されます。

※追記
ユーザー名とか長くなっちゃうので省略したいときには以下のように

```vim:~/.bashrc
export PS1='\[\033[37m\][\[\033[32m\]\W\[\033[37m\]]\[\033[31m\]$(__git_ps1)\[\033[00m\]\$ '
```