OmniAICreator/Qiita-1.07M huggingface dataset:
Google Formのサブミット時にGoogle Apps Scriptで値を取得する（Slackに通知するサンプルコード付）

# 概要
Google Formのsubmit時にtriggerとして設定した関数からフォームの情報を取得したい。
これを達成するためドキュメントを読んだり、リバースエンジニアリング的に調査した結果をまとめておきます。
備忘録です。

コピペで使えるようなコードを記載していますので、ぜひご利用ください！

# 対象読者
- Google Formのsubmit時に何かしたい人
  - Google Formのsubmit時にSlackに通知したい人

# 前提知識
Google Formのフォームサブミット時のトリガーのコールバック関数の一覧を確認しておきましょう。
参照: https://developers.google.com/apps-script/guides/triggers/events#form-submit_4

- authMode
- response
- source
- triggerUid

Google Formのフォームサブミット時のユーザが回答した内容は `response` パラメータに含まれます。
回答以外の要素(タイトル、説明)などは `source` パラメータに含まれます。

# サンプルコード

サンプルコードを添付します。サンプルコードの解説は次の章に記載します。

```js
function submit(event) {
  var itemResponses = event.response.getItemResponses();
  
  var order = '';
  var firstName = '';
  var lastName = '';
  
  for (var i = 0; i < itemResponses.length; i++) {
    var itemResponse = itemResponses[i];
    var question = itemResponse.getItem().getTitle();
    var type = itemResponse.getItem().getType();
    var answer = itemResponse.getResponse();
    if (question === 'お名前（姓）をご入力ください'){
      lastName = answer;
    }
    else if (question === 'お名前（名）をご入力ください') {
      firstName = answer;
    }
    
    if(type == 'GRID'){ // typeはEnumのため比較演算子を使う
      var rows = itemResponse.getItem().asGridItem().getRows();
      for(var j = 0; j < rows.length; j++){
        var titleRow = rows[j];
        var answerCol = answer[j];
        order += titleRow + ' : ' + answerCol + '\n';
      }
    }        
  }
  
  var message = order 
  message += '名前: ' + lastName + firstName + JSON.stringify(getItemSummary(event));
  notifySlack({ message: message })
}

// 回答したフォームに配置されているアイテム全てをオブジェクトに変換する
function getItemSummary(event) {
  var items = event.source.getItems();
  
  var sourceSummary = [];
  
  for (var i = 0; i < items.length; i++) {
    var item = items[i]
    var title = item.getTitle();
    var type = item.getType() + '';
    var helpText = item.getHelpText();
    
    var summary = {
      title: title,
      type: type,
      helpText: helpText,
    }
    
    sourceSummary.push(summary)
  }
  return sourceSummary
}


function notifySlack(opt) {
  var WEBHOOK_URL = ''; // Slackで取得したweb hook url
  var options = opt || {}
  var jsonData = {
    "username": options.botName || '通知',
    "text": options.message || "送信テスト",
    "icon_emoji": options.botIcon || ':bird:'
  };
  var payload = JSON.stringify(jsonData);
  UrlFetchApp.fetch(WEBHOOK_URL, {"method": "post", "payload": payload});
}
```

## サンプルコードに書いてあること
- フォームサブミット時にユーザの回答をstringに変換する
- フォームサブミット時にフォームの要素全てをobjectに変換する
- Google Formの選択式(グリッド)の内容を取得したい場合は、asGridItem関数でGridItemを取得し、全ての情報を取得する
- Google Apps ScriptからSlack通知を行いたい場合は、web hook URLを取得し、UrlFetchAppでpostする
- getType関数はEnumが返るため文字列にしたい場合は、空文字と結合することで対応する


# おわりに
Google Formのsubmit時のtriggerのドキュメントを見つけるのが難しかったのと
リバースエンジニアリング的に挙動を調べ、思いの外時間が取られたのでまとめました。

参考になれば幸いです！

Happy coding!

# 参照文献
https://developers.google.com/apps-script/guides/triggers/events#form-submit_4
Bullet Physicsの導入

#Bulletのダウンロード
githubからクローンするかzipをダウンロードします
バージョンは  2.83 です
https://github.com/bulletphysics/bullet3

#プロジェクトのビルド
ダウンロードしたフォルダの中にある
build_visual_studio_vr_pybullet_double.bat
をダブルクリックすると同じフォルダにあるbulid3の中のvs2010にプロジェクトが作成されます

0_Bullet3Solution.sln
からソリューションを開きビルドをして正常にビルドが終了するか確認します

phythonが入っていない場合エラーが出ますがその機能を使わない場合は問題ないので無視しても大丈夫です

ダウンロードしたフォルダの一番上にあるbinフォルダの中にlibファイルがあるか確認します
BulletDynamic
BulletCollision
LinearMath
があれば最初は大丈夫だと思います

このBinフォルダとsrcフォルダへの環境変数を作っておくとbulletを使ったプロジェクトの作成が楽になると思います

#Bulletを使ったプロジェクトを作成
Visual Studio 2017 ver15.7.5で作っていますが基本的には変わらないと思います

プロジェクトを作成し上にある
**プロジェクト->プロパティ**
プロパティ画面で左にある
**c++->全般**
の一番上にある
**追加のインクルードディレクトリ**
にダウンロードしたフォルダにあるsrcフォルダへのパスを通します

**c++->プリプロセッサ**
の一番上にあるプリプロセッサの定義の部分に
**BT_THREADSAFE=1
BT_USE_DOUBLE_PRECISION**
の二つを追加します

プロパティ画面の左にある
**リンカ->全般**
の上から８番目にある
**追加のライブラリ ディレクトリ**
にダウンロードしたフォルダにあるbinフォルダへのパスを通します

**リンカ->入力**
の一番上にある
**追加の依存ファイル**
使用したいlibファイル(binフォルダの中にあるもの)の名前を書きます
x64とx86(Win32)、debug,releaseを間違わないようにします

*btBulletDynamicsCommon.h*
をインクルードし
次のコードを追加してプロジェクトをビルドしてみます

```c++:test.cpp
	btBroadphaseInterface* broadphase = new btDbvtBroadphase();
	
	btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
	btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);

	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver();

	btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);

	delete broadphase;
	delete collisionConfiguration;
	delete dispatcher;
	delete solver;
	delete world;

```

エラーが出なければ導入成功です

#おわりに
プリプロセッサで定義したBT_USE_DOUBLE_PRECISIONはlibファイルをビルドするときに各プロジェクトから外しておけば使用するプロジェクトでも書く必要がなくなります
この定義はbullet内の各クラスが値をdoubleで持つようにので精度が上がるはずです
定義を書かない場合はfloatになります
個人的にはdoubleが必要になる場面はまだないので外していいかなと思います

lib作成時の定義と導入プロジェクトの定義とで差異があると
未解決の外部シンボルやデリートしたときのエラーが起きるので原因のがわからず個人的に導入で一番躓いた部分でした

この定義の部分に触れているbulletの導入記事が見当たらなかったので今回の記事を書いてみました
公式のどこかに書いてあったのかな？
[AWS]Route53の「エイリアス」レコードについて

ソリューションアーキテクトの資格本を読んでいて、「AWSでは「エイリアス」レコードが独自で提供されていて、これを使えば「zone apex」でマッピングできるよ。CNAMEだとできないから便利だよ」という内容の意味がよくわからなかったので、少しお勉強しました。（AWSというよりはDNSの話）

https://aws.amazon.com/jp/route53/faqs/#Supported_DNS_record_types

色々探している内に詳しい記事を見つけました。

https://tech.blog.aerie.jp/entry/2014/09/09/162135

正直DNSの知識はかなりお粗末なのでちゃんと理解できたとは言い難いのですが、ざっくり言うと、

- あるラベル名でCNAMEを定義したら、他のレコードは指定できない
- ドメインを定義する時はCNAME以外にも色々（MXとかSOAとか）を指定する必要がある

この二つが矛盾するので、CNAMEレコードでドメインを定義できない、という理屈のようです。
あまりピンときていないので、DNSのゾーンファイルの書き方から出直してきます。
新しいSelenium IDEでeval

# 背景

新しいSelenium IDEでevalがなくて困ってると言う話を聞いたので、調べてみたところ代わりが即見つかったのでメモっておく。

# 使用したSelenium IDE

- Chrome版3.4.5
- https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd?utm_source=chrome-ntp-icon

# やり方

- execute script / execute async scriptを使う

# 設定例

- randomで出した数字を出力してみる

|Command|Target|Value|
|:--:|:--:|:--:|
|execute script|return Math.random();|var1|
|echo|${var1}||

