OmniAICreator/Qiita-1.07M huggingface dataset:
ブロックチェーンシミュレータ（１）

 これから**ブロックチェーンシミュレータ**に関しての投稿をしていこうと思います。
私が大学で研究しているテーマがブロックチェーン技術に関してです。現在、ブロックチェーン技術に関しての知識をどんどんインプットしてるのですが、やはりアウトプットをしないと理解が進まないので、趣味でやっていた**Unity**を使って、アウトプットしていこうと思い、このブロックチェーンシミュレータを作りました。

ここにブロックチェーンシミュレータの作り方を記すので、興味がある方はぜひ参考にしてみてください。

少し長くなると思うので、投稿を二つに分けたいと思います。
書き方とかまだあまり分かってないのですが、頑張ります！
修正があれば、その都度更新していく予定です。

二つ目→[ブロックチェーンシミュレータ（２）](https://qiita.com/MichihiroTsukano/items/be708773a956d9e7ebb1)

ブロックチェーン技術に関してより詳しい記事 → [ブロックチェーン技術及び関連技術](https://qiita.com/MichihiroTsukano/items/1485f05a45a37d7ffe08)






# 目的
そもそもブロックチェーンってなんだ？ということで、簡単にブロックチェーンとは何かを技術的な面から、理解するためのツールを作ることを目指しています。





# ブロックチェーン技術に関しての基礎知識
ブロックチェーンシミュレータの作り方の前にまずはブロックチェーン技術の基礎的なことから書きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/309633/e48f5015-ec3d-bfa9-e93b-7bbe64c18fa6.png)

ブロックチェーンはその名の通り、**ブロック同士が繋がって**できています。ブロックには、やりとりや取引の情報が記録されている**トランザクション**と**ヘッダ**というものが存在しています。




![image.png](https://qiita-image-store.s3.amazonaws.com/0/309633/349b6a2c-4bc7-1067-cd7e-03dca92b88cd.png)
ヘッダの中にある三つの値を関数に入れ、**ある一定の値より小さな値を求めることができれば、ブロックを生成することができます。**ある一定の値を調整することによって、生成の難易度が変わり、生成時間が変わってくるというわけです。例えば、**ビットコイン**では**PoW(proof of works)**を採用しており、**約10分**でブロックを生成しています。また、**イーサリアム**では**PoS(proof of stake)**を採用しており、**約12秒**でブロックを生成しています。他にもありますが、今回はここまで。（笑）
詳細に関しては別のサイトや書籍などで調べてみてください。。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/309633/065bfe24-595a-1271-0e0e-498d2cc82f70.png)

ブロックチェーンは**分散型システム**を採用しています。集中型システムでは通常の銀行ネットワークように、**管理者が一人だけ**でありますが、分散型システムでは、**参加者全員が管理者**となっています。




>[参考文献] ビットコインとブロックチェーン:暗号通貨を支える技術(コンサイス版)-アンドレア・M・アントノプス-NTT出版(2018)







# ブロックチェーンシミュレータのアルゴリズム
さてさて、ブロックチェーンシミュレータではどのような動きをするのかについて話します。
さきほど説明したヘッダの三つの値をこのブロックチェーンシミュレータでは以下のように定義します。
>**・トランザクションの圧縮データ　→　MakeTimeValue
・最新ブロックのヘッダの圧縮データ　→　BaseValue
・ナンス　→　AnswerValue**


ブロック間の繋がりに関しては①のような式で表します。

>**①(MakeTimeValue + BaseValue + AnswerValue) % ModValue = BaseValue'**

BaseValue'が次のブロックのBaseValueとなりブロック間の繋がりを実現することができます。


そして、ブロックを生成するためにナンス(ブロックチェーンシミュレータではAnswerValue)を計算するには②のような式で表します。
>**②(BaseValue + AnswerValue) % ModValue = 求める値**(ブロックチェーンのある一定の値のようなもの)

ブロックチェーンシミュレータはある一定の値より小さな値を求めるのではなく、**求める値と同じ値になるようにAnswerValueを計算していきます。**
※ブロックチェーンシミュレータでは最初のブロックは自動生成するようにしてあるので、最初のBaseValueとModValue、求める値は**乱数**としています。





# 終わりに
目的とブロックチェーン技術に関しての基礎知識、ブロックチェーンシミュレータのアルゴリズムを記しましたがどうだったでしょうか。

次の投稿から、実際にUnityを使ってブロックチェーンシミュレータの制作の内容を記していこうと思います。
ここまで見ていただき、ありがとうございました。



二つ目→[ブロックチェーンシミュレータ（２）](https://qiita.com/MichihiroTsukano/items/be708773a956d9e7ebb1)

ブロックチェーン技術に関してより詳しい記事 → [ブロックチェーン技術及び関連技術](https://qiita.com/MichihiroTsukano/items/1485f05a45a37d7ffe08)
まずいな～。プログラムを打つ環境設定が必要らしい。

PaizaラーニングでPython入門を行いながら。

天気を自動で読み込むプログラムをコピペしてみようとやってみた。

よくわからないまま、Paiza.IoでJupyter Notebookというものを立ち上げることまではできたのですが。

コピペする。

う～～ん。

そうか。

動かし方がよくわかってない。

ホームページ作成やブログのカスタマイズなどはクラウド上で環境構築できている。

プログラムを動かすには、プログラムを打つ環境を作らないといけないみたいだな。

う～～～ん、これはこれは。

プログラムを学ぶのと同時にPCについても知らないと動かせないのね。

なるほどね～～。

プログラムを打ったらすぐに使えるものだと考えていた。

アホだな。

ソフトという形で、ど素人でもホームページ作成できるようにシステム開発してくれていたんですね。

先は長いな～～＞＜

でも、楽しいです。

自分でやってみると、便利にできるようにしてくれてるって実感できる。

このサイトだってそうです。

困ったことは書いておこう。
Blueprintからモックサーバーを爆速で作る

npmはすでに入れているものとします。


# BlueprintでAPI設計書を作る

```md:api.md
FORMAT: 1A
HOST: http://example.com

# API

API仕様書

# Group USERS

## USERS [/api/users]

### 全ユーザ情報を取得する [GET]

+ Response 200 (application/json)

        [
            {
                "id": 1,
                "name": "user name",
                "avatar": "https://...",
                "description": "Hi, I'm teaching Ruby at Proconbu."
            },
            {
                "id": 2,
                "name": "user name",
                "avatar": "https://...",
                "description": "Hi, I'm teaching network at Proconbu."
            }
        ]

### ユーザーを登録する [POST]

+ Request (application/json)

    + Attributes

        + id (required)
        + name (required)
        + avator (required)
        + description (required)

    + Body

        {
            "id": 1,
            "name": "user name",
            "avator": "http://~",
            "description": "Hi, I'm teaching Golang at Proconbu."
        }

+ Response 200 (application/json)

        {
            "id": 1,
            "name": "user name",
            "avator": "http://~",
            "description": "Hi, I'm teaching Golang at Proconbu."
        }

## USER [/api/users/{userId}]

+ Parameters

    + userId(number) - ユーザID

### 特定のユーザ情報を取得する [GET]

+ Response 200 (application/json)

        {
            "id": 1,
            "name": "user name",
            "avator": "http://~",
            "description": "Hi, I'm teaching Golang at Proconbu."
        }
```

# モックサーバー用ライブラリをインストール
**drakov**というnpmのパッケージが存在します。
これはBlueprintのファイルからモックサーバーを立ち上げることができます。

```bash
$ npm install -g drakov
```

# モックサーバーを立てる
*※デフォルトポートは3000番*

```bash
$ drakov -f api.md --server
```
#### Vagrantとかなら

```bash
$ drakov -f api.md -p 8080 --public
```

# モックサーバーにアクセス
いい感じに帰ってきます。

```bash
$ curl http://localhost:3000/api/users

[
    {
        "id": 1,
        "name": "bookuser",
        "avatar": "https://...",
        "description": "Hi, I'm teaching network at Kobedenshi."
    },
    {
        "id": 2,
        "name": "bookuser",
        "avatar": "https://...",
        "description": "Hi, I'm teaching network at Kobedenshi."
    }
]
```

# まとめ
API設計書を書くついでにモックサーバーまでできてしまう一石二鳥な方法です。
後はAPIを呼び出すコードでは、ドメインの部分を変数などで指定してやればすぐに書き換えられますね。

では良い開発ライフを！！


# 補足

drakovのPOSTリクエストは、まずBodyの内容をサンプルデータと完全一致で検査します。
そのあと、Attributesの内容でスキーマ的に判定します。
省略することはできますので、それぞれのモックに求められる精度によってご自由に組み替えてください。

[Blueprint公式](https://apiblueprint.org/documentation/)
全くのゼロから始めるボードゲームのプログラミングと機械学習 [2日目]

#前回の振り返り
[全くのゼロから始めるボードゲームのプログラミングと機械学習 \[1日目\] \- Qiita](https://qiita.com/Coshian23/items/11c7efeafe67077b6830)

- 目下の目標は「Pythonでカルカソンヌを再現する」
- 参考とする書籍の選定
- Python勉強環境の準備

7年前に買った参考書籍をやっと使い始めました。

#参考書籍の紹介
[Pythonゲームプログラミング入門 \| Will McGugan, 杉田臣輔, 郷古泰昭 \|本 \| 通販 \| Amazon](https://www.amazon.co.jp/Python%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-Will-McGugan/dp/4048704397/ref=sr_1_14?s=books&ie=UTF8&qid=1540967866&sr=1-14&refinements=p_n_feature_seven_browse-bin%3A3232405051)
前回紹介した通りPythonでのゲーム制作については上記の書籍を参考に学んでまいります。目次を紹介しているサイトがありましたので下記引用させていただきます。

>・はじめに
・序文
・第1章 Python 入門
・第2章 Python 探検
・第3章 Pygame 入門
・第4章 ビジュアルの生成
・第5章 物体の動きの作成
・第6章 ユーザー入力を受け付ける
・第7章 人工知能を導入する
・第8章 ３次元に移行する
・第9章 ３次元を探検する
・第10章 効果音の作成
・第11章 ライト、カメラ、アクション！
・第12章 OpenGL のシーンの設定
・付録A Gmae Objects リファレンス
・付録B ゲームのパッケージ化

引用元：[Pygameの日本語の解説本「Pythonゲームプログラミング入門」 \- 強火で進め](http://d.hatena.ne.jp/nakamura001/20110628/1309281359)

まさに現在の自分が望んでいる内容がそろっています。

- 第1章 Python 入門
- 第3章 Pygame 入門
- 第7章 人工知能を導入する

この辺が本プロジェクトにとっては非常にホットなテーマとなりそうです。8章以降はボードゲームをプログラミングしたいという自分の目標からするとやや逸脱した内容になりそうですが、せっかくなので合わせて学んでいきたいと思います。

#Python勉強開始

ひとまずPython実行環境も整えましたので、丁寧に1から学んでいきたいと思います。非常にあたりまえな話も出てきてしまうかもしれませんがタイトルの通りゼロスタートですので泥臭くいこうと思います。

因みに書籍ではPython2.4が使われています。
現行のPythonはPython3.7とpython2.7のようですね。ひとまず大は小を兼ねる(？)ということでPython3.7を使ってみることにいたしました。

```Python3.7
>>> print "hello world!"
```
なんとこれでエラーが発生。まさかHello world!で躓くとは……
調べてみたところ3系からprintは関数に変更されていたのですね。
[Python2からPython3\.0での変更点 \- Qiita](https://qiita.com/CS_Toku/items/353fd4b0fd9ed17dc152)

```Python2.7
>>> print "hello world!"
>>> hello world!
```
2系では上手くいきました。知ってる人からすると初歩的で当たり前の話なのだろうけれど、Pythonを使ったことがない自分からすると勉強になりました。参考書にあわせて2系を使っていこうと思います。

そのほか

- 数値型や変数について
- リスト、タプルについて
- インデントの大切さ

などを学びましたがこの辺はjavaの経験からある程度なじみがありますし、さすがにネット上にいくらでも優れた情報がありますので本記事では割愛させていただきます。

#今後の予定
1. ボードゲームをプログラミング
    2. Pythonの基礎勉強　👈
    3. Pygameの基礎勉強
2. ボードゲームのAI作成
3. 機械学習によるAI強化

Pygameの章に入るまではまだまだPythonの基礎勉強が続きそうです。

#今回の振り返り
- やったこと
    - 参考書の内容確認
    - Pythonでコマンド実行
- わかったこと
    - Pythonの2系と3系は大きく違う
    - Pythonの変数や型などについて
    - Pythonはインデックスが重要
- つぎにやること
    - Pythonの関数について勉強
    - モジュール作成
    - 勉強の計画を立てる
fastlane 使い方

# fastlane actions
`$ fastlane actions` は アクションの一覧が見れる

# fastlane action hoge
`$ fastlane action hoge` で hogeアクションの詳細が見れる

# fastlane run hoge
`$ fastlane run hoge` で hogeアクションを実行できる

# アクションの引数について
アクションには `key:value`の形で引数を渡せる

**例**
`$ fastlane run increment_build_number build_number:10000`
JUCEを使ったVST製作におけるファクトリープリセットの作り方

# 概要
Juceライブラリを使ってVSTを開発したい．
一般のプログラムのようにファクトリープリセットを搭載したい．
VSTライブラリの側の関数をオーバーライドする．

# 結果
Studio One 2にて確認．ファクトリープリセットをこのようにして実装できた．
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/125382/e749a845-9e13-2dc6-898d-192b01715804.png)

# やり方
VSTライブラリで，ファクトリープリセット用の関数があるのでオーバーライドして呼ぶ．
Juceを使う場合だと，`AudioProcessor`クラスが継承している．なのでプラグインの本体で呼び出すのが自然だと思う．

プリセットに関しては，JuceやVSTライブラリでも`〇〇program`といった呼び名で管理しているもよう．このキーワードで検索すると周辺情報も得られるだろう．

実際の記述．Juceのサンプルプラグインの例に従う場合には以下のように記述．
[https://github.com/WeAreROLI/JUCE/tree/master/examples/Plugins](https://github.com/WeAreROLI/JUCE/tree/master/examples/Plugins)

```C++:JuceDemoPluginAudioProcessor.h
class JuceDemoPluginAudioProcessor : public AudioProcessor
{
//変更点以外の関数記述は省略しています．

public:
   //プリセットの数を定義
   int getNumPrograms () override
   {
      return NUM_OF_PRESETS;
   }
   //現在のプリセットインデクス
   int getCurrentProgram () override
   {
      return currentProgIndex;
   }
   //プリセットのパラメータをハードコーディングする
   void setCurrentProgram (int index) override
   {
      switch(index) 
      {
      case 0:
         param1 = x;
         param2 = y;
         param3 = z;
         break;
      case 1:
         param1 = xx;
         param2 = yy;
         param3 = zz;
         break;
      case default:
         break;
      }
      //現在のプリセットインデクスはクラス内に記憶する
      currentProgIndex = index;
   }
   //プリセットの名前を記述していく
   const String getProgramName (int index) override
   {
      switch(index) 
      {
      case 0:
         return(PRESEST_NAME_00);
         break;
      case 1:
         return(PRESEST_NAME_01);
         break;
      case default:
         return("");
         break;
      }
   }

private:
   //現在のプリセットを変数として保持する
   int currentProgIndex = 0;
}
```

# 参考
[プリセットのあるエフェクターを作成する | C++でVST作り](http://vstcpp.wpblog.jp/?page_id=483)
webサービスをIPv6に対応させて見たけどハマったポイント

KusanagiでWordpressでブログをやりつつ、Cakephp2.9系/Nginx/CentOS7系/PHP7系/kusanagi/さくらのVPSの環境でwebサービスを運営しています。
今回、IPv6に対応してみました。

###対応手順
https://help.sakura.ad.jp/hc/ja/articles/115000065981-IPv6%E6%9C%89%E5%8A%B9%E5%8C%96%E6%89%8B%E9%A0%86-CentOS7-
https://qiita.com/moutend/items/a14afc83f256af8543aa
このあたりを見ればやれます。
あとはネームサーバーにAAAAレコードを登録するくらいです。
cakephpの環境構築に比べればだいぶ簡単です。


###ハマった所
Wordpressをアクセスするためのnginxのコンフィグファイル(/etc/nginx/conf.d/にあるやつ)のうち、Wordpress管理画面のアクセスフィルタリングがIPv6に非対応だった。

allow 0.0.0.0/0;
が入っている場合は
allow ::/0;
を入力してください。
入っていない時はアクセスするIPv6アドレスを書いてください。
基本的には、アクセスするIPv6アドレス決まっているなら後者の方が良いかと...

###アクセスへの影響は？
前週のGoogleanalyticsのアクセス数と見比べていますが、今のところはなさそうです。（前週よりアクセス総計は増えているため）
個人的にはIPv6とIPv4のアクセス比率がどんなもんなのかも気になりますが。。。

###なんで対応したの？
いわゆるNTTがやっているフレッツ光や光コラボレーションモデル（ビッグローブひかりとかドコモ光とかソフトバンク光）ではIPv4という道路とIPv6という道路の２つが用意されています。しかし、NTT側の事情(http://www.denet.ad.jp/technology/2018/03/ntt-flets.html)
により、IPv4の道路は混雑しており、IPv6の道路は空いている状況です。「IPoE対応のルーターを入れて、対応するプロバイダIPoEオプションについての契約をすれば」、IPv4のみの対応でも快適に見ることができますが、敷居が高いため、「プロバイダや回線がIPv6に対応さえしてれば」快適に見ることが出来るようにサーバの設定を変えたつもりです。
意味あれば良いんですが...
最近はスマートフォンもIPv6経由でのアクセスができるようになってきているようです。
UnityにAdMob実装

####<font color="DeepSkyBlue">[Google AdMobガイド](https://developers.google.com/admob/unity/start)から、プラグインダウンロード</font>

![1.png](https://qiita-image-store.s3.amazonaws.com/0/159490/2bf3ea46-db17-9f1a-0002-4bcc7dd0934b.png)

**[DOWNLOAD THE PLUGIN]ボタンクリック**

![2.png](https://qiita-image-store.s3.amazonaws.com/0/159490/250a002f-29d8-e68c-6e72-3d45c22c0e9f.png)

**unitypackageをクリック**

####<font color="DeepSkyBlue">Mobile Ads SDKを入れる</font>

![3.png](https://qiita-image-store.s3.amazonaws.com/0/159490/f57331c6-efca-9155-4997-95475dc89938.png)

**Resolve**で成功すると、成功のメッセージボックスが出るでしょう！。

####<font color="DeepSkyBlue">ソースコードとサンプル</font>

左の各ボタンから入ると、ソースコードが見られます。

![10.png](https://qiita-image-store.s3.amazonaws.com/0/159490/c2af1ba9-803a-bd90-8adf-871e7fb64416.png)

一番下に**HellWorld example**、すでに用意したサンプルもございます。それと**AdMob UI**から広告の作成もできます。

![5.png](https://qiita-image-store.s3.amazonaws.com/0/159490/d212a46f-786a-9327-c95b-11695d22caef.png)

####<font color="DeepSkyBlue">広告アイテム作成</font>

アイテム作成するには、まず[アカウント作成](https://apps.admob.com/)がひつようです。

[アカウント作成](https://apps.admob.com/)ができましたら、新しい**アプリ**を作ります。
アプリが作成出来たら、次の画面が出るでしょう！。

![7.png](https://qiita-image-store.s3.amazonaws.com/0/159490/45dc7cc6-7493-c944-ab4a-1cac26a6bae9.png)

広告ユニットボタンから入り、あたらしいアイテムが作れます。

![8.png](https://qiita-image-store.s3.amazonaws.com/0/159490/e8293e45-b78e-18c3-082c-5f25fcc5b0c8.png)


###<font color="Coral">参考資料</font>

[Google AdMobガイド](https://developers.google.com/admob/unity/start)
[AdMob利用契約](https://support.google.com/admob/answer/6128543?hl=ja)
InterSystems IRIS NLPをVB.NETから使う方法のまとめ(1)

InterSystems IRISの目玉機能であるNatural Language Processing(NLP)は、
・「その文章がいかなる意味のつながりを持っているか」を数値化する
・「コンテクスト」（その文章が表現しようとしている知識領域のマップ）と「エンティティ」（コンテクストを構成する要素としてのまとまった単語）を出力する
という機能が特徴です。この能力を知るためには、Webブラウザ上からGUIで動作できる「Analyze」機能がありますが、プログラムと連動して動作させるためにはObjectScriptで記述する必要があります。接続方法をInterSystems掛地様に教えていただいた（ありがとうございます）ので、まとめます。まず、GUI操作でのNLP利用までの流れを紹介します。この土台を用いて、プログラミングを行います。

・InterSystems IRISの起動
右下のアイコンから[IR]->[Management Portal]を起動
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262065/693549ad-e3b2-d81e-1721-70c65a52d0d4.png)

・Analyticsから、解析するネームスペースを選択する（ここではTESTSAMPLESにデータを格納している）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262065/b5042aa4-09da-4c1b-f27a-7578a7e7c092.png)

・NLPで読み出せる基本的なデータセットを作成するため、[Text Analytics]→[ドメイン・アーキテクト]をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262065/9ad0df30-0196-6987-472b-2eb8cab944e0.png)

・新規作成をクリックする。ドメイン名を任意でつける（ここではAnalyzeとした）と、クラスとして、User.Analyzeというクラス名が自動的に記述される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262065/e550df34-97bc-e86d-7aad-e62478a55b61.png)

・スキーマ（ここでは、NLPの元データを入力した場所。"User"という名前の直下にクラスを作成してデータを入れた場合のみ、"SQLUser"という名前になることに注意）とテーブル名"MercForNLP"を入力する。最も簡単に行う場合は、IDフィールドにID、グループフィールドにもID、データフィールドにNLPにかけたいデータフィールド（ここではContentFull）を入れると始めやすい。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262065/31235253-716c-bc9c-fb46-4855c918379a.png)

・[保存][コンパイル][構築]を準備実行すると、NLP用データドメインの作成が始まる。（結構時間がかかります）その後、[Domain Explorer]を押して、分析結果を見る環境に入る。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262065/3bb281b9-4af2-7b24-cb75-58381a848e77.png)

・既にドメイン構築ができている場合には、[Text Analytics]->[Domain Explorer]を選択してもよい。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262065/6121af13-1133-d4aa-a81d-c5e65e50e31b.png)
[Domain Explorer]では、左に解析されたエンティティとその頻度、真ん中に類似エンティティ、右側に関連（コンセプト）が表示される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262065/273aff20-7af4-eb2a-261f-d74bf8011c75.png)
git コマンド(自分用メモ)

#リポジトリを初期化する(リポジトリが壊れた時などに一度git管理を外してあげて、再度git管理にする時など)
```
git init
```
#.gitを管理から消す
```
rm -rf .git
```
#ステージングエリアにまとめて仮登録する

```
git add .
```
#バージョン管理されていて、変更があったすべてのファイルがaddされる(それ以外のバージョン管理されていないファイルや、新しく追加されたファイルは、addされない)
```
git add -u (git add --update)
```
#変更されたファイル、削除されたファイル、新しく作られたファイル、すべてがaddされる
```
git add -A (git add --all)
```

#仮登録とコミットを同時に行う(コミットが実行される前にステージングされていない追跡ファイル(インデックスにあるもの)が対称)※追跡ファイルの作業ディレクトリからの削除も含む
```
git commit -a
```
※追跡されていないものは、対象にならない

#コミットメッセージを同時に指定する
```
git commit -m "コミットメッセージ"
```
**(git addでステージングに追加した後に間違いなどに気づいて作成済みのファイルを更新した時などにまたファイル(Untracked files)をaddするのは手間なのでその際に使う)**

```
git commit -a -m "commit message"
```

#リモートリポジトリの名前に紐づいたurlを確認したい時
```
git remote -v
```
※複数のリポジトリを設定している時は、複数表示される

#originがない時にリモートリポジトリを追加したい時(git cloneをした時は、自動で追加される)

```
git remote add origin リポジトリ名
//ローカルパスでなく、リモートサーバーの時の設定
git remote add origin ssh://sshでログインする時のユーザー名@xxx-xxx-xxxx.vs.sakura.ne.jp/var/www/html/xxxxx.xyz/xxx-xxxxxxxxxxxx

```

#リモートリポジトリが不要になったや間違って設定した時に消す
```
git remote remove origin
```
#リモートリポジトリの変更を取り込みたい時(マージされる)
```
git pull
```
ssh & viしてのリリースを、git管理に移行して、デプロイフローを整備する

# ssh & vi してのリリースとは

* ソースコードは、EC2サーバーの特定の場所に、唯一存在している
* ソースコードは、EC2サーバーにsshして、viすることでリリースしている

を指しています。これをどうにかして、

* github管理にしたい
* githubにあるソースコードをデプロイできるようにしたい

以下、EC2インスタンスの `/var/www/cgi-bin/` 以下にソースコードを散らかしてあると仮定して書きます。

# サーバーに設置してあるソースコードを手元に持ってくる

EC2インスタンス内の `/var/www/cgi-bin` をまるっと手元にscpしてきます。権限、ログファイルなどなどややこしいことは一旦考えません。

```bash
$ scp -i ~/.ssh/hoge.pem -r ec2-user@ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com:/var/www/cgi-bin ./
```

# githubでプライベートリポジトリをひとつ作成する

githubで課金しましょう。プライベートリポジトリを作れるようになります。または、bitbucket, gitlabなど他のサービスを使っても構わないです。とにかくプライベートリポジトリです。

# github管理する

EC2サーバーからscpしてきたときに、実行権限が消失してるかもしれないので、適宜付与してからcommitしてください。

```bash
$ git clone git@github.com:hoge-company/hoge-repos.git
$ mv cgi-bin/* hoge-repos/
$ cd hoge-repos
$ git add .
$ git commit -m "initial commit"
$ git push
```

# デプロイする (初回)

いま置いてある cgi-bin をどけます。

```bash
$ ssh -i ~/.ssh/hoge.pem ec2-user@ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com
$ cd /var/www/
$ mv cgi-bin cgi-bin.bk
$ exit
```

hgoe-reposをscpすることでデプロイ

```bash
$ scp -i ~/.ssh/hoge.pem -r hoge-repos ec2-user@ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com:/var/www/cgi-bin 
```

ひととおり動作確認して、大丈夫そうだったら、cgi-bin.bk は削除してしまいましょう。

```bash
$ rm -rf cgi-bin.bk
```

# デプロイする (2回目以降

```bash
$ ssh -i ~/.ssh/hoge.pem ec2-user@ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com 'rm -rf /var/www/cgi-bin'
$ scp -i ~/.ssh/hoge.pem -r hoge-repos ec2-user@ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com:/var/www/cgi-bin 
```

# この先は

以下のような方向性に発展させるのがよいでしょう。

* EC2でデプロイサーバーを構える & Capistranoを使う
* ElasticBeanstalkにする & CircleCIでデプロイする
* Herokuにする & CircleCIでデプロイする
* Dockerでクソがんばる

インフラとCI/CDに知見のあるメンバーが不在なら、Heroku & CircleCIが一番楽できるはず。
emacsでjs2-modeでインデントの設定をしたい

# emacsのjs2-modeのデフォルトのインデントがいけてない

## init.elにこうかいてやればいい

```elisp
(add-hook 'js2-mode-hook
          (lambda ()
             (setq my-js-mode-indent-num 2)
             (setq js2-basic-offset my-js-mode-indent-num)
             (setq js-switch-indent-offset my-js-mode-indent-num)
            ))
```

## 参考

https://cortyuming.hateblo.jp/entry/2015/11/07/133529
PHPでOGPを取得


OGPに括るとライブラリがあるようですのでそちらを使った方が良いかもしれません。

[おてがるにOGPのチェッカーを作る - Qiita](https://qiita.com/tadsan/items/25ce0e940a481c0fb41d)


よく使うのでメモ
curl例

```php
$title = '';

$ch = curl_init($url);// urlは対象のページ
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);// exec時に出力させない
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);// リダイレクト許可
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);// 最大リダイレクト数
$html = curl_exec($ch);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// ここでhtmlのfalseチェックや空チェックやバイナリチェックやステータスコードチェック
// 空が来るとsimplexml_import_domでInvalid Nodetype to importのエラー

$dom_document = new \DOMDocument();
$from_encoding = mb_detect_encoding($html, ['ASCII', 'ISO-2022-JP', 'UTF-8', 'EUC-JP', 'SJIS'], true);
if ( ! $from_encoding)
{
    $from_encoding = 'SJIS';
}
@$dom_document->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', $from_encoding));
$xml_object = simplexml_import_dom($dom_document);

$og_title_xpath = $xml_object->xpath('//meta[@property="og:title"]/@content');
$title_xpath = $xml_object->xpath('//title');

if ( ! empty($og_title_xpath))
{
    $title = (string)$og_title_xpath[0];
}

if ($title === '')
{
    $title = (string)$title_xpath[0];
}
```


[PHPでスクレイピング](https://qiita.com/horikeso/items/dd8bd2995e880ca7cb8a)
[PHPでの無難なエンコーディング検出方法](https://qiita.com/horikeso/items/ff1f78ec555eeb1df65f)
（初）第七弾　ABAPー訓練「帳票」

:writing_hand_tone1:[第六弾](https://qiita.com/luyu1567/items/82044e7cfa23f08cf7e3)
:writing_hand_tone1:[SAP 訓練目次](https://qiita.com/items/dd1fdf83a42f90a78c6e)

[Smartforms Tutorials](http://saptechnical.com/Tutorials/Smartforms/SFMain.htm)
#１．SmartForms
##１．１Tr-Cd：SMARTFORMS
##１．２実装順序
- スタイル〔書式設定〕⇒フォーム〔スタイル依頼〕⇒FORMID生成
- レポート（Tr-Cd：SE38）

#２．業務ニーズ
- 選択画面には学生番号を入力条件としてする
- 学生毎に試験項目のポイントをリストする

#３．実装
```ABAP

* 制御構造
  DATA:
    LW_CONTROL_PARAMETERS     TYPE SSFCTRLOP.
* ①仮にフォーム〔ZSDFF0001〕のFORMID←汎用モジュール名〔/IBCDWB/SF00000001〕
* ②SmartformIDの取得
  CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
    EXPORTING
      FORMNAME           = I_FORMNME   "フォーム名
    IMPORTING
      FM_NAME            = O_NAME      "SmartformID
    EXCEPTIONS
      NO_FORM            = 1
      NO_FUNCTION_MODULE = 2
      OTHERS             = 3.

* ③汎用モジュール名〔/IBCDWB/SF00000001〕をコールする
  CALL FUNCTION '/IBCDWB/SF00000001'
    EXPORTING
      CONTROL_PARAMETERS = I_CONTROL_PARAMETERS
      OUTPUT_OPTONS      = I_OUTPUT_OPTONS
      USER_SETTINGS      = CNS_FLG_OFF
    TABLES
      TD_DATA            = I_TBL
    EXCEPTIONS
      FORMATING_ERROR    = 1
      INTERNAL_ERROR     = 2
      SEND_ERROR         = 3
      USER_CANCELED      = 4
      OTHERS             = 5.
  IF SY-SUBRC <>0
  AND SY-SUBRC <> 4.
* 該当処理
  ENDIF.
```

#３．サンプル

```ABAP
```
[Smartforms Tutorials](http://saptechnical.com/Tutorials/Smartforms/SFMain.htm)

:writing_hand_tone1:[第八弾](https://qiita.com/luyu1567/items/81e8ed4545ca0a61cdcf)
:writing_hand_tone1:[SAP 訓練目次](https://qiita.com/items/dd1fdf83a42f90a78c6e)
（初）第五弾　ABAPー訓練「Dynpro」

:writing_hand_tone1:[第四弾](https://qiita.com/luyu1567/items/99c366529daae823ea29)
:writing_hand_tone1:[SAP 訓練目次](https://qiita.com/items/dd1fdf83a42f90a78c6e)
#１．概要
画面レイアウト（layout）
      ↓
ロジック流れ(flow logic)
　ＰＢＯ／ＰＡＩ
      ↓
　通信方式（同名）
#２．プログラムの登録 
- Tr-Cd:SE38 or SE80
- プログラム名:SAPMZSTUDENTS
- タイプ:M:モジュールプール 

![h-00100110000_image002.gif](https://qiita-image-store.s3.amazonaws.com/0/185058/ab5201fa-d839-ca5c-fc26-440c3e8389f6.gif)


#３．Dynproの登録 
- Tr-Cd:SE51
- Dynpro番号：9000から採番
- Dynproエレメントタブを表示し、エレメントタイプ'OK'の名称項目に値を設定 
- ここで設定した値をプログラムで判定処理に使用 

#４．Dynproの編集
- Tr-Cd:SE51 ⇒ スクリーンペインタ

#５．GUIステータス 登録
- Tr-Cd:SE41
![h-00100040000_image002.gif](https://qiita-image-store.s3.amazonaws.com/0/185058/c4958a18-3f86-a62c-f852-201414072227.gif)


- メニューバー：黄色いエリアで編集
- アプリケーション：黄色いエリアで編集

[ヘルプ](https://help.sap.com/saphelp_nw70/helpdata/ja/9f/dba99935c111d1829f0000e829fbfe/content.htm?no_cache=true)

[ボタン](https://help.sap.com/doc/saphelp_nw70/7.0.12/ja-JP/9f/dba9a635c111d1829f0000e829fbfe/content.htm?no_cache=true)

#６．GUI表題 登録
- Tr-Cd:SE80
- 右クリック⇒登録⇒GUI表題

[ヘルプ](https://help.sap.com/saphelp_nw70ehp1/helpdata/ja/d1/801d29454211d189710000e8322d00/content.htm?no_cache=true)
#７.PBO Module 作成 

```ruby:ABAP
*--9000--
 MODULE STATUS_9000.
 CALL SUBSCREEN:SUB01 INCLUDING SY-REPID '9100',
                SUB02 INCLUDING SY-REPID '9100'.
*--9100--
 MODULE SET_SCREEN_9100.
 
*--9200--
 MODULE SET_SCREEN_9200.
```

#８.PAI Module 作成

```ruby:ABAP
*--9000--
 CALL SUBSCREEN SUB01.
 CALL SUBSCREEN SUB02. 
 MODULE EXIT_COMMAND_9000 AT EXIT-COMMAND.
 MODULE USER_COMMAND_9000.
*--9100--
 MODULE USER_COMMAND_9100.
```
#９．実装
* 画面属性を改修すれば

```ruby:ABAP

LOOP AT SCREEN.
  IF SCREEN-GROUP1 = 'H1'
    SCREEN-INPUT = 0.
    MODIFY SCREEN.
  ENDIF.

ENDLOOP.
```

* 確認ポップアップ

```ruby:ABAP
CALL FUNCTION 'POPUP_TO_CONFIRM_STEP'

```
:writing_hand_tone1:[第六弾](https://qiita.com/luyu1567/items/82044e7cfa23f08cf7e3)
:writing_hand_tone1:[SAP 訓練目次](https://qiita.com/items/dd1fdf83a42f90a78c6e)
[参照](https://blog.csdn.net/rztyzxzy/article/details/46756761)
AWS X-Ray を使っていると aws-mock から`Service.prototype.customizeRequests is not a function`と怒られる件

## 問題

`aws-mock` が `aws-xray-sdk` に対応していないらしく、`captureAWS` で XRay　関連の関数を呼び出そうとした時点で以下のようなエラーが出てしまいます。

```
/project/dir/node_modules/aws-xray-sdk-core/lib/patchers/aws_p.js:37
      Service.prototype.customizeRequests(captureAWSRequest);
                        ^

TypeError: Service.prototype.customizeRequests is not a function
```

どちらも、元の関数を別の処理に置き換える／処理を差し込むということを目的としているものなので競合は当然かもしれません。

## とりあえずの対処

テスト時には　X-Ray不要なので、それらをコメントアウトするなりで無効化すれば良いのですが、いちいちソースコードを書き換えるのは面倒です。

そこで、`aws-xray-sdk` の読み込みを動的に切り替えるモジュールを作成します

```my-xray.js
module.exports = (function () {
  if (process.env.DISABLE_XRAY) {
    // 環境変数 DISABLE_XRAY が定義されている場合、以下の mock オブジェクトを返す
    const mock = {
      captureAWS (obj) {
        return obj
      },
      captureAsyncFunc (segmentName, asyncFunc) {
        const mockSubSegment = {
          close () { /* do nothing */ }
        }
        asyncFunc(mockSubSegment)
      }
    }
    return mock
  } else {
    // 環境変数が定義されていない場合は通常通り aws-xray-sdk を読み込んで返す
    return require('aws-xray-sdk')
  }
})()
```

これまで `aws-xray-sdk` パッケージを require していた箇所では代わりに `my-xray`　を require するように修正します。

```.diff
- const awsXRay = require('aws-xray-sdk')
+ const awsXRay = require('./my-xray')
const AWS = awsXRay.captureAWS(require('aws-sdk'))
```

これで、`mocha`などでテスト実行する際に環境変数を設定してあげれば X-Ray が無効化された状態でテストが実行できます。

```
$ DISABLE_XRAY=1 yarn run mocha
```
vue-cliのdev-serverをhttps化する

こんにちわ。

先日ついにVue.jsへ手を出し始めました。
敷居高そうで食わず嫌いしてましたが、(とりあえず入口は)全然そんな事無かったです。

さて本題。
`npm run dev`した時のサーバーをHTTPS化するTipsです。
検索すると似たような事例は幾つかあったのですが、どれも上手く行かなかったので、自分の環境で成功した方法を記しておきます。

内部で予め用意されている証明書と、自分で用意した証明書と、どっちも使えるらしいので、簡単に変更出来るようにしました。

基本的に設定変更は`./config/index.js`で行います。

```diff:./config/index.diff
--- ./config/index.js
+++ ./config/index.temp
@@ -11,10 +11,14 @@ module.exports = {
     assetsSubDirectory: 'static',
     assetsPublicPath: '/',
     proxyTable: {},
+    tlsKeyPath: path.resolve(__dirname, '../build/server.key'),
+    tlsCrtPath: path.resolve(__dirname, '../build/server.crt'),
 
     // Various Dev Server settings
     host: 'localhost', // can be overwritten by process.env.HOST
-    port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    port: 443, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    https: true,
+    useOwnCertificate: true,
     autoOpenBrowser: false,
     errorOverlay: true,
     notifyOnErrors: true,
```

```diff:./build/webpack.dev.conf.diff
--- ./build/webpack.dev.conf.js
+++ ./build/webpack.dev.conf.temp
@@ -3,6 +3,7 @@ const utils = require('./utils')
 const webpack = require('webpack')
 const config = require('../config')
 const merge = require('webpack-merge')
+const fs = require("fs")
 const path = require('path')
 const baseWebpackConfig = require('./webpack.base.conf')
 const CopyWebpackPlugin = require('copy-webpack-plugin')
@@ -33,6 +34,11 @@ const devWebpackConfig = merge(baseWebpa
     compress: true,
     host: HOST || config.dev.host,
     port: PORT || config.dev.port,
+    https: config.dev.https
+      ? config.dev.useOwnCertificate
+        ? { key: fs.readFileSync(config.dev.tlsKeyPath), cert: fs.readFileSync(config.dev.tlsCertPath) }
+        : true
+      : false,
     open: config.dev.autoOpenBrowser,
     overlay: config.dev.errorOverlay
       ? { warnings: false, errors: true }
@@ -82,7 +88,7 @@ module.exports = new Promise((resolve, r
       // Add FriendlyErrorsPlugin
       devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
         compilationSuccessInfo: {
-          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
+          messages: [`Your application is running here: ${devWebpackConfig.devServer.https?'https':'http'}://${devWebpackConfig.devServer.host}:${port}`],
         },
         onErrors: config.dev.notifyOnErrors
         ? utils.createNotifierCallback()
```
エクセル列の数値変換(26進数変換)

#はじめに
普段26進数なんて意識しませんが、プログラムからExcelを操作する時に、何列目？って26進数変換します。

###ファイル形式によって扱える最大列数の表

|ファイル形式|最大列数|
|:--|:--|
|Excel(xlsx)|XFD(16384列)|
|Excel97-2003(xls)|IV(256列)|

#実装例
###C#による実装

```c#
///<summary>10進数から26進数を求める</summary>
public static string ToBase26(this long self)
{
    if (self <= 0) return "";

    long n = (self % 26 == 0) ? 26 : self % 26;
    if (self == n) return ((char)(n + 64)).ToString();
    return ((self - n) / 26).ToBase26() + ((char)(n + 64)).ToString();
}
///<summary>26進数から10進数を求める</summary>
public static long FromBase26(this string self)
{
    if (string.IsNullOrEmpty(self)) return 0;

    long result = 0;
    char[] chars = self.ToCharArray();
    int len = self.Length - 1;
    foreach (var c in chars)
    {
        int asc = (int)c - 64;
        if (asc < 1 || asc > 26) return 0;
        result += asc * (long)Math.Pow((double)26, (double)len--);
    }
    return result;
}
```
###VB.NETによる実装
```vb
    '''<summary>10進数から26進数を求める</summary>
    <Extension()>
    Public Shared Function ToBase26(ByVal self As Long) As String
        If self <= 0 Then Return ""
        Dim n As Long = If((self Mod 26 = 0), 26, self Mod 26)
        If self = n Then Return (ChrW((n + 64))).ToString()
        Return ((self - n) / 26).ToBase26() & (ChrW((n + 64))).ToString()
    End Function

    '''<summary>26進数から10進数を求める</summary>
    <Extension()>
    Public Shared Function FromBase26(ByVal self As String) As Long
        If String.IsNullOrEmpty(self) Then Return 0
        Dim result As Long = 0
        Dim chars As Char() = self.ToCharArray()
        Dim len As Integer = self.Length - 1

        For Each c In chars
            Dim asc As Integer = CInt(c) - 64
            If asc < 1 OrElse asc > 26 Then Return 0
            result += asc * CLng(Math.Pow(CDbl(26), CDbl(Math.Max(System.Threading.Interlocked.Decrement(len), len + 1))))
        Next

        Return result
    End Function
```
객체 메소드 "this"

##객쳄메쏘드 예제
```javascript:file.js
let user = {
    name: 'John',
    age: 30
};
user.sayHi = function() {
    alert("hello");
}
user.sayHi();// hello
```
```javascript:file.js
let user = {

}
//함수선언
function sayHi() {
    alert("Hello");
}
user.sayHi = sayHi;
user.sayHi(); // Hello
```
```javascript:file.js
let user = {
    sayHi = function() {
        alert("Hello");
    }
}

let user = {
    sayHi() { // 위와 같은 함수입니다.
        alert("Hello");
    }
}
```
정확히 이야기하면 완전하게 같지는 않고 미묘한 차이가 있다

```javascript:file.js
let user = {
    name: "John",
    age: 30,
    sayHi() {
        alert(this.name);
    }
}

user.sayHi(); // John
```
```javascript:file.js
let user = {
  name: "John",
  age: 30,

  sayHi() {
    alert(user.name); // 신뢰할수 없는 코드이다.
  }

};

//만일 let admin = user 하면 카피한 객체의 user.name 을 찿을수 없게 된다.

let user = {
    name: "John",
    age: 30,
    sayHi() {
        alert(user.name);
    }
}

let admin = user;
user = null;
admin.sayHi(); //error;

```
```javascript:file.js
let user = {name: "John"}
let admin = {name: "admin"}
function sayHi() {
    alert(this.name);
}

user.f = sayHi;
admin.f = sayHi;

user.f(); // johnb
admin.f(); // admin
admin['f'](); //admin  괄호표기로 함수를 호출할수 있다
```
```javascript:file.js
function sayHi() {
    alert(this)
}

sayHi(); //undefiend
```
일반적으로 this객체없이 사용하는 함수의 호출은 정상적인 것이 아니라 프로그래밍 실수입니다. 함수가 가지고있는 경우, this일반적으로 객체의 컨텍스트에서 호출되도록되어 있습니다.

```javascript:file.js

let user = {
    name : "John",
    go: function() {
        alert(this.name)
    }
};

(user.go)();
```
대괄호 (user.go)는 아무 것도하지 않습니다. 
보통 그들은 작업 순서를 설정하지만 ., 어쨌든 점이 먼저 작동하므로 효과가 없습니다. 
세미콜론 만 중요합니다.

```javascript:file.js
let obj, method;
obj = {
    go: function() {
        alert(this);
    }
}
obj.go(); // [object Object]
(obj.go)();// [object Object]
(method = obj.go)();//undefined
(obj.go||obj.stop)();//undefined
```
## 계산기
```javascript:file.js
let calculator = {
    sum() {
        return this.a + this.b;
    },    
    mul() {
        return this.a * this.b
    },    
    read() {
        this.a = +prompt('a?',0);// +prompt 숫자로 인식
        this.b = +prompt('b?',0);
    }
}

calculator.read();
alert(calculator.sum());
alert(calculator.mul());
```

```javascript:file.js
let ladder = {
    step : 0,
    up() {
        this.step++;
    },
    down() {
        this.step--;
    },
    showStep : function() {
        alert(this.step);
    }
};

ladder.up();
ladder.up();
ladder.down();
ladder.showStep(); // 1
```

## chaining 
```javascript:file.js
let ladder = {
    step : 0,
    up() {
        this.step++;
        return this;
    },
    down() {
        this.step--;
        return this;    
    },
    showStep : function() {
        alert(this.step);
        return this;
    }
};
// chaining 모든객체에서 this를 반환
ladder.up().up().down().showStep(); // 1
```
객체를 반환해서 체이닝기법으로 사용할수도 있다.
자바스크립트 라이브러리에서 많이 쓰인다.
Xamarin.Forms SafeAreaをTopだけ設けたい場合

##Xamarin.FormsでTopのステータスバー部分だけセーフエリアを設けたい時があると思う。

結論としては

```c#:TestPage.xaml.cs

protected override void OnAppearing()
{
    base.OnAppearing();
    if( Device.RuntimePlatform == Device.iOS )
    {
        var safeInsets = On<Xamarin.Forms.PlatformConfiguration.iOS>().SafeAreaInsets();
        safeInsets.Bottom = 0;
        this.Padding = safeInsets;
    }
}
```

セーフエリアがある場合は、Bottomも値が入っているので0を代入してあげてマージンを設定してあげるだけ

実に簡単だがあまり情報がなかったので参考にしてほしい。
個人的にはXAML側で記述したいところなので良いコードがあれば情報共有したいと思います。


###おまけ
上下ともSafeAreaがあっても良い場合

```c#:TestPage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:views="clr-namespace:StampApp.Views"
             xmlns:vm="clr-namespace:StampApp.ViewModel"
             x:Class="StampApp.Page.TestPage"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" 
             ios:Page.UseSafeArea="true">
```

XAML側で
ios:Page.UseSafeArea="true"にするだけ
12 Factor App - 開発/本番一致

# 開発、ステージング、本番環境をできるだけ一致させた状態を保つ

---

# みなさん、意識できてますか？

---

# でも一致させるって？

---

# 開発と本番の環境のギャップを小さく保つことで実現

---

# ギャップ🤔

---

# 3つの領域でギャップが現れる

---

- 時間のギャップ
- 人材のギャップ
- ツールのギャップ

---

# 一つずつ見ていきましょう

---

# 時間のギャップ

- 開発したコードが本番に反映されるまで数日・数週間と時間がかかるギャップ

---

- アプリケーションのコードはいろんな人がいじる。時間が経てば経つほどギャップが生まれる
- レビュー待ちでマージまでに時間がかかり、その間加わった変更によってコンフリクトが発生することもある
 
---

## 時間のギャップが生まれると、余分な作業や考え事が増える。コードは時間が経つと腐る

---

# 人材のギャップ

- 開発者本人以外の人がデプロイを行うギャップ

---

- 開発した人以外は、そのコードに深く関わっていないので不具合があったときに気づけなかったりする
- デプロイするコードに他の人のコミットが混ざっていると危ない

---

## 人材のギャップが生まれると、そのコードによってもたらされる挙動の正確なモニタリングができない

---

# ツールのギャップ

- 本番ではLinux、開発ではOSXのように、ミドルウェアやOSなど技術スタックにギャップがある

---

- 想定外の挙動を起こすことがある
- その挙動に遭遇しても、ツールが違うためローカルで再現できず対応できなかったりもする

---

## ツールのギャップが生まれると、僅かな非互換性が顕在化したときに想定外の自体に陥る。問題発見に手間取ってしまう可能性が高まる

---

# まとめると

---

- 時間のギャップを小さくしよう
    - 開発者が書いたコードは数時間後、さらには数分後にはデプロイされるのが理想
- 人材のギャップを小さくしよう
    - コードを書いた開発者はそのコードのデプロイに深く関わり、そのコードの本番環境での挙動をモニタリングする
- ツールのギャップを小さくしよう
    - 開発環境と本番環境の技術スタックをできるだけ一致させた状態を保つ

---

## これで継続的デプロイしやすい環境ができあがり、アプリケーションのライフサイクルのコストが長い目で抑えられることになります👏
【自然言語処理】自然言語処理の入門

【はじめに】
皆さん、こんにちは。機械学習エンジニアの外人です。同時にSEもやってます。
今回は【自然言語処理】を勉強して行きたいと思います。元々は画像処理がメインなんですが自然言語処理の業務を頼まれてやることになりました。もし皆さんからこのサイトが良いですとか自分はここで勉強しましたとかあればぜひ教えて頂けたら嬉しいです。

あ！ちなみに【自然言語】という名前だけで難しいそうなイメージがあるので軽く説明しながらやって行きたいと思います。もし僕は論文レベルで勉強したいっていう方は他の方の記事を読んで下さい。

##自然言語とは
>[自然言語のウィキペディア](https://ja.wikipedia.org/wiki/%E8%87%AA%E7%84%B6%E8%A8%80%E8%AA%9E)こちらを引用します。

 + 人間によって日常の意思疎通のために用いられる、文化的背景を持って自然に発展してきた言語である。
 + 人間がお互いに<b>コミュニケーション</b>を行うための自然発生的な言語である。

もっと簡単に言うと<b>英語</b>、<b>日本語</b>、<b>中国語</b>など人間がいつも使っている単語とかが自然言語です。


##自然言語処理とは
>[自然言語処理のウィキペディア](https://ja.wikipedia.org/wiki/%E8%87%AA%E7%84%B6%E8%A8%80%E8%AA%9E%E5%87%A6%E7%90%86)こちらを引用します。

+ 人間の単語を理解できる<b>アプリケーション</b>と<b>サービス</b>を開発すること
+ 人間が日常的に使っている自然言語を<b>コンピュータ処理</b>させること

##自然言語処理の特徴
>[機械学習における自然言語処理](http://gagbot.net/machine-learning/ml3)こちらを引用します。

+ 英語版
![image.png](https://qiita-image-store.s3.amazonaws.com/0/309361/503898e6-b031-7840-7da8-6d7d3d6c5c8f.png)
文章から分割した単語をクリーニングした後特徴量を抽出します。これか<b>ベクトル化</b>だと呼ばれます。そして<b>ベクトル化</b>したことで<b>文章の類似度を比較</b>したり、<b>意味を抽出</b>したり、<b>機械翻訳</b>することが可能となります。

+ 日本語版
![image.png](https://qiita-image-store.s3.amazonaws.com/0/309361/029db25a-cade-d737-c864-847619bfb44f.png)
英語とは違い日本語には文章の区切りがないため単語の意味とか文法などをデータベース化する必要があります。日本語には時代によって意味が変わることもあり、新しいこと言葉が出たりするので<b>曖昧さ</b>が存在します。なのでまず<b>形態素解析</b>→<b>構文解析</b>→<b>意味解析</b>→<b>文脈解析</b>の順番で処理が行います。

【まとめ】
やはり画像処理より難しいですね。自分なりにまとめたりして記事として載せますが皆さんに役に立つのかはわかりませんが、この記事は徐々にアップデートしますので、何かあったらコメント残して下さい。
DbCommand 型の拡張 (SQL 実行)

# System.Data.Common.DbCommand 型のユーティリティ

拡張メソッド用に DbCommandExtensions クラスを用意


## SQL 実行メソッドをラップ

DbCommand クラスには、SQL を実行するメソッドが 3 つあるが、実行したクエリをログ出力したい場合など、それぞれのメソッドをラップしておけば便利。

- ExecuteNonQuery
- ExecuteScalar
- ExecuteReader

### ログ出力
まずはログ出力用のメソッド（中身は適当に変更）

```C#
static void Log(this DbCommand command)
{
	Trace.WriteLine(command.CommandText);
}
```

### ExecuteNonQuery
結果を伴わないクエリの実行

```C#
public static void Execute(this DbCommand command)
{
	if (command == null) throw new ArgumentNullException(nameof(command));
	try
	{
		command.Log();
		command.ExecuteNonQuery();
	}
	catch (Exception ex)
	{
		throw new ApplicationException("Attempt to ExecuteNonQuery failed.", ex);
	}
}
```

### ExecuteScalar
結果を１つだけ取得するクエリの実行

```C#
public static TResult Execute<TResult>(this DbCommand command)
{
	Func<Type, bool> isNullable = type => type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>));
	Func<Type, Type> getBaseOrSelf = type => isNullable(type) ? Nullable.GetUnderlyingType(type) : type;

	if (command == null) throw new ArgumentNullException(nameof(command));
	try
	{
		command.Log();
		var result = command.ExecuteScalar();
		if (result == null) return default(TResult);
		if (result is DBNull) return default(TResult);
		return (TResult)Convert.ChangeType(result, getBaseOrSelf(typeof(TResult)));
	}
	catch (Exception ex)
	{
		throw new ApplicationException("Attempt to ExecuteScalar failed.", ex);
	}
}
```

### ExecuteReader
テーブル情報を取得するクエリの実行
- IDataRecord から任意の型に変換するメソッドを渡す

```C#
public static IEnumerable<TResult> Execute<TResult>(this DbCommand command, Func<IDataRecord, TResult> parse)
{
	if (command == null) throw new ArgumentNullException(nameof(command));
	if (parse == null) throw new ArgumentNullException(nameof(parse));
	try
	{
		command.Log();
		return command.ExecuteYield(parse);
	}
	catch (Exception ex)
	{
		throw new ApplicationException("Attempt to ExecuteReader failed.", ex);
	}
}

private static IEnumerable<TResult> ExecuteYield<TResult>(this DbCommand command, Func<IDataRecord, TResult> parse)
{
	using (var reader = command.ExecuteReader())
	{
		while (reader.Read()) yield return parse(reader);
	}
}
```


## 使用例

```C#
using (var connection = new SqlConnection("接続文字列"))
{
	connection.Open();

	using (var command1 = connection.CreateCommand())
	{
		command1.CommandText = "UPDATE xxx SET value = 'test' WHERE key = 1";
		command1.Execute();
	}

	using (var command2 = connection.CreateCommand())
	{
		command2.CommandText = "SELECT value FROM xxx WHERE key = 1";
		var value = command2.Execute<string>();
	}

	using (var command3 = connection.CreateCommand())
	{
		command3.CommandText = "SELECT * FROM xxx";
		var records = command3.Execute(record =>
		{
			return new KeyValuPair<int, string>(record.GetInt32(0), record.GetString(1));
		});
	}
}
```
Dev AWSome Day 2018の復習③　～Amazon S3編～

[前回](https://qiita.com/mine820/items/0267ce3763612786a62b)に続き、「[Dev AWSome Day 2018](https://aws.amazon.com/jp/aws-devday-tokyo-2018/dev-awsomeday/)」の復習として、「Amazon S3」を勉強し直します。

AWSにおいてS3は基本中の基本ですが、今回はアクセス権限の設定がメインのお話となります。

# S3について
こちらは改めて説明する必要もないと思いますが、インターネット経由でアクセスできる非常にスケーラブルで耐久性の高いオブジェクトストレージになります。

今回は、認証済みのユーザのみがファイルを保存できるようにします。

# バケットの作成
S3を利用するには、データ(以下、オブジェクトとします) を格納するバケットを作成します。

1. マネージメントコンソールを開く
2. 「S3」を選択<br/>![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/b989cb9f-502b-158d-1064-adeadd6e2f28.png)
3. 「バケットを作成する」ボタンをクリック
4. 「バケット名」を入力し、「作成」ボタンをクリック

# バケットのCORS（Cross Origin Resource Sharing）設定
今回、公開用のWebアプリ側のコードをS3に置くため、そこから別のバケットにアクセスすることになります。
その許可の設定をCORSで行います。

1. 先ほど作成したバケットを選択
2. 「アクセス権限」を選択
3. 「CORSの設定」ボタンをクリック
4. CORSの構成を入力し、「保存」ボタンをクリック

入力するCORSの構成の例は以下のようになります。

```text
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <ExposeHeader>x-amz-server-side-encryption</ExposeHeader>
        <ExposeHeader>x-amz-request-id</ExposeHeader>
        <ExposeHeader>x-amz-id-2</ExposeHeader>
        <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>
```

# アプリケーションでの設定
JavaScriptからS3への保存部分は以下のようになります。

前回修正した部分のうちの「Storage:」のところに、作成したバケット名を設定します。

```javascript
Storage: {
  bucket: 'devawsome-photo-mine',   
  region: 'us-west-2'
}
```

あとは、実際にファイルを保存するコードを作成します。

```javascript
// Task: S3 Upload
console.log("Define S3 Put Operation here.");
Storage.put(photokey, file, {
        level: 'private',
        contentType: contentType,
        metadata: {
            username: username,
            description: Base64.encode(this.state.desc)
        }
    })
    .then(result => {
        console.log(result);
        alert("Uploading succeeded");
    })
    .catch(err => {
        console.log(err);
        alert("Err: " + err);
    }
```

# Cognitoでの設定
あとはCognitoにもアクセス権限の設定をしてあげる必要があります。

1. マネージメントコンソールを開く
2. 「Cognito」を選択
3. 「フェデレーテッドアイデンティティの管理」ボタンをクリック
4. 作成したIDプールを選択
5. 「IDプールの編集」を選択
6. 認証されたロールの名前を確認

この確認した名前に対してS3バケットへのアクセス権限を与えます。

1. マネージメントコンソールを開く
2. 「IAM」を選択
3. 「ロール」を選択
4. 先程確認したロールを探し、選択<br/>※似た名前で「Unauth」となっている方ではないので注意
5. 「インラインポリシーの追加」を選択
6. 「JSON」タブを選択し、権限を入力
7. 「Review policy」ボタンをクリック
8. 名前を入力して、「Create poilcy」ボタンをクリック

設定する権限（JSON）は以下のような感じになります。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3put01",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": [
                "arn:aws:s3:::devawsome-photo-mine",
                "arn:aws:s3:::devawsome-photo-mine/*"
            ]
        }
    ]
}
```

# まとめ
S3にアクセス権限を設定する手順を確認しました。
S3のバケット側の設定（どこからのアクセスに何を許可するのか）とCognito側の設定（どのユーザにどこに対してどういう許可を与えるか）があるようです。
Reactの関数にコンポーネントの配列を返す時はkeyに要注意

# Reactの関数にコンポーネントの配列を返す時はkeyに要注意

Reactのwarningを解消しようと試行錯誤していた所、アンチパターンになりそうな書き方を見つけたので紹介します。
「コンポーネントを配列に格納したい時は各コンポーネントに必ずkeyを割り振ろう」という話です。

## 環境

* React 16.2.0

## コンポーネントの配列

React上で複数のコンポーネントをまとめて扱いたい時に使います。
例えば、以下のような書き方をすることでComponentA,B,Cをひとまとめにして返すことができます。

``` javaScript

anyFunction(){

  ver list = [];

  list.push(<ComponentA />);
  list.push(<ComponentB />);
  list.push(<ComponentC />);

  return list;
}

```

実際には配列やmapから渡して繰り返しコンポーネントを生成する場面での使い道のほうが多いです。
（テーブルの列を生成する時など）

``` javaScript
   Object.keys(this.props.data).forEach((key, index) => {
      list.push(
        <Checkbox
          key={this.props.data[key].id}
          id={this.props.data[key].id}
          label={this.props.data[key].label}
        />,
      );
    });
```



## ハマった所

しかし、ブラウザで画面を開いてコンソールを開くと下記のようなWarningが出ることがあります。

```
Warning: Each child in an array or iterator should have a unique "key" prop.

Check the render method of `ParentComponent`. See https://fb.me/react-warning-keys for more information.
```


直接keyを指定しないと出るようです。

なので、最初のコードは

``` javaScript

anyFunction(){

  ver list = [];

  list.push(<ComponentA key={"a"} />);
  list.push(<ComponentB key={"b"} />);
  list.push(<ComponentC key={"c"} />);

  return list;
}

```

と書かないとwarningが出ます。

もしくは、returnを使うとkey値を指定しなくてもよくなります。


``` javaScript

anyFunction(){

  ver list = [];

  list.push(<ComponentA key={"a"} />);

  return list;
}

```

と、以下のコードが同じような意味合いです。

``` javaScript

anyFunction(){

  return(
    <ComponentA />
  );
}

```

配列にコンポーネントを持たせるときは（1個であっても）必ずkeyを割り振りましょう、というReactの作法。

returnを使う場合は自動でkeyを割り振ってくれることもありますが、それ以外はkeyを明示したほうがよさそうです。

* 直接returnする
* そもそも配列で複数コンポーネントを渡さない

ようにするとこのwarningを回避できる＋Reactと相性の良いコードになりそうです。
今回のように直接コンポーネントが置かれているとわかりやすいですが、コードによっては色々ネストして、


``` javaScript

import Table from 'react-bootstrap';

//略

  list.push(
   <Table>
     <tbody key={'tbody_key'}>
         <tr key={"event_start_date_column"}>
           <td><ComponentA key={aaa}/></td>
           <td><ComponentB key={bbb}/></td>
           <td>ccc</td>
      </tr>
      // 略
    </Table>
  );
//略
```

のようになると、うっかり「Tableにkey入れるの忘れてた！」とハマることがあるので、
1関数で1コンポーネントをreturnして配列を返すのを避けるようにしたほうが良い設計になるのかな、と思いました。


## まとめ

Reactの配列はObjectの配列として扱われるので、コンポーネントとして扱われず、自動的にkeyが割り振られないのかと。

一方で、`return(<Component />);` の場合は自動的にkeyを割り振ってくれるため、わざわざ`return(<Component key={'component_key'} />);` のような書き方をしなくてOKらしい。

今回紹介したwarningを見かけた方へ解決の参考になれば幸いです。


## 参考

* (React.jsの地味だけど重要なkeyについて)[https://qiita.com/koba04/items/a4d23245d246c53cd49d]
* (Reactでユニークなkey指定の警告が出たときの対処法)[https://hacknote.jp/archives/25626/]
AWSとGCP間のインターネットVPN接続のファイル転送速度を計測してみる

# はじめに
前回の記事でGCPとAWS間をインターネットVPNで接続しました。
https://qiita.com/TBT/items/2a834e119b10f51d57bf

今回はこの環境を使ってファイルの転送速度を確認してみます。
結論から言うと、**GCP～AWS間のインターネットVPNのファイル転送速度はかなり速いです。**

# 基本環境

![AWS&GCPインターネットVPN(基本環境).png](https://qiita-image-store.s3.amazonaws.com/0/169814/e7fd3880-9166-fd7e-2291-afeb76010dc9.png)

# 実施環境
* GCP、AWSそれぞれの環境にWindowsサーバを立てる。
* プライベートIPでWindowsファイル共有できるようにする。
* 2GBのファイル転送にかかる時間を計測する。

参考：ファイル作成Windowsコマンド

```
fsutil file createnew testfile 2147483648
```

# 実行パターン
以下の3条件のうち1つだけを変えて計測
1. 時間帯
2. リージョン
3. マシンスペック


## 時間帯別
朝は09:00頃、昼は16:00頃、夜は23:00頃に計測

||朝|昼|夜|
|---|---|---|---|
|1回目|76秒|70秒|64秒|
|2回目|71秒|65秒|84秒|
|3回目|74秒|62秒|62秒|
|転送速度|約220Mbps|約250Mbps|195Mbps～265Mbps|

時間帯による大きな差はなかった

## リージョン別

- 同リージョン
 - GCPは**asia-northeast1**
 - AWSは**ap-northeast-1**
- 異リージョン 
 - GCPは**asia-northeast1**
 - AWSは**us-east-1**

![AWS&GCPインターネットVPN(異リージョン).png](https://qiita-image-store.s3.amazonaws.com/0/169814/8447329a-1bbb-6be6-83fe-3bf04305f785.png)


||同リージョン|異リージョン|
|---|---|---|
|1回目|58秒|12分35秒
|転送速度|約280Mbps|約21.7Mbps|

異なるリージョンだと転送速度はかなり遅くなるが、インターネットVPNにしてはそれなりの速度は出ている。

## マシンスペック別
- 最低スペック
 - GCPは**f1-micro**（vCPU x 1、メモリ 0.6 GB） 
 - AWSは**t3.nano**（vCPU x 2、メモリ 0.5 GB）
- 中スペック
 - GCPは**n1-standard-1**（vCPU x 1、メモリ 3.75 GB）
 - AWSは**t3.medium**（vCPU x 2、メモリ 4 GB）
- 高スペック
 - GCPは**n1-standard-8**（vCPU x 8、メモリ 30 GB）
 - AWSは**t3.2xlarge**（vCPU x 8、メモリ 32 GB）

||最低スペック|中スペック|高スペック|
|---|---|---|---|
|1回目|306秒|66秒|65秒|
|転送速度|約53Mbps|約250Mbps|約250Mbps|

中スペック以上は回線側がボトルネックになるのか転送速度は変わらず。
インスタンス毎の帯域やディスクI/Oというよりは、インスタンス自体のスペック（メモリ）の影響が大きいのかと思った。
prepushでjestのテストを動かすとasync functionがSyntaxError

こんな感じになってた

    husky > npm run -s prepush (node v6.10.3)
      :
      :
          beforeAll(async () => {
                          ^
    SyntaxError: Unexpected token (

huskyがnode v6で動いてasyncがSyntaxErrorになってた。
node v6.10.3はnvmのdefaultのverをみているみたいだった。

    $ nvm ls
            v6.10.3
            v7.10.0
            v8.1.4
            v8.2.1
    ->       v8.9.4
    default -> v6 (-> v6.10.3)
    node -> stable (-> v8.9.4) (default)
    stable -> 8.9 (-> v8.9.4) (default)
    iojs -> N/A (default)
    lts/* -> lts/carbon (-> v8.9.4)
    lts/argon -> v4.8.7 (-> N/A)
    lts/boron -> v6.12.3 (-> N/A)
    lts/carbon -> v8.9.4
    $

nvmのデフォルトを変更

    $ nvm alias default v8.9.4
    default -> v8.9.4

これでちゃんとテストが動くようになった。