# ログ

> Running 'Untitled'
> 1.executeScript on return Math.random(); with value var1... OK
> echo: 0.2338915770602541
You are using pip version 9.0.3, however version 18.1 is available.となったときの対応方法

# 事象 : pipコマンドを使ったらYou are using pip version 20.1.1; however, version 20.2.4 is available.となった
- 環境
    - Windows10 Pro 64bit バージョン1909
    - Python 3.8.5

```bash
# 仮想環境でMkDocsをインストールしたらなんか言われた
$ pip install mkdocs
# ...省略...
WARNING: You are using pip version 20.1.1; however, version 20.2.4 is available.
You should consider upgrading via the 'c:\path\to\mkdocs\scripts\python.exe -m pip install --upgrade pip' command.
(mkdocs)
```

## 原因 : バージョンが古いから
時がたっても原因は同じ

```bash
$ pip --version
pip 20.1.1 from c:\path\to\mkdocs\lib\site-packages\pip (python 3.8)
(mkdocs)
```

### 対応方法 : アップグレードする
やってから思った・・・仮想環境作る前にやっときゃよかった・・・と思いながら仮想環境の外でもアップグレードする・・・

```bash
$ python -m pip install --upgrade pip
Collecting pip
  Downloading pip-20.2.4-py2.py3-none-any.whl (1.5 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 20.1.1
    Uninstalling pip-20.1.1:
      Successfully uninstalled pip-20.1.1
Successfully installed pip-20.2.4
(mkdocs)

# アップグレードした最初はウイルススキャンツールとかが動いて遅いことがある
$ pip --version
pip 20.2.4 from c:\path\to\mkdocs\lib\site-packages\pip (python 3.8)
(mkdocs)
```

# 事象 : pip3コマンドを使ったらYou are using pip version 9.0.3, however version 18.1 is available.となった
- 環境
    - macOS Mojave バージョン10.14.1
    - Python 3.6.5
    - pip 9.0.3
  

```bash
$ pip3 install requests
# ...省略...
Successfully installed certifi-2018.10.15 chardet-3.0.4 idna-2.7 requests-2.20.1 urllib3-1.24.1
You are using pip version 9.0.3, however version 18.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```

## 原因 : バージョンが古いから
```bash
$ pip3 --version
pip 9.0.3 from /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages (python 3.6)
```

### 対応方法 : アップグレードする
```bash
$ pip3 install --upgrade pip
Collecting pip
  Downloading https://files.pythonhosted.org/packages/c2/d7/90f34cb0d83a6c5631cf71dfe64cc1054598c843a92b400e55675cc2ac37/pip-18.1-py2.py3-none-any.whl (1.3MB)
    100% |████████████████████████████████| 1.3MB 1.1MB/s 
Installing collected packages: pip
  Found existing installation: pip 9.0.3
    Uninstalling pip-9.0.3:
      Successfully uninstalled pip-9.0.3
Successfully installed pip-18.1

$ pip3 --version
pip 18.1 from /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pip (python 3.6)
```
ButtonとUnityEventよもやま

uGUIのButtonとかでおなじみのUnityEventですが、あんまり開発現場では人気がないような気がしませんかね。するよね実際。

だいたい、

```C#:TestButtonScene1.cs
using UnityEngine;
using UnityEngine.UI;

public class TestButtonScene1: MonoBehaviour
{
    [SerializeField] private Button sampleButton;

   void Start()
    {
        sampleButton.onClick.AddListener(() => {
            //処理
        });
    }
}
```

こんな風にコード上で入れちゃう。

コレをButtonのUnityEventでメソッドを呼ぶ形にすると、

```C#:TestButtonScene2.cs
using UnityEngine;

public class TestButtonScene2: MonoBehaviour
{
    public void OnSampleButtonClick()
    {
            //処理
    }
}
```

こんな風に書けるわけで、一見こっちのほうがシンプルだしButtonの参照もなく、コンポーネントが独立してていいじゃーんと思うわけです。

### メリットとか

一人で作ってるならともかうとして複数人でコードをいじる場合、ButtonのUnityEventを使うとバグった時にコード上からは追いにくいのですね。

TestButtonScene1.csの場合はコードを読むだけでボタンの中の処理だとわかる。
TestButtonScene2.csに場合はもちろんメソッド名がOn～ButtonClickなんだから分かるだろ、ってなもんですが、その保証はないし。publicメソッドだからどこからでも呼べるわけだし。うっかり貼り間違いとかでもバグることになる。

プログラマはできることならIDEから離れたくない人種(偏見)なのでTestButtonScene1.csが好まれたりするのだと思います。

### UnityEventをどういう時に使う？
上でも書きましたが、UnityEventを使うとメソッドの呼ぶ先を貼り付けれるわけですからコンポーネントの独立性を保ちやすいです。

いろんな場所で使って欲しいようなコンポーネントを作る時に効果を発揮するでしょう。汎用性でる。

逆に言えばそうでないなら無理して使うこともないよねって思います。


#### 余談1

Buttonに入れるもう一つのメリットとして、Buttonの拡張を仕込んでおけば「連打」や「同時押し」を抑制できるというのがあります。UniRxとか使うとイイよね。

この辺は特にスマフォ向けだとなにかとバグるし、イチイチメソッドごとに対策いれるのも面倒だしで賞味こっちのメリットのほうが大きいかも。

#### 余談2

AddListenerは何個も入れれてしまうのでウッカリOnEnableとかリフレッシュ処理とかに突っ込むと沢山はいってしまう。この辺も拡張解決したほうが幸せです。
【備忘録】MongoDB使用してRailsでマイグレする方法

MongoDBのフィールドを追加等したときの
Rails側のマイグレーション方法の備忘録。
(コマンド叩く必要ないので)


例:
MongoDBの
コレクション:Userに
フィールド:emailを追加

環境
---
Rails v5.2.1
MongoDB v4.0.2


Rails
---
model側に

```rb:user.rb
class User
  include Mongoid::Document
  include Mongoid::Timestamps
  field :name, type: String
  # (追加)emailフィールド
  field :email, type: String

  validates :name,{presence: true, uniqueness: true}
  
  # (追加)emailカラムに関するバリデーション
  validates :email,{presence: true, uniqueness: true}

end
```

的な感じでフィールド追加すればいける
Tubidy

With the internet entering our lives, everyone has been surfing the websites among the greatest passions. While you are tired from work to home or after school, surfing the internet sites are among the entertainments of everyone, it is also nice to have publications that appeal to each audience. Today we will offer you the most beautiful songs downloading site and will tell you how to use the site, we will provide you to reach songs easily. The songs in the site, in every sense to be beautiful and up to date and of course, you can also find popular songs around the world, you want to enjoy the download of tubidy music as you want. https://tubidylive.com
ATFでList型のフィールドに値設定できない

- ServiceNowのバージョンはKingston

# こまったこと
- ATFのテスト内で、List型のフィールドに値を設定したかった
- でもSet Field Values では設定できなかった
- 必須フィールドなので設定できないとテストできない

# 回避策
- そのテスト中のみ、デフォルト値を無理やり設定することで回避できた
- ただし sys_dictionary テーブルの変更なので、テストはGlobalスコープで作成する必要がある
    - テスト実行時のスコープは、そのテストを作成したスコープと同じ
    - できれば避けたい。。。が、いい方法が思いつかない
- また、実行時のユーザーは、アクセス制御的にsys_dictionary変更可能なユーザーである必要がある。

# 詳細
Serverカテゴリのテストステップを作成する

inputsは以下の通り

- u_table(TableName型)
- u_field(FieldName型, depend on で↑を選ぶ)
- u_value(String型 長さは512※)

outputsは以下の通り

- u_value（String型　長さは512※）

※ sys_dictionary.default_valueの文字長が512

説明生成スクリプト

```
function generateDescription() {
	var t = step.inputs.u_table;
	var f = step.inputs.u_field;
	var v = step.inputs.u_value; // String
	
	var description = "["+t+"."+f+"] のデフォルト値を一時的に ["+v+"] に変更します";
	return description;
}
generateDescription();
```

実行スクリプト

```
(function executeStep(inputs, outputs, stepResult, timeout) {
	try {
		// GlideRecord準備
		var gr = new GlideRecord('sys_dictionary');
		
		// 入力値を準備
		var t = inputs.u_table;
		var f = inputs.u_field;
		var v = inputs.u_value; // String
		
		// 一応出力
		outputs.u_value = v;
		
		// 対象のフィールドを検索
		gr.addQuery('name', t);
		gr.addQuery('element', f);
		gr.query();
		var found = gr.getRowCount();
		
		// 1件ではなかった場合はテスト失敗
		if (found != 1) {
			stepResult.setOutputMessage('['+t+'.'+f+'] の検索結果が'+found+'件でした');
			stepResult.setFailed();
			return;
		}
		
		// 見つかったレコードを対象にする
		gr.next();
		
		// デフォルト値を更新
		gr.default_value = v;
		var result = gr.update();
				
		if (result) {
			// 更新に成功した
			stepResult.setOutputMessage('['+t+'.'+f+'] のデフォルト値を一時的に ['+v+'] に変更しました('+result+')');
			stepResult.setSuccess();
		}　 else {
			// 更新に失敗した
			stepResult.setOutputMessage('['+t+'.'+f+'] のデフォルト値を一時的に ['+v+'] に変更しようとしましたが、失敗しました');
			stepResult.setFailed();
		}
	} catch(e) {
		// 例外発生時はテスト失敗
		stepResult.setOutputMessage(e);
		stepResult.setFailed();
	}
}(inputs, outputs, stepResult, timeout));
```

おしまい
macOS Docker導入メモ 2

# Docker版 ubuntuでやったこと
## user登録
常にルートで動いているのも気持ち悪いのでラズパイ用にアカウントを追加してsudo権限を持たせた
＊ただしuserのDockerグループへの登録は危険ですので注意しましょう
https://qiita.com/matyapiro31/items/3e6398ce737e2cdb5a22

```sh
# adduser raspi
# gpasswd -a raspi sudo
```
パッと見た感じこのコマンドを実行しても```/etc/sudoers```ファイルがないので登録が成功したか分からない。

```sh
echo 'Defaults visiblepw'　>> /etc/sudoers
```
これでsudoersファイルは作れたけどraspiアカウントは何も記載がない状態。
sudoersの中身は
https://wa3.i-3-i.info/word13805.html
https://qiita.com/kmikmy/items/6a6a086f6415d9b55b96
このサイトなどが参考になった

```sh
# usermod -G sudo raspi
# cat /etc/group | grep raspi
sudo:x:27:raspi
raspi:x:1000:
```
上記のコマンドでsudoグループに登録されていることが分かった
ただしsudoersへの登録はされていないので、必要なら登録する。
調べていて、セキュリティの考慮なしにユーザー登録するのはまずいという記事を見つけたので貼っておく
https://qiita.com/matyapiro31/items/3e6398ce737e2cdb5a22

# Dockerの使い方
## 設定が消えた！
Dockerを起動してapt installや/etc/*.confファイルを編集してexitした後、Dockerのubuntuを起動し直したら全部消えていた。
原因はDockerの起動方法にあった

```
Docker run -it ubuntu
```
を毎回実行していた。runコマンドはDockerコンテナを作成するコマンドで毎回新規にubuntuを作成していたためであった。
試しにコンテナのリストを見てみると

```
$docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                                    
22ea90c85eca        ubuntu              "/bin/bash"         12 minutes ago      Exited (127) 7 seconds ago                      
9c47d492bbdc        ubuntu              "/bin/bash"         2 days ago          Exited (0) 12 minutes ago                       
79af5ad1880b        ubuntu              "/bin/bash"         3 days ago          Exited (0) 2 days ago                           
0834869a6065        ubuntu              "bash"              4 days ago          Exited (255) 4 days ago                         
283f0f3ec454        ubuntu              "bash"              4 days ago          Exited (0) 4 days ago                           
d4d2ccefa838        ubuntu              "bash"              6 days ago          Exited (0) 4 days ago                           
```
となっていた。前回起動したコンテナを再度起動するには

```
docker start -i コンテナIDか名前
```
でできた。
この投稿を参考にしました。
https://qiita.com/tifa2chan/items/e9aa408244687a63a0ae


# バグっぽい動作

```
# dmesg
dmesg: read kernel buffer failed: Operation not permitted
```
と出る。このメッセージでググったら
https://myn.meganecco.org/1481313000.html
などのブログが見つかった。
[Ethereum]とりあえずterminalからweb3触ってみる

# 必要な環境

node.js
web3.js

# テストネット環境を作る

GUIとして使えるGanacheを使う

https://truffleframework.com/ganache

<img width="1677" alt="スクリーンショット 2018-11-27 23.43.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/77198/cf60792a-ab37-677b-c62d-fe7efaea5262.png">

# web3.jsをインストール

```
$npm install web3 
```

# web3.jsをインストール

```
$npm install web3 
```

# web3につなぐ

```
node
var Web3 = require('web3')
var web3 = new Web3('http://127.0.0.1:7545')
```

# テストアカウントのETH量を見てみる

```
web3.eth.getBalance(
    '0xc78d2B19d0C245B8806C4d06BB4F55877fcFB8F2',(err, wei) => {
        balance = web3.utils.fromWei(wei, 'ether')
    }
)
```

```
balance
>100
```

見れた
get_categories、get_termsでhide_empty=0でも空のタームが出力されなかったときの覚書

[User Access Manager](https://ja.wordpress.org/plugins/user-access-manager/)プラグインが入っている場合、その影響かもしれない。

管理画面＞UAM＞設定＞Taxonomies settings

1. 空でも出力しないカテゴリー・カスタムタクソノミーを選択
2. Hide emptyを「いいえ」にして「設定を更新」をクリック
3. get_categories、get_termsのパラメータでhide_empty=0を指定する

参考：[categories \- hide\_empty property not working when using get\_terms \- WordPress Development Stack Exchange](https://wordpress.stackexchange.com/questions/279016/hide-empty-property-not-working-when-using-get-terms)
意義テストを使用してWhatsapp 2019新バージョン

アプリケーショ Whatsapp2019後のWhatsapp最新バージョンとして瞬時に表示されます。 時間の経過とともに、Whatsappは常に電源を固定していました。 ユーザーがより簡単にそれを適用するように。 <a href='https://softalead.com/download-whatsapp-2019-new-version.html'>Whatsapp2019新バージョン</a>確かに、より収益性の高いユーザーになります。

理由の人々の一部は、この1つのアプリケーションが提供する機能のためにWhatsappを使用するのが好きです。 Whatsappは、最大250のメンバーを収容することができるグループ会談などの機能を提供します。 のグループ全員で共有できる画像、動画その他の文書ファイルです。 Whatsapp最新また、それは全体としてのグループの画像を記述する機能であるグループの機能の説明を発生させます。 この説明では、最大512文字の説明を書くことができます。

<a href='https://softalead.com/download-whatsapp-2019-new-version.html'>Whatsapp2019</a>アプリのチャットのお気に入りは、ビデオ通話の機能のためです。 この機能はよりよい他の同様のアプリです。 また、Whatsappに特別なものを多く獲得のチケット利用無料なしデータ数のオンラインの世界です。 多くのベンダーにモバイルネットワークには、パケットデータの無料チャットWhatsappに適用します。 このメソッドは、特に貧しいクォータされているときに非常に有益です。


<A href='https://softalead.com/whatsapp-2019-apk.html'>ダウンロードWhatsapp2019年Apk Android</a>を希望される方は簡単にダウンロードすることの出店申込のスマートフォンなどがあります。 あなただけのGoogleや他の検索エンジンでアプリ名を入力して行うことができます。 この後も、アプリをダウンロードするためのリンクが表示されます。 アプリをダウンロードする必要がありますが、すぐにインストールで使用Whatsappます。
Windowsコンテキストメニューに「Visual Studio Codeで開く」を追加する

# Windowsコンテキストメニューに「Visual Studio Codeで開く」を追加する
## やりたいこと
右クリック（コンテキストメニューを開く）した際に、Visual Studio Codeで開く「VSCode Here」を追加すること。
具体的には、下記３つのケースで表示させる。


| ケース | 実現したいこと                                                           |
| ------ | ------------------------------------------------------------------------ |
| 1      | 任意ファイルのアイコンを右クリックした場合に表示させる                   |
| 2      | エクスプローラーで開いているフォルダを右クリックした場合に表示させる     |
| 3      | ファイルフォルダ／ディレクトリのアイコンを右クリックした場合に表示させる |

---
## やったこと
Windowsのレジストリエディタから、設定を追加（レジストリを書き換え）します。
### 1. レジストリエディタを起動
[Win + R]キーを押下して、`regedit`と入力します
### 2. キーを追加する場所へ移動
調査したところ、コンテキストメニューを表示させる条件によって、追加する場所は決まっているようだ。  
上記の「やりたいこと」で挙げたケースを実現する場合は、下記の場所にキーを登録する。  

| ケース | レジストリキー                                              |
| ------ | ----------------------------------------------------------- |
| 1      | コンピューター\HKEY_CLASSES_ROOT\*\shell                    |
| 2      | コンピューター\HKEY_CLASSES_ROOT\Directory\Background\shell |
| 3      | コンピューター\HKEY_CLASSES_ROOT\Directory\shell            |

上記の`shell`キー配下に、次のツリー構造になるようにキーを登録していきます。

```
shell
    L VSCode
        L command
```

### 3. キーの登録
キーを登録していきます。  
キー`VScode`には次の設定を追加します。

| 名前   | 種類   | データ                                      |
| ------ | ------ | ------------------------------------------- |
| (既定) | REG_SZ | VSCodeで開く(C)                             |
| Icon   | REG_SZ | C:\Program Files\Microsoft VS Code\Code.exe |
*Iconはコンテキストメニューにアイコンを表示させるための設定です。設定は任意です。

キー`command`には次の設定を追加します。

| 名前   | 種類   | データ                                      |
| ------ | ------ | ------------------------------------------- |
| (既定) | REG_SZ | C:\Program Files\Microsoft VS Code\Code.exe |

---
### 4. 動作確認
上記の３ケースそれぞれうまくいったみたいです。Goodです。

## 参考
- [ASCII] http://ascii.jp/elem/000/000/953/953807/
【Ruby on Rails】リンクパスの指定方法について【プログラミング学習91日目】

# はじめに
- プログラミング学習を開始して3ヶ月の初学者が、Ruby on Railsチュートリアルに取り組んでいる中で疑問に思った点を言語化し、疑問点を解消、および知識を定着させることを目的とした記事です。
- 今回は`link_to`ヘルパー、`url_for`ヘルパー、`redirect_to`メソッドなどで指定するパス(URL)では様々な記述方法があるものの、それらの使い分け方などについてあまり理解できていないと感じていたため、調査・まとめをすることとしました。

# 前提条件
- 今回は例として`$ rails g scaffold Entry title:string body:text`とした場合を想定しています。
- ルーティングには`resources :entries`を設定し、`$ rails routes`では以下のように示されているとします。

```
    Prefix    Verb    URI Pattern                   Controller#Action
    entries    GET     /entries(.:format)             entries#index
               POST    /entries(.:format)             entries#create
  new_entry    GET     /entries/new(.:format)         entries#new
 edit_entry    GET     /entries/:id/edit(.:format)    entries#edit
      entry    GET     /entries/:id(.:format)         entries#show
              PATCH    /entries/:id(.:format)         entries#update
               PUT     /entries/:id(.:format)         entries#update
             DELETE    /entries/:id(.:format)         entries#destroy

```

# Railsにおけるリンクパスの指定方法

- この3ヶ月のRails学習（Progate, ドットインストール, Railsチュートリアル）の過程で出会ったリンクパスの種類は以下3パターンです。

``` 
1. URI Pattern
2. Prefix_path
3. Prefix_url
```

- これらの違いについて調べた内容を下記します。

## 1. URI Patternによるパス指定
- `<%= link_to @entries.title, '/entries' %>`のような形となります。
- テスト用の、`test ~ do ... end` の中ではこの記述方法での指定が必要とのことです。
- Progateではこの記述法のみ取り扱っていました。
- Progateから入った私としては、これが最も読みやすく馴染みやすいと感じているのですが、ドットインストールやRailsチュートリアルでは基本的にこの形での記述はしていませんでした。
- 簡単なヒアリングをした結果、この記述方法は実務ではあまり使われていないようです（違っていたらすみません。）
- なぜあまり使われていないのかについて理由が分かる方がいらっしゃいましたらご教示いただければ幸いです。
    - 理由についてコメントをいただきました。詳しくは下記コメントをご参照ください。（@scivolaさん、ありがとうございました。）

## 2. Prefix_pathによるパス指定
- `<%= link_to @entries.title, entries_path %>`のような形となります。
- リソースフルなルーティングを作成すると、利用できるようになるヘルパーです。
- 例えば、`entries_path`は`/entries`を返し、`new_entries_path`は`/entries/new`を返します。
- `test ~ do ... end`の中ではこの記述方法での指定はNGとのことです。
- 体感ですが、ドットインストールやRailsチュートリアルではこの形が最も使用されていた気がします。


## 3. Prefix_urlによるパス指定
- `<%= link_to @entries.title, entries_url %>`のような形となります。
- `_url`は、`_path`の前に現在のホスト名、ポート番号、パスのプレフィックスが追加されている点が異なります。
    - つまり、`http://www.example.com/entries`と完全なURLの文字列を返すという意味です。
- `redirect_to`では`_url`を使用し、それ以外は`_path`を使うとのこと。
    - コメントをいただき、`_url`は`redirect_to`のとき限定ではなく、使用する際の本質的な考え方として「`https://`で始まるフルのURLが必要かどうか」という点が重要となってくるようです。（@scivolaさん、ありがとうございました。）
- `test ~ do ... end`の中ではこの記述方法での指定はNGとのことです。

# まとめ
- Railsにおける下記のリンクパスの指定法についてまとめた。
    - 1. `URI Pattern`
    - 2. `Prefix_path`
    - 3. `Prefix_url`
- それぞれの使い分けは以下の通りであった。
    - `test ~ do...end`中では1.を使用
    - `https://`で始まるフルのURLが必要な場面では3.を使用
    - その他の場合は2.を使用

# 参考URL
- [Rails のルーティング](https://railsguides.jp/routing.html)
- [_pathメソッドと_urlメソッドの使い分け](https://qiita.com/higeaaa/items/df8feaa5b6f12e13fb6f)


# (自分のメモ用) 合わせて読んでおきたい関連URL
- [【Rails】link_to / url_forなどリンク関連のビューヘルパーまとめ](https://qiita.com/nao_u/items/9197e30cc7faf1f80199)
- [railsのrenderとredirect_toの違い](https://qiita.com/1ulce/items/282cccba1e44158489c8)
WLinuxでdocker動かすまでに困ったこと

# これは何？
ここまできたらせっかくだからWLinuxでもdocker動かせるようにするか…と思って、ハマったポイントとか、ハマったというほどでもないけど調べたポイントです。

wlinuxはdebianベースらしいので、基本は↓どおりでいけるかなと思ってやりました。
[WSLでdockerのインストールからdocker-composeまで動かす
](https://qiita.com/tettsu__/items/85c96850d187e4386c24)

# 困ったこと

## lsb_releaseが無い

### ハマったところ

```
sudo -E add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
```

### エラー内容

```
lsb_release: command not found 
```

### 暫定対処
良く調べたら、いつのタイミングからか`lsb_release`から`lsb-release`に名称が変更になっていたらしい。
新しい名称でちゃんとインストールしてあげればOK。

```
sudo apt-get install lsb-release
```

ubuntu on wslでやった時は正常終了したので、OSやパッケージ管理ソフトのバージョン等によって旧名でも解釈してくれたりしてくれなかったりするのだと思う。

## add-apt-repositoryが無い

### ハマったところ(上と同じ)

```
sudo -E add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
```

### エラー内容

```
aptsources.distro.NoDistroTemplateException: Error: could not find a distribution template for WLinux/buster
```

### 暫定対処

```
sudo apt-get install add-apt-repository
```

をやっても、この名称で見つからないとのエラー。
`software-properties-common`というパッケージが必要とのこと。

* [Ubuntu Linuxで、add-apt-repositoryしようとして「コマンドがない」って言われたら](https://kazuhira-r.hatenablog.com/entry/20160116/1452933387)

```
sudo apt-get install software-properties-common
sudo apt-get update
```

でも、エラーは変わらず。

### 情報収集

似たようなissueを見てみる。
https://github.com/WhitewaterFoundry/WLinux/issues/157

>add-apt-repository and apt-key seem to give up a lot on WSL, 

とあり、

>add-apt-repositoryとapt-keyはWSLでは大部分を諦めているようで、

と読み取れるので、完全に無理かどうかはともかく、`add-apt-repository`はWSL上では安定とは思わない方がいいのかもしれない。

## 無理そうなので方針転換

別の方法は無いのかなと探して、↓を参考にさせて頂きました。

* [Ubuntuにdockerをインストールする
](https://qiita.com/tkyonezu/items/0f6da57eb2d823d2611d)

「スクリプトでのインストール」で、なんとかなりました。

```
curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
```

稼働確認。

```
docker --version
Docker version 18.09.0, build 4d60db4
```

これでdockerデーモンはdocker for windowsのものを使えば、WLinuxからでもdockerが操作可能になると思います。

# 所感

* いろんな環境で試してみましたが、Win10でdocker for windowsとpowerShellを使うのが一番ストレス無いかな、と思いました。vi代わりにはVSCodeで良いと思う。
KotlinでVPNを判定する方法

AndroidStudio3.2.1 Kotlinでの挙動です。

VPN接続の場合は、 Log.i("VPN", "VPN" )の分岐に入ります。

参考ソース

https://developer.android.com/reference/android/net/NetworkCapabilities
https://stackoverflow.com/questions/29419175/networkinfo-for-vpn-on-android-api-21

```kotlin
import android.util.Log
import android.os.Bundle
import android.content.Context
import android.annotation.SuppressLint
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.support.v7.app.AppCompatActivity


class MainActivity : AppCompatActivity() {

    @SuppressLint("MissingPermission")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var cm = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val networks = cm.allNetworks

        for (i in networks.indices) {
            val caps = cm.getNetworkCapabilities(networks[i])
            if (caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
                Log.i("VPN", "VPN" )
            } else {
                Log.i("NOTVPN", "NOTVPN" )
            }
        }
    }
}
```
RHNに登録したRHELでのyumのproxy関連設定の変更方法

# なぜこれを書いたか？
- RHELサーバー を RHN に登録してから数か月が経過し、すでに subscription-manager の設定などは綺麗さっぱり忘れていた。
- そしてproxyサーバーのIPアドレスが変わった際に、誤って /etc/yum.repos.d/redhat.repo を編集した。
- しかし変更したはずのproxyの設定が反映されず、また何故か書いたはずの設定が元に戻ってしまってちょっと困った（redhat.repo ファイルの冒頭には「このファイルを直接編集するな」と書いてある。）。
- 私の様な忘れんぼが居るとは思えないが、自分はまた忘れるかもしれないので。

# 環境
- RHEL 6.5 | 7.1 にて確認済み。
- proxy経由でインターネットに接続している。
- 過去に Red Hat Network に登録済み。

# やりたいこと
上記又は類似の環境下で、次の何れか、又は全てが変更された際に、yumが正しく動作する様に、proxy関連の設定を変更して反映したい。

- http proxyサーバーのホスト名、又はIPアドレス。
- http proxyサーバーのポート番号
- 認証proxyのユーザー名
- 認証proxyのパスワード

# 作業の概要
1. **sudo** か **su** で作業する。
2. 以下の **手順1-a** か **手順1-b** の何れか一方をやる。
3. 次に **手順2** をやる。
4. 最後に **確認** をして終わり。

# 手順1-a
/etc/rhsm/rhsm.conf ファイルをテキストエディタで直接編集し、次の項目を設定する。

```rhsm.conf
proxy_hostname =<PROXY_SERVER_NAME or IP-Addr>
proxy_port =<PORT_NUMBER>
proxy_user =<USER_NAME>
proxy_password =<PASSWORD>
```

- <>の部分は各自の設定に置き換える。
- proxy_user と proxy_password はproxy認証が必要な場合のみに記述する。


# 手順1-b
subscription-manager コマンドを介して /etc/rhsm/rhsm.conf の内容を書き換える。

```
[root@localhost ~]# /usr/sbin/subscription-manager config --server.proxy_hostname=<PROXY_SERVER_NAME or IP-Addr> --server.proxy_port=<PORT_NUMBER> --server.proxy_user=<USER_NAME> --server.proxy_password=<PASSWORD>
```

- <>の部分は各自の設定に置き換える。
- --server.proxy_user と --server.proxy_password はproxy認証が必要な場合のみに記述する。

# 手順2
適当な yum コマンドを発行すると、/etc/yum.repos.d/redhat.repo に設定が反映される。

```
[root@localhost ~]# /usr/sbin/yum repolist
```

# 確認
/etc/yum.repos.d/redhat.repo ファイルを less 等で見ると、上記で行った作業が反映されている事がわかる。
【T-Pot 】Cowrieログから実行されたコマンドの集計

##やりたいこと
T-PotのCowrieログから、SSH接続に成功した攻撃者がどのようなコマンドを実行してどんな情報を引き出しているのか等集計してみたい。

##事前情報
###保存先
デフォルトでは、データの格納先は以下のパスになっている。カスタマイズされている方は読み替えてほしい。
/data/cowrie/log/cowrie-textlog.log

※過去のものは圧縮されている
/data/cowrie/log/cowrie-textlog.log.1.gz

###データ形式
ログの中を見てみると、だいたいが以下のようなログで埋め尽くされていることがわかる。

```shell-session
2018-11-26T18:39:51.623555Z New connection: *.*.*.*:52904 (172.24.0.2:2222) [session: 24f914cda400]
2018-11-26T18:39:51.818871Z Remote SSH version: SSH-2.0-Granados-1.0
2018-11-26T18:39:51.821196Z Connection lost after 0 seconds
```

この中に稀にこのような実行されたコマンドのログが残っている

```shell-session
2018-11-27T12:58:40.796273Z Command found: head -n 1
2018-11-27T12:58:40.797353Z Command found: grep name
```

##集計の表示
このログを集計してみる。
圧縮された過去のファイルがたくさんあるので、そちらを対象にしてみる。

```shell-session
zcat cowrie-textlog.*gz | grep "Command found" | cut -d ' ' -f 4- | sort | uniq -c | sort -rn | head -10
    540 mkdir /tmp/.xs/
    167 cat /proc/cpuinfo
    114 grep name
    108 chmod 777 /tmp/.xs/test.mod
    108 chmod 777 /tmp/.xs/daemon.mips.mod
    108 chmod 777 /tmp/.xs/daemon.mipsel.mod
    108 chmod 777 /tmp/.xs/daemon.i686.mod
    108 chmod 777 /tmp/.xs/daemon.armv4l.mod
    108 cat > /tmp/.xs/test.mod
    108 cat > /tmp/.xs/daemon.mips.mod
```

お客様はフォルダ作成がお好きなようで。

ちなみに引数とオプションを無視した場合は以下のようになった。

```shell-session
zcat cowrie-textlog.*gz | grep "Command found" | cut -d ' ' -f 4 | sort | uniq -c | sort -rn | head -10
    724 cat
    546 chmod
    540 mkdir
    250 grep
    129 export
    123 uname
    116 head
    100 free
     86 unset
     65 ps
```

この結果はなんとなくわかる気がする。
そしてフォルダ作成大好きな方はもしかするとお一人様なのかもしれない。

おわり
zip関数について

##背景
kaggleのサッカーのデータセットに対してのタプルを作成する方法を模索していた際にzip関数を使用しました。
##zip関数について
zip関数は複数のリストを抽出したり、タプルを作成します。

```python:zip.py

a = [1, 2, 3, 4]
b = [2, 4, 6, 8]
c = []
for i in zip(a, b):
    c.append(i)
print(c)
```

`c = [(1,2), (2,3), (3,4)]`

以下のように複数のリストのそれぞれの要素の抽出に成功しました！！
また、タプルを作成する場合は、以下のようにします！！
`tuple(c)
c = ((1, 2), (2, 3), (3, 4)) `
Refactoring第2版のサンプルコードをTypeScriptで実習する：part.0 Starting Point

Martin Fowler先生の名著『Refactoring』の第2版が、先日発売されました。

Refactoring第2版は、サンプルコードがJavaScriptになっているということもあり、普段JSを書くことが多い自分としては、「Fowler先生はどんなJSを書くのだろう」と気になっていました。

サンプルコードをそのまま写経するのも芸がないので、TypeScriptの学習も兼ね、サンプルコードをTypeScriptに置き換えてやっていくことにします。

JSのコードはTypeScriptのコードとしても有効なので、サボろうと思えばいくらでもサボれるのですが、できるだけ型を付けながらやっていきたいと思います。

なお、本記事のコードは下記リポジトリでも公開しています。
https://github.com/ryo-utsunomiya/refactoring-2nd-ts

何回かに分けて書く予定ですが、まずはセットアップと最初のコード。

## セットアップ

開発用ディレクトリを作って、必要そうなものを入れます。

```bash
# npm設定を初期化
$ yarn init -y

# tsc(TypeScriptコンパイラ)
$ yarn add -D typescript

# .tsを食わせると即実行できる便利コマンド
$ yarn add -D ts-node

# Node.js用型定義
$ yarn add -D @types/node
```

package.jsonはこんな感じで

```package.json
{
  "name": "refactoring-2nd-ts",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "build": "tsc",
    "watch": "tsc --watch"
  },
  "devDependencies": {
    "@types/node": "^10.12.10",
    "ts-node": "^7.0.1",
    "typescript": "^3.1.6"
  }
}
```

tsconfig.jsonはこんな感じ(nodeでの実行を想定)

```tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2018",
    "sourceMap": true,
    "types": ["node"],
    "resolveJsonModule": true
  },
  "exclude": ["node_modules"]
}
```

できたら適当に実行してみると良いと思います。

```bash
$ echo 'console.log("hello")' > hello.ts
$ yarn ts-node hello.ts
...
hello
```

以上でセットアップ完了。

## Starting Point

次に、最初のサンプルコードを動かしてみます。

invoices.jsonとplays.jsonは省略。

最初の時点での、領収書発行関数(statement)は以下のようになっています。

```statement.ts
interface Performance {
  playID: string;
  audience: number;
}

interface Invoice {
  customer: string;
  performances: Array<Performance>;
}

interface Play {
  name: string;
  type: string;
}
export function statement(
  invoice: Invoice,
  plays: { [playID: string]: Play }
): string {
  // 関数の中身は書籍と同じなので省略
}
```

これだけだと動作確認ができないので、動作確認用のファイルを別途用意します。

```index.ts
import { statement } from "./statement";
import * as invoices from "./invoices.json";
import * as plays from "./plays.json";

invoices.forEach(invoice => {
  console.log(statement(invoice, plays));
});
```

実行してみると、以下のように請求書が出力されることがわかります。

```bash
$ yarn ts-node index.ts
...
Statement for BigCo
  Hamlet: $650.00 (55 seats)
  As You Like It: $580.00 (35 seats)
  Othello: $500.00 (40 seats)
Amount owed is $1,730.00
You earned 47 credits
```

ここをStarting Pointにして、リファクタリングを進めていきたいと思います。
pythonへのCCXT導入について。

仮想通貨用のBOTを作ろうかと思い、最初にCCXTというライブラリを

```ターミナル
sudo install ccxt'
```

とコマンドを打ったのですが、下記のようなエラーが出てしまいました。

```エラー
Cannot uninstall 'urllib3'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.
```

解決方法ありましたら伝授お願いしたいです。

環境　
cloud9
python 3.4.3
【便利】mkdirコマンドで複数並列に複階層ディレクトリを作る。

#コマンドの指定でカッコ { } を使うと便利
mkdirの「あっそういえばそうか」な使い方
ディレクトリを複層作りたい時に使うオプション `-p` ですが、ディレクトリを並列で複層に一括作成したい時もありますね。
そんな時は、 `{}で「,」区切り` で複数のディレクトリを一度に作成できてしまうのです。

```
# mkdir -p {dir1/dir1-1,dir2/dir2-1/dir2-2,dir3/dir3-1}
```

```
bash-4.2# pwd
/work
bash-4.2#
bash-4.2# tree
.
|-- list
|-- result
|-- sample.rb
|-- test1.rb
`-- test1.rb_bk
0 directories, 5 files
bash-4.2#
bash-4.2#  mkdir -p {a/1,b/2}
bash-4.2#
bash-4.2# tree
.
|-- a
|   `-- 1
|-- b
|   `-- 2
|-- list
|-- result
|-- sample.rb
|-- test1.rb
`-- test1.rb_bk

4 directories, 5 files
```

便利です!!
これで少し効率化。

>「0.1秒でも早く帰ってアニメを見る。
　時間に対するコミットは、世界で戦うアスリートもエンジニアも、同じなんじゃないですか！？」

#一応 man
https://linux.die.net/man/1/mkdir
汎用分析環境の構築(Jupyter containerをAnsibleで構築)

# 背景

前回途中でほったらかしとなっていた汎用分析環境の構築を進める。
今回やったことは以下。

* jupyter containerを利用したdockerベースのjupyter notebook環境を作る
* dockerのデータ永続領域をNFS経由とする
* jupyter notebookのフロントエンドをnginxでリバースプロキシ化する
* 構築をansible playbook化する

# 構築した環境

## 前回まで

本記事は以下の記事の続きです。

https://qiita.com/ken223/items/2b3d87edd952bae1b4ba

## 今回追加した構成

前回の構成図は以下の通りです。

![前回の構成図]
(https://camo.qiitausercontent.com/832b6361d848aa852fdf5565fc47bfdffcdeeb40/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3239383037382f38363964333833372d316161652d333339642d623439322d3633623934313133343266652e706e67)

---

今回の構成図。色がついている部分が追加分。

![for_testing_r2.png](https://qiita-image-store.s3.amazonaws.com/0/298078/61aa1b3d-2a98-66ca-66b5-71362d7d20c6.png)

構築に利用したansible資材は以下にpushしてあります。(前回から更新)

https://github.com/ken223/ansible-docker-analyzer


# 構築方法

基本的にはmaster側からansibleを叩けば終わり。
jupyter containerのplaybookはこんな感じ。

```roles/container/tasks/main.yml
- name: Install worker package by apt
  apt:
    name: python3-pip
    state: present

- name: Install docker-py
  pip:
    name: "docker"
    state: present

- name: Create container jupyter scipy-notebook
  docker_container:
    name: scipy-notebook
    hostname: scipy-notebook_001
    image: jupyter/scipy-notebook:latest
    detach: yes
    auto_remove: yes
    ports:
      - "10000:8888"
    volumes:
      - /mnt/work:/home/jovyan/work
```

起動後、クライアントPCから以下URLにアクセスすると、jupyter notebookの認証画面が表示される

```
http://192.168.32.10/
```

![スクリーンショット (14).png](https://qiita-image-store.s3.amazonaws.com/0/298078/b691ddd8-cd16-dd09-c272-c8c594567c50.png)


```
vagrant@worker001:~$ docker ps -a
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                     NAMES
34e624124079        jupyter/scipy-notebook:latest   "tini -g -- start-no…"   5 seconds ago       Up 5 seconds        0.0.0.0:10000->8888/tcp   scipy-notebook
vagrant@worker001:~$ docker exec -it scipy-notebook /bin/bash
jovyan@scipy-notebook_001:~$ jupyter notebook list
Currently running servers:
http://0.0.0.0:8888/?token=c51fdbe9ed6774a85d89e466fda819729705084f0bec2d67 :: /home/jovyan
jovyan@scipy-notebook_001:~$
```

token=の後の文字列(c51～2d67)までをコピーして、Password or tokenのテキストボックスに入れて、ログイン。
あとはいつものjupyter notebookと同じ使い方ができる。

![スクリーンショット (15).png](https://qiita-image-store.s3.amazonaws.com/0/298078/1e0b2d10-ca19-da87-e7a7-94291e46351c.png)

# 残課題

まだまだやり残しが多い。。。

* ansible playbookのパラメータ化
* 複数ユーザ、複数環境を考慮したディレクトリ設計
* ログの集約

次回以降の宿題。
CircleCI から GCR に Push できなくなった時（2018/11現在）

# CircleCI から GCR への Push ができなくなった時の対処

今まで動いていた CirclrCI から GCR(Google Container Registry) への Push が、ある日突然失敗することが・・・
あったので、ちょっと対応してみます。

## こんなの発見

とりあえずここから。

[gcloud docker は Docker 18.03 以降をサポートしないらしい。](https://blog.dnpp.org/gcloud_docker_18_03)

それを拝見しながら試行錯誤してるうちに、こんな感じのメッセージが出てきました。

```
unauthorized: You don't have the needed permissions to perform this operation, and you may have invalid credentials. To authenticate your request, follow the steps in: https://cloud.google.com/container-registry/docs/advanced-authentication
```

[Authentication Methods](https://cloud.google.com/container-registry/docs/advanced-authentication)

要は、`docker-credential-gcr` 入れろってことですよね。

## 結局やったこと

`gcloud auth` と `deploy` 以外は適当です。

```"./.circleci/config.yml"
version: '2'
jobs:
  build:
    working_directory: ~/work
    machine: true
    steps:
      - checkout
      - run:
          name: check docker version
          command: |
            docker version
            docker-compose version
      - run:
          name: get dependencies
          command: |
            make dep
      - run:
          name: generate clients
          command: |
            make generate-clients
      - run:
          name: build docker
          command: |
            make build
            docker-compose up -d
      - run:
          name: gcloud auth
          command: |
            ./gcloud.sh
      - deploy:
          command: |
            ./docker-push.sh latest
workflows:
  version: 2
  workflow:
    jobs:
        - build:
            context: <コンテキスト名>
```

- credential を取得する部分では、`docker-credential-gcr` を使うのが肝です。
- `docker-credential-gcr` を入れたそのままだと、Path がダメと言われるので、Path が通ってる場所にコピーします。

```"./gcloud.sh"
#!/bin/bash

echo $<Environment Variables name> | base64 --decode --ignore-garbage > ${HOME}/gcloud-service-key.json
sudo /opt/google-cloud-sdk/bin/gcloud --quiet components update
sudo /opt/google-cloud-sdk/bin/gcloud components install docker-credential-gcr
sudo cp -p /opt/google-cloud-sdk/bin/docker-credential-gcr /usr/bin/
sudo /opt/google-cloud-sdk/bin/gcloud auth activate-service-account --key-file ${HOME}/gcloud-service-key.json
sudo /usr/bin/docker-credential-gcr configure-docker
```

- 実際プッシュを行う部分では、gcloud コマンドではなく、docker コマンドを使用するようにしました。

```"./docker-push.sh"
#!/bin/bash

if [ $# -ne 1 ]; then
  echo "指定された引数は$#個です。" 1>&2
  echo "実行するには1個の引数が必要です。" 1>&2
  exit 1
fi

container_tag=${1}
dest=asia.gcr.io/<project name>/<repository name>

docker-compose build
sudo docker tag <repository name>:latest ${dest}:${container_tag}
sudo docker push ${dest}:${container_tag}
```
カスタマイズしたスタート画面から消えたタイルを復活させる方法

[Windows10 Proでスタート画面とタスクバーをカスタマイズする方法](https://qiita.com/a_o_i_k_o/items/d333a49528c9481ba139)
でカスタマイズ→新規プロファイル作成を繰り返していると、たまにスタート画面の**IEのタイル**だけが消えるというバグ？がありました。

## 検証環境 ##
Windows 10 April 2018 Update (バージョン1803)

## 消えたIE ##
![nai02.png](https://qiita-image-store.s3.amazonaws.com/0/143735/7c44d7fb-9870-16dd-6ef7-18671917fb4c.png)


## 発生条件 ##
以下の条件で毎回発生

- ドメインユーザー　かつ 新規プロファイル

※既存のドメインユーザープロファイルにGPOを設定するとIEも出てきます（謎仕様）
## 復活のさせ方 ##
1. デスクトップにショートカットを作成
![コメント 2018-11-27 133514.jpg](https://qiita-image-store.s3.amazonaws.com/0/143735/48d40fe4-dba7-b6bd-d148-2c70cf3ae05c.jpeg)

2. C:\ProgramData\Microsoft\Windows\Start Menu\Programs 直下にショートカットを移動させる
![aru0.png](https://qiita-image-store.s3.amazonaws.com/0/143735/2af0c95e-baa9-8451-25b7-cdca861d4dbc.png)

3. 新規ユーザーでログインすると、消えたアイコンが復活します！
RailsのフォームでのAjax通信について

#はじめに
エンジニア1年生です。
日々の学びのメモとしてコツコツと記事を書こうと思っています。
今回はRailsでのAjax通信について書いていきます。

#Ajaxとは？
Asynchronous JavaScript XMLを略したもので
Javascriptを使用してサーバーと非同期通信が出来る技術です。

#非同期通信？？
通常のweb通信は以下の流れとなります。
`１、リンク等をクリック
２、ブラウザからサーバーにリクエストを投げる
３、サーバーからファイルがレスポンスが返される
４、ブラウザがファイルを読み込み画面が表示される`

これが**同期通信**です。
上記の処理が行われる際はサーバーと通信中のため他の処理を行うことが出来ません、、、

サーバーと通信中でも他の処理を行うことが**非同期通信**です。
google mapやtwitterがページ遷移を行わずに快適に使用出来るのは非同期通信を行っているからです。

#具体例
railsのフォームを使用して具体的な使い方を説明します。
例として好きな食べ物をフォームから送信し登録した際に別ページに遷移せず
アラートを表示するコードを書きます。

##フォームの記述
```html:food.html.erb
  <%= form_for(@food, data: { remote: true }) do |f| %>
    <%= f.text_field :food %>
    <%= f.submit('送信') %>
  <% end %>
```
ポイントはremoto:trueを設定していることです。
formにremoto:trueを設定することにより画面遷移は行わずに
リクエストだけを投げてくれます。

##コントローラーの記述
```rb:foods_controller.rb
def new
  @food = Food.new
end

def create
  @favorite_food = Food.new(food_form_params)
  
  ActiveRecord::Base.transaction do
    unless @favorite_food.save
      raise ActiveRecord::Rollback
    end
  end
  
  if @favorite_food.errors.any?
    @errors = @favorite_food.errors.full_messages
    render json: @errors, status: 422
  else
    render json: {}, status: 200
  end
end

private
def food_form_params
  params.require(:food).permit(:food)
end
```

ポイントはrender部分でjsonとstatusを返していることです
エラーの場合はjsonにエラーメッセージ、statusに422をセット
正常の場合はstatusに200をセット

##jQueryの記述
```javascript:food.js

$(function(){
  $("#new_food").on("ajax:error", function(event, jqXHR, ajaxSettings, thrownError) {
      var data = jqXHR.responseJSON;
              alert(data);
  });
});

$(function(){
  $("#new_food").on("ajax:success", function(event, xhr, settings) {　
              alert("登録が完了しました。");
  });
});
```
ポイントはajax:error,ajax:successをトリガーに処理を記述していることです。
statusが200の場合は"ajax:success"、statusが422の場合は"ajax:error"が発火します。
OpenModelicaで伝熱流動　SimpleFrictionのモデル

前回使ってみたSimpleFrictionに使われていた見慣れない摩擦損失を算出する式を他の式と比べてみました。
条件は以下の通り。
![condition.png](https://qiita-image-store.s3.amazonaws.com/0/317126/f06a8485-7e14-a43e-e380-fa3992a28b08.png)
まず、この条件で、層流の摩擦損失係数λをハーゲン・ポアズイユの式
λ=64Re
Re=udρ/μ
で算出し、乱流の摩擦損失係数λをブラジウスの式
λ=4×0.0791Re^-0.25
で算出します。
層流と乱流を切り替える遷移Re数を2000としました。
横軸に体積流量、縦軸に圧力損失をとって、SimpleFrictionで算出した圧力損失と比べてみました。
![dp.png](https://qiita-image-store.s3.amazonaws.com/0/317126/87770839-3449-3ab8-b1c2-c5102ff90527.png)
SimpleFrictionのdpLaminarはハーゲン・ポアズイユの式で出した体積流量1.5e-4[m3/s](Re=1910)の圧力損失を、dpNominalにはブラジウスの式で出した体積流量1.5e-3[m3/s]（Re=19100)の圧力損失を与えています。
層流域は、ハーゲン・ポアズイユ、SimpleFrictionともに体積流量に比例していますので、以下の層流域を拡大したグラフの通り一致しますが、乱流域では差が生じます。
![dp_lam.png](https://qiita-image-store.s3.amazonaws.com/0/317126/04831f38-19a1-d3fe-59f7-dce986e2bffd.png)
この差をどう見るかは場合によりますが、層流域と乱流域の圧力損失のデータがあって、しかもそのデータをそのまま使う(流路寸法を全く変えない)ことはほぼ無いと思いますので、SimpleFrictionとそれを用いるIsolatedPipeは、伝熱流動のモデルには使いにくいのではと感じました。
Ubuntu 16.04で英語配列キーボードを用いて英語/日本語入力の切り替えをAlt+`に設定する

#UbuntuでもAlt+`を入力ソースの切り替えキーに設定したい
##重複ショートカットの削除
一般的にWindowsマシンで英語配列キーボードを使う際はAlt+`が全角/半角キーの役割を果たしますがUbuntuでこれを
やろうと思うとすでに重複しているショートカットが設定されておりデフォルトのままではウインドウの切り替えショートカットが優先して実行されてしまいます。

そこでCompiz Config 設定マネージャーをインストールして設定を弄ります

```shell
$ sudo apt install compizconfig-settings-manager
```

これでインストールができるはずです
![Screenshot from 2018-11-27 21-17-20.png](https://qiita-image-store.s3.amazonaws.com/0/232732/2081ff89-11d4-8d0a-4e3a-8f85f0597745.png)
これを起動して


![Screenshot from 2018-11-27 21-20-16.png](https://qiita-image-store.s3.amazonaws.com/0/232732/9a212645-a10b-6899-6925-a21f68f10d5d.png)
このような画面が出ますがOKします

次にデスクトップ>Ubuntu Unity Pluginにチェックを入れてからクリックします
![Screenshot from 2018-11-27 21-22-04.png](https://qiita-image-store.s3.amazonaws.com/0/232732/809c1530-8e31-fd86-be7e-de0192108ae4.png)

次に上から５番目にある "Key to flip through windows in the Switcher"をクリックします
![Screenshot from 2018-11-27 21-22-53.png](https://qiita-image-store.s3.amazonaws.com/0/232732/c354d426-265f-c433-19f0-7dc9a46d42bc.png)

ここでポイントなのは既に無効となっていますがなぜか実際には有効なので改めて適当なキーを入れてから一旦有効にしてからまた無効に
するという動作が必要になってきます。
![Screenshot from 2018-11-27 21-26-24.png](https://qiita-image-store.s3.amazonaws.com/0/232732/56988c7f-5e56-fed5-79c0-e7980c12f706.png)
ここまでやって初めてalt+`のショートカットの重複が無効化できます

##ショートカットの設定
あとは入力ソースの切り替えショートカットを自分で設定するだけです
ubuntuではibusとfcitxの二大インプットメソッドフレームワークが存在し16.04はでapt-getコマンドでインストールすればfcitxも普通に
使えますが今回はibusで行います。

設定＞地域と言語から入力ソースを英語（US）と日本語（Mozc）にします
![Screenshot from 2018-11-27 21-32-13.png](https://qiita-image-store.s3.amazonaws.com/0/232732/26a87397-376f-f047-7803-97ba1018edcf.png)

言語サポートからIMシステムをIBusに設定して
![Screenshot from 2018-11-27 21-34-44.png](https://qiita-image-store.s3.amazonaws.com/0/232732/8d724ceb-ed27-33d6-cf9f-fb8eedbf2aea.png)

最後に設定＞キーボード＞ショートカットから”次の入力ソースへ切り替える”のショートカットをalt+`に設定します
![Screenshot from 2018-11-27 21-36-11.png](https://qiita-image-store.s3.amazonaws.com/0/232732/04da5571-d966-c402-072c-a23731a36ed6.png)

これで入力ソースの切り替えが一応alt+`で可能なはずですが僕は念の為再起動しました

#おまけ
今までLinux機は英語配列ではなく日本語配列でやってたのでこの現象には大変悩まされました・・・またUbuntu機の環境を構築する機会もあると思うので自分用の手順書も兼ねて記事を書きました。
多分手順は抜けてないはずですがなんかミス等ありましたら御一報のほどよろしくお願いします。
#追記
Gnomeデスクトップ環境だとこれだけだとうまくいきませんでした.
設定>キーボード>ショートカット>ナビゲーション>"ひとつのアプリケーション内のウィンドウを切り替える"の設定が見かけ上無効になってたので一旦デタラメなショートカットを有効にしてから,無効にしてまた再度先ほどの手順を繰り返したら動くようになりました....一回沼にハマるとなかなか大変なので気をつけてください(2018/12/03更新)
【SAPUI5】MVCを完成させよう

##はじめに
前々回の記事（[MVCで作ってみよう](https://qiita.com/tami/items/2442c0641e74eb07bd6d#_reference-055b404a11f35f158d4b)）ではビュー、コントローラーの実装まで行いました。今回は、モデルを使ってデータを表示させます。これでモデル、ビュー、コントローラーがそろってMVCが完成します。

【前提ステップ】
[【SAPUI5】MVCで作ってみよう](https://qiita.com/tami/items/2442c0641e74eb07bd6d)
[【SAPUI5】Component.jsとmanifest.json](https://qiita.com/tami/items/fa7755d91f95c3224638)

##モデルの種類
SAPUI5では、以下のモデルを使うことができます。

- ODataモデル：サーバとデータをやり取りするのに使用します。データはサーバ側に持ちます。
- JSONモデル：クライアント側で持つ、JSON形式のデータセットです。
- XMLモデル：クライアント側で持つ、XML形式のデータセットです。
- Resourceモデル：主に多言語対応のために、翻訳用のテキストを定義するのに使用します。

JSONモデルとXMLモデルは、基本的には小さいデータセットを扱うのに使用します。

##モデルの実装
今回はJSONモデルで簡単なデータセットを定義し、それを画面に表示させてみます。

###ゴール
ボタンの下にモデルから取得したテキストが表示されるようにします。
![WS000011.JPG](https://qiita-image-store.s3.amazonaws.com/0/276021/82e05055-1e85-3359-e626-be03bd91c956.jpeg)

###ステップ

1. モデルを定義する
2. manifest.jsonにモデルを追加する
3. ビューにテキストを追加する
4. アプリを実行する

###1. モデルを定義する
新しく"model"フォルダを作り、その配下に"Price.json"を作成します。
![WS000012.JPG](https://qiita-image-store.s3.amazonaws.com/0/276021/bcea186a-07fb-ca2d-e48f-200a4b5a73b1.jpeg)
以下のコードを入力します。

```json
{ 
	"product" : {
		"name" : "pumpkin",
		"price": 150
	}
}
```
###2. manifest.jsonにモデルを追加する
manifest.jsonの	"sap.ui5"のセクションの一番下に、以下のコードを追加します。

```json
	"sap.ui5": {
		"_version": "1.2.0",
                <省略>
		"models": {
			"mPrice":{
				"type": "sap.ui.model.json.JSONModel",
				"uri": "model/Price.json"
			}
		}
	}
```

モデル名は任意です。ここではわかりやすいように先頭にmをつけています。
- type：JSONファイルなので、"sap.ui.model.json.JSONModel"を指定します。
- uri：モデルのファイルパスを指定します。

###3. ビューにテキストを追加する
App.view.xmlを以下のように変更します。

```xml
<mvc:View 
	controllerName="test.helloworld.controller.App" 
	xmlns="sap.m" xmlns:l="sap.ui.layout" 
	xmlns:mvc="sap.ui.core.mvc">
	<l:VerticalLayout class="sapUiContentPadding">
		<Button text="Say Hello" press="onShowHello"/>
		<Text text="{mPrice>/product/name}"/>
		<Text text="{mPrice>/product/price}"/>
	</l:VerticalLayout>
</mvc:View>
```
VerticalLayoutは要素を縦に整列させるために入れました。ここで注目するのは、Textに指定した値です。
{mPrice>/product/name}のように波カッコで囲むと、モデルからデータをバインド（割り当て）すると解釈されます。指定する値は左から順に以下の通りです。

1. manifest.jsonファイルで指定したモデル名
2. オブジェクト名
3. キー

モデル名の後ろにスラッシュをつけると、絶対パスを意味します。

###4. アプリを実行する
実行結果は以下のようになります。
![WS000011.JPG](https://qiita-image-store.s3.amazonaws.com/0/276021/34c4e91b-0800-5e68-8ad8-b87ed885705e.jpeg)
RaspberryPi zero w で外付けHDDマウント

# RaspberryPi zero w で外付けHDDマウント
ほったらかしの2.5インチHDD（PS4産）をNASとして利用する計画
まずは外付けHDDケースを買ってきてラズパイに接続

## デバイス名確認
`$sudo fdisk -l`
たぶん/dev/sdaとしてマウントされている

## デバイスからパーティション削除＆作成
パーティション作成モード立ち上げのコマンドは以下
`$sudo fdisk /dev/sda`

### パーティション削除
`Command : d`
パーティションが複数存在する場合はその数だけ実行する必要あり

### パーティション作成
`Command : n`
defaultのままEnter連打した

### 状態確認
`Command : p`
現在の状態がみられる

## フォーマット
`$sudo mkfs -t ntfs /dev/sda1`
だが、ntfsがデフォルトではパッケージが入ってないらしいので以下を叩いてから
`sudo apt install ntfs-3g`

## マウント
`$sudo mount /dev/sda1 /mnt/hdd`
/mnt/に適当なフォルダを作ってマウント対象に設定

## sambaの設定
### パスの設定
```
[dirname]
path = /mnt/hdd/
browseable = yes
public = yes
read only = no
```
### samba再起動
```
$sudo systemctl restart smbd
$sudo systemctl restart nmbd
```
あとはwindowsからネットワーク内に認識できれば完了。
Fiddlerを使ってWebAPIをデバッグする際に、個人的によく忘れること

Fiddlerを使ってWebAPIをデバッグする際に、個人的によく忘れることをまとめました。
何か思いつけば随時追記します。


#1. Content-Type ヘッダーの設定
|種類    |Content-Type    |
|:---|:----|
| json | Content-Type: application/json |
| csv | Content-Type: text/csv |

他のものは [Content-Typeの一覧](https://qiita.com/AkihiroTakamura/items/b93fbe511465f52bffaa) を参照

#2. JSONの書き方
[JSON Data Types](https://www.w3schools.com/js/js_json_datatypes.asp) を参照

```sample.json
{
    "object": {
        "string":"abcdefg",
        "number":12345.123,
        "boolean":true,
        "array":["a","b","c"],
        "null":null
    }
}
```