OmniAICreator/Qiita-1.07M huggingface dataset:
SwiftでUITextViewにリンクを挿入する

# はじめに
以下のような、複数のタップ可能なリンクを持つUITextViewの作成方法のメモです。
リンクタップした際に、ログ送信など別の処理も行いたいものと想定します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/113553/92f48b93-0ce2-3f26-48a6-eb94fd6351ab.png)

# 実現方法
UITextViewへリンクを追加する方法はNSMutableAttributedString（.link）を追加することで実現できます。また、リンクタップ時の処理は、**何かリンクを識別する文字列をURLとして与えておき、UItextViewのデリゲートメソッド内で判別してハンドリングします。**

```swift:UITextViewがリンクをタップされた際に実行されるデリゲートメソッド
public func textView(_ textView: UITextView, 
                     shouldInteractWith URL: URL, 
                     in characterRange: NSRange, 
                     interaction: UITextItemInteraction) -> Bool { }
```

以下のソースコードでは、利用規約およびプライバシーポリシーのリンクを識別する文字列として、`TermOfUseLink`と`PrivacyPolicyLink`を設定しています。
※識別する文字列に**マルチバイト文字を設定するとクラッシュする**ので注意

```swift:利用規約およびプライバシーポリシーのリンクを識別する文字列の設定
        attributedString.addAttribute(.link,
                                      value: "TermOfUseLink",
                                      range: NSString(string: baseString).range(of: "利用規約"))
        
        attributedString.addAttribute(.link,
                                      value: "PrivacyPolicyLink",
                                      range: NSString(string: baseString).range(of: "プライバシーポリシー"))
```

# ソースコード
```swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let baseString = "利用規約、プライバシーポリシーに同意する。"
        let attributedString = NSMutableAttributedString(string: baseString)
        
        attributedString.addAttribute(.link,
                                      value: "TermOfUseLink",
                                      range: NSString(string: baseString).range(of: "利用規約"))
        
        attributedString.addAttribute(.link,
                                      value: "PrivacyPolicyLink",
                                      range: NSString(string: baseString).range(of: "プライバシーポリシー"))
        
        let textView = UITextView()
        textView.attributedText = attributedString
        textView.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
        textView.center = view.center
        textView.isSelectable = true
        textView.isEditable = false
        textView.delegate = self
        view.addSubview(textView)
    }
}

extension UIViewController: UITextViewDelegate {
    public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        
        let urlString = URL.absoluteString
        if urlString == "TermOfUseLink" {
            print("利用規約のリンクがタップされました")
            // ログ送信処理
            // 利用規約画面を開く処理
        }
        
        if urlString == "PrivacyPolicyLink" {
            print("プライバシーポリシーのリンクがタップされました")
            // ログ送信処理
            // プライバシーポリシー画面を開く処理
        }
        
        return false
    }
}
```

# 参考

- [UITextView内の特定文字を文字装飾してタップイベントを追加する](https://qiita.com/wrbss/items/7a88e4c18578315977fc)
- [UITextViewにタップ可能なリンクを挿入する](https://qiita.com/shtnkgm/items/3c8b6b794219fbf087ba)
EC2でsshやsudoできなくなった場合の対処法

EC2でデフォルトユーザを消したり、visudoを使わずに編集ミスした場合、sudoが使えなくなります。つまり、インスタンスのシャットダウンすら出来なくなります。
または、authorized_keysを間違えて消した場合などは、SSHの代替手段がないのでログインすらできなくなります。

そんな時でも、ルートデバイスがEBSなら、ディスクを他のインスタンスに付け替えられるので簡単に復旧できます。以下の例はubuntuですが、他のディストリビューションでも同じことが出来ます。

# 手順

## 問題が起きたインスタンスをAWSコンソールから停止

ログインできないので、コンソールから止めるしか無いです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/69350/d96c7f3b-aef4-f883-8762-833b828cf4dd.png)

## EBSのデタッチ

アタッチしているインスタンスが停止すると、デタッチできるようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/69350/2ea29d07-8625-23e2-51b1-5c5922996754.png)

## 新規インスタンスの作成

一時的な救出用のインスタンスを作ります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/69350/cb289912-1fc7-eafe-ef01-74bdcd0f4bbf.png)

## EBSアタッチして、マウントする

先程作った救出用インスタンスにデタッチしたEBSをアタッチして、適当なディレクトリにマウントすると、間違えて操作したインスタンスのルートディレクトリが操作できます。（ここはrootで作業）

~~~
root@ip-10-0-0-44:/home/ubuntu# mkdir hoge
root@ip-10-0-0-44:/home/ubuntu# mount /dev/xvdf1 hoge
root@ip-10-0-0-44:/home/ubuntu# ls hoge/
bin   dev  home        initrd.img.old  lib64       media  opt   root  sbin  srv  tmp  var      vmlinuz.old
boot  etc  initrd.img  lib             lost+found  mnt    proc  run   snap  sys  usr  vmlinuz
~~~

## sudoersをいい感じに編集して、シャットダウン

アンマウントするか、綺麗にインスタンスを落とします。

~~~
nano hoge/etc/sudoers.d/90-cloud-init-users
umount hoge
halt
~~~

## EBSをルート用にアタッチ

元のインスタンスにEBSを戻します。基本的には先程と逆の操作ですが、適当な名前でアタッチすると起動できないので、予約済みのデバイス名を参考に戻します。
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/device_naming.html#available-ec2-device-names

ubuntuでは/dev/sda1です。アタッチせずに起動するとエラーで教えてくれるようなので、それを参考にしても良いかも。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/69350/93e0b990-9ab1-7a8a-fcdd-387cb53a4326.png)

起動すると、なおっていますね。

~~~
juntaki@ec2 ~> sudo su
root@ec2:/home/juntaki#
~~~

# まとめ

これで、EC2で設定ミスをしても戻せます。
フレッツ 光ネクスト IPv6 IPoEにしてみました

今住んでいるとこのISPはSo-netなんですが、いわゆるNGN問題は
http://itpro.nikkeibp.co.jp/article/COLUMN/20070125/259673/?rt=nocnt
ここらへんで。いままでISPの問題と思ってましたが、NTTの怠慢やん！(# ﾟДﾟ)
平日でも21時すぎると speedtest.net でダウンロード一桁MBって、いくらベストエフォートでもあまり動画見ないユーザでもあまりの仕打ち。
で、前に「遅いって思ってるんならIPv6にしたら」（かなり意訳）ってメールが来たんですよね。So-netから。
色々調べながらIPv6にしても無料とのことで試してみました。

So-netでIPv6申し込んだら1時間ぐらいで開通メール来た
なんか1日から3日かかるかもと言われてたのでちょいアセアセ(^_^;)
とりあえずAmazonでIPoE対応ルータとのことで(I-O DATA WN-AX1167GR)注文
翌日ルータ到着
で繋いで・・・え！ケーブルまとめてる結束バンド切ったら電話線切っちゃったｗ
とりあえずカッターで4線剝いて接続。。orz　また買おう。いまのところ問題ない
![IMG_0296.jpg](https://qiita-image-store.s3.amazonaws.com/0/194075/79091c3b-15c6-2e72-691f-13384b7deb1e.jpeg)
とりあえずセロテープ(R)で絶縁ｗ

ルーターの設定はとっても簡単。
「インターネット」で「transix」をクリするのみ！
あと無線LAN(wi-Fi)を前に使ってたルータと同じにしたり。。
ワンルームとか平屋とかだと5GHzの11ac使うと早くなるかも。なので前回使用のルータのSSIDとパスを
5GHzに設定。iPhoneも何事もなく接続。ノートPCも

祝日なのですが午前中に設定したため21時過ぎ辺りに速度を計測しました。
一桁MBがなんと！！！！！！！！！！！！！！！！！！！！！！
90M超え。。。なんなの

ルータからはIPv6で送信するようですが相手にはどっかでいいかんじでv4に変換してくれて見れなくなることはありません。
ただっていうかあまり関係ないかもですがSo-netでtransixするとリモホが
xxx.xxx.xxx.xxx.shared.user.transix.jp
先頭はv4のIPの逆が振られてました。

今はv6使ってる人少ないのでいいのかもですが、増えたらまたv4のような問題が出てくるんですかね？

追記
DS-liteにするとポート開放できないようです。
自宅サーバーとかゲームでなどの人はちょっと無理かも。
自宅環境ははVDSLです。マンションタイプで100Mしか出ません。
しかしながらとりあえず90Mは出ています。
Java でスレッドを起動する方法2種類 +@

## Thread のサブクラス

Thread クラスを継承して `run()` メソッドを実装する。 

```java
public class Qiita {
    public static void main(String[] args) {
        new HelloThread("World!").start();
        new HelloThread("Qiita!").start();
    }
}

class HelloThread extends Thread {
    private String message;

    public HelloThread(String message) {
        this.message = message;
    }

    public void run() {
        System.out.print("Hello, " + message);
    }
}
```

## Runnable インターフェース

Runnable インターフェースを実装したクラスを、Thread のコンストラクタに渡す。

```java
public class Qiita {
    public static void main(String[] args) {
        new Thread(new Greeting("World!")).start();
        new Thread(new Greeting("Qiita!")).start();
    }
}

class Greeting implements Runnable {
    private String message;

    public Greeting(String message) {
        this.message = message;
    }

    public void run() {
        System.out.print("Hello, " + message);
    }
}
```

## (+@) ThreadFactory でスレッドを生成する

ThreadFactory でスレッドの生成を抽象化する。

```java
public class Qiita {
    public static void main(String[] args) {
        ThreadFactory factory = Executors.defaultThreadFactory();
        factory.newThread(new Greeting("Qiita!")).start();
    }
}
```
python-twitterを利用して、pythonでTwitterを操作する。

# python-twitterを利用して、pythonでTwitterを操作する。

python-twitterを利用して、pythonからTwitterを操作してみます。

## プログラム実行前に準備すること
[Twitter App](https://apps.twitter.com)にアクセスし、[Create an app]で新規作成します。
URLの入力が求められることがありますが、なんでも構いません。
各種Keyを発行します。以下の4つです。
　・Consumer Key(API Key)
　・Consumer Secret(API Secret)
　・Access Token
　・Access Token Secret
これらが終われば、必要な準備は終わりです。

## ライブラリのインストール
PythonでのTwitterライブラリは数多くありますが、今回はpython-twitterを使用したいと思います。
インストールは`$ pip install python-twitter`によりできます。

## 実際にライブラリを使用してみる
ログインしましょう。

```python3
import twitter

api = twitter.Api(consumer_key=' ',
                  consumer_secret=' ',
                  access_token_key=' ',
                  access_token_secret=' '
                  ))
# 空白には自分で取得した各種キーを文字列として入力してください。
# これによりプログラムからTwitterを動かすことができます。
```

最近の自分のタイムラインを取得してみましょう。
ついでに内容も表示してみましょう。

```python3
statuse = api.GetUserTimeline(api.VerifyCredentials().id, count=200)
# countに指定した個数のタイムラインを取得することができます。
# 取得できる最大値は200です。

for s in statuse:
    print(s.text)
# タイムラインの内容が表示されます。
```

フォロワーのタイムラインを取得してみましょう。
今回は数が多くなるので、5人のフォロワーの最新の５件を表示します。
*鍵垢の人のタイムラインは取得できないようです。

```python3
friends = api.GetFriends()
for i,friend in enumerate(friends):
    if i > 5:
        break
    friends_statuse = api.GetUserTimeline(friend.id, count=5)
    print(friend.name) # ユーザー名
    for f_s in friends_statuse:
        print(f_s.text) # ツイートの内容
    print() # 改行
```

実際につぶやいてみましょう。
ダイレクトメッセージもついでに送ってみましょう。

```python3
api.PostUpdates('I love python-twitter.')

for i,friend in enumerate(friends):
    if i > 5:
        break
    api.PostDirectMessage(friend.id, 'I love you.')
```

最後は写真をツイートしてみましょう。

```python3
api.PostUpdate('Picture.', media=' ')
# mediaの空白にアップロードしたい写真のパスを指定してください。
```

そのほかにもAPIには様々な関数が定義されているので、
気になる方は参考サイトを参照してください。

# 参考サイト
http://python-twitter.readthedocs.io/en/latest/
JSでcmp関数を定義してsortを読みやすく書く技

JavaScript で sort を書く場合、普通なら次のように書く。

```js
ary = ary.sort(function (a, b) {
    var _a, _b;
    _a = a['Instance Family'].replace(/General purpose/, '');
    _b = b['Instance Family'].replace(/General purpose/, '');
    if (_a !== _b) return _a < _b ? -1 : 1;
    _a = a['vCPU'] * 1;
    _b = b['vCPU'] * 1;
    if (_a !== _b) return _a > _b ? -1 : 1;
    _a = a['Memory'].replace(/ .*$/, '').replace(/,/g, '') * 1;
    _b = b['Memory'].replace(/ .*$/, '').replace(/,/g, '') * 1;
    if (_a !== _b) return _a < _b ? -1 : 1;
    return 0;
});
```

次のようにすると、これがもっと解りやすく書ける。

まずは cmp という関数を定義。

```js
function cmp(a, b, func) {
  a = func(a);
  b = func(b);
  if (a === b) return 0;
  return a < b ? -1 : 1;
}
```

すると、先ほどんのロジックは次のように書ける。

```js
ary = ary.sort(function (a, b) {
  return false ||
    cmp(a, b, function (v) { return v['Instance Family'].replace(/General purpose/, '') } ||
    cmp(b, a, function (v) { return v['vCPU'] * 1 } ||
    cmp(a, b, function (v) { return v['Memory'].replace(/ .*$/, '').replace(/,/g, '') * 1 } ||
    0;
});
```

比較ロジックが見えやすくなる。
JavaScript/jQuery の処理の実施タイミングの切り分けを示す例を書いてみた

突っ込みどころ満載な内容ですが・・・。

# 処理実施のタイミングが気になった。

(jQueryを含む）JavaScriptを使ったコードはよく、`$(document).ready(function({ (中略） });`　みたいな中に記載して、ページを操作しても良いレンダリング終了後に有効化させるケースが多いですが・・・。処理の中には、レンダリング中に実施してもよいものもあると思って。

## JSで処理する内容を、適した時期ごとに分けてみた。

1. DBからデータ取得など、レンダリングとは直接関係ない処理。
2. タグ埋め込みなど、終わったときに実施する処理。
3. バリデーションなど、操作・変化を検知したときに行う処理。
4. 時刻表示など、ページ表示中定期的に動く処理。

１のようなタイプの処理は、先にAjaxで取得のリクエストを送信、非同期にデータを受け取り、レンダリング終了後に所定の位置に埋め込むような使い方もできるかな？と思ったり。

# 単純化したコードを書いてみて　動かしてみた。

事象を単純化し以下のファイルを用意する。

1. レンダリングされたページ代わりのHTMLファイル
2. カプセル化したい処理をまとめたクラスを記載したJSファイル
3. 2の中にあるクラスを呼び出す記載をしたJSファイル


## ソース


```html:ページのHTML
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="read1.js"></script>
<script type="text/javascript" src="read2.js"></script>
</head>
<body>
<h1>実際の運用環境ではもっと多いHTMLコードがあるので、レンダリングに時間がかかる</h1>
</body>
</html>
```

１に相当する。こんな感じのHTMLをレンダリングすることは多々あるはず。



```javascript:read1.js(クラスが書いてあるほう）
console.log("read read1.js");

console.log("/*クラスとして作りたいもの*/");

var someClass = function(msg="someClass"){
	
	
	console.log("/*someClassのコンストラクタが処理される*/");
	var instance_var = "instance param";
	console.log("new Instance "+msg);
	
	this.readInstansVar = function(){
	console.log("read method");
		return instance_var;
	}
	
	$(document).ready(function(){
		console.log("Rendering is end");
	});
	
}
```

２に相当する。コンストラクタに相当するもの、クラスメソッドに相当するもの、
HTMLレンダリング実施後に行う処理に分けた。


```javascript:read2.js(クラスを呼び出すほう）

console.log("read read2.js");


console.log("/*先に、レンダリング終了時に処理する内容を記載する。*/");

$(document).ready(function(){
	console.log("Docuent Ready at read2");
});
console.log("/*インスタンスを生成して、処理する*/");

var ins = new someClass("read2");
var ret = ins.readInstansVar();
console.log(ret);

```
３に相当する。わざと２のスクリプトファイルインスタンス生成より前に、レンダリング終了後に実施する処理を先に書いている。

## 実施結果

```text:console.log
read1.js:2 read read1.js
read1.js:4 /*クラスとして作りたいもの*/
read2.js:2 read read2.js
read2.js:5 /*先に、レンダリング終了時に処理する内容を記載する。*/
read2.js:10 /*インスタンスを生成して、処理する*/
read1.js:9 /*someClassのコンストラクタが処理される*/
read1.js:11 new Instance read2
read1.js:14 read method
read2.js:14 instance param
read2.js:8 Docuent Ready at read2
read1.js:19 Rendering is end
```

処理を追っていくと

1. 「先」のファイルの地の部分が実行される。
2. 「後」の地の部分が実行され、先の方のクラスのインスタンスを生成する。
3. 「後」インスタンス生成と同時に、「先」のコンストラクタが実行される。
4. 「先」メソッドを呼び出し、回答を取得する。
5. レンダリングが終了し、「後」、「先」の順に`(document).ready`の中身を実施する。

といった流れ。

# 考察～レンダリング終了前後が重要？

1. レンダリングが終わる前に、データ取得のAjaxなどを呼び出す。
2. レンダリング終了時に、1.の結果を取得する・・・が、まだ取得できていなかったり、エラーが発生したときのことも考慮すること。

# 参考
JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる
https://qiita.com/YoshikiNakamura/items/732ded26c85a7f771a27
VirtualBox の Ubuntu に Anaconda をインストール



# 環境
macOS 10.12.6

# Virtual Box をインストール
## 1. Dropbox をダウンロード
[DropBoxダウンロードページ](https://www.virtualbox.org/wiki/Downloads)より、OS にあった VirtualBox のバイナリと ExtensionPack をダウンロード

* VirtualBox 5.2.0 platform package
* VirtualBox 5.2.0 Oracle VM VirtualBox Extension Pack 

 
## 2. Virtualbox platform package をインストール
ダウンロードした platform package をウィザードに従ってインストール
　
## 3. Virtualbox に拡張パックをインストール
VirtualBox を起動し、ダウンロードした Extention Pack を追加。

　VirtualBox - 設定 - 機能拡張
　![スクリーンショット 2017-11-03 18.47.22.png](https://qiita-image-store.s3.amazonaws.com/0/27486/4eb4967d-8bfd-c0d2-0065-93391817c5d2.png "スクリーンショット 2017-11-03 18.47.22.png")


# Virtual Box に Ubuntu の仮想マシンを作成
## 1. Ubuntu 仮想ハードディスクをダウンロード
[Ubuntu ダウンロードページ](https://www.ubuntulinux.jp/download)より Ubuntu の仮想ハードディスクイメージをダウンロードし、適当な場所に解凍する。
![スクリーンショット 2017-11-03 18.44.37.png](https://qiita-image-store.s3.amazonaws.com/0/27486/a51a6c12-89be-f2b1-8984-b8af0b9e9739.png "スクリーンショット 2017-11-03 18.44.37.png")

## 2. Ubuntu の仮想マシンを作成する
(1) VirtualBox 上で新規
(2) 名前を決め、Linux / Ubuntu を指定する
(3) メモリは 2048MBとした ＊あとで変更できる
(4) ハードディスクは、「すでにある仮想ハードディスクファイルを使用する」とし、ダウンロードした Ubuntu の仮想ハードディスクファイルを指定

## 3. Ubuntu をセットアップする
(1) 作成した仮想マシンを起動する
(2) ウィザードに従って言語、タイムゾーン、キーボード、アカウントを設定
(3) 作成したアカウントでログインする

# Ubuntu 上に anaconda をインストールする
## 1.anaconda インストーラをダウンロード
[anacondaダウンロードページ](https://www.continuum.io/download)をブラウザで開くと、OS にあわせたダウンロードページにリダイレクトされるので、python のバージョンとアーキテクチャにあわせたインストーラをダウンロードする。
![スクリーンショット 2017-11-03 21.16.25.png](https://qiita-image-store.s3.amazonaws.com/0/27486/3f9358f9-7e3f-4bca-f847-a8bd736bd17a.png "スクリーンショット 2017-11-03 21.16.25.png")
＊Python 3.6 version の、64-bit(x86)


## 2. anaconda をインストールする
(1) terminal を開き、~/ダウンロード に移動する。

(2) インストールする

```
$ bash Anaconda3-5.0.1-Linux-x86_64.sh
```

途中、以下を聞かれる

* ライセンス
	* yes で表示し、enter で文末までスクロール
* anaconda のインストールディレクトリ
	* デフォルト：/home/hoge/anadonda3
* PATH に追加するか
	* デフォルト：yes

(3) 確認する

conda のバージョン

```
$ conda -V
conda 4.3.30
```

Python のバージョンも確認しておく

```
$ python -V
Python 3.6.3 :: Anaconda, Inc.
```


# Tips

## シャットダウン
いくつかの方法がある

* デスクトップ右上の歯車アイコン![スクリーンショット 2017-11-03 20.42.06.png](https://qiita-image-store.s3.amazonaws.com/0/27486/843e0d00-c4e1-c172-630e-d0ce97c962ed.png "スクリーンショット 2017-11-03 20.42.06.png")からシャットダウンする
* もちろん、terminal でシャットダウンコマンドを叩いても OK

## ゲスト-ホストの移動

* ゲスト OS を抜けてホスト OS に戻るには、Command キー
* ゲスト OS にマウスを戻すには、ゲスト OS 上をクリック

## クリップボードの共有

設定 - 一般 - 高度 で下記のとおり設定する

* クリップボードの共有＝双方
* ドラッグ＆ドロップ＝双方

 ![スクリーンショット 2017-11-03 20.38.56.png](https://qiita-image-store.s3.amazonaws.com/0/27486/5a6f6648-5291-2ec3-2e91-dfc7b1edb8a9.png "スクリーンショット 2017-11-03 20.38.56.png")
immutable.js v4でTypeScriptの型定義が改善された

# strictNullChecks時の改善
今まではmapやforEach関数に渡すコールバックの第一引数が`T?`でしたが、v4では`T`になりました。
これによってstrictNullChecks時でも`!`が不要になりました。
例:

```ts
//v3以前
x.map(x=>x!+1);

//v4
x.map(x=>x+1);
```

v3以前もxにundefinedやnullが渡されることはなかったのに型定義は`T?`で気持ち悪かったので修正されてよかったです。

# Recordが型安全になった
```ts
const MyRecord = Record({ x:1,y:2 });
const myRecord = new MyRecord({});

//v3以前は以下のコードのコンパイルが通る
//v4では型エラーになる
myRecord.get('a');
```

今までは型安全じゃなかったのでRecordを使うのは避けていたのですが、これによって安心して使えるようになりました。
Slack Appの作り方について

Slack Appで色々やろうと思ったときに、少しやり方が分かりにくかった部分もあるのでまとめ中。適宜追記していくので間違い等あればご指摘ください。

# Slack Appの作り方
* https://api.slack.com/apps から App を作成する（Create New Appから情報を入力して作成）
* 作成すると色々設定する画面に入るので設定を行う
* ちゃんと設定するとSlack Appが使える状態になる

参考：https://qiita.com/YumaInaura/items/0fc810e885a3d988f123

# 設定すること
## 基本情報（Basic Information）について
Slack Appを作ると、基本情報の画面に遷移する。ここでは以下の3つの項目がある。
![slack-app-setting-top.PNG](https://qiita-image-store.s3.amazonaws.com/0/188222/a6c8fd44-79cb-fb02-7691-43b375085cfe.png)

* Add features and functionality：Slack Appに持たせたい機能・関数をaddするところ。初期状態で開いている
* Install your app to your workspace：Slack Appをインストールするためにtokenを発行し、workspaceに追加するところ
* Manage distribution：個人で使う場合には不要。他のworkspaceでも使えるように共有するところ

## 機能・関数の追加（Add features and functionality）
Slack Appを作るのに必要なツールを選択して設定するところ。6つの項目がある。
![slack-app-features.PNG](https://qiita-image-store.s3.amazonaws.com/0/188222/7e2395e3-8551-d568-2ffa-3d1fb4fab625.png)

* Incoming Webhooks：別の外部ソースから連携してSlackにメッセージ投稿する。
* Interactive Components：Slack Appから投稿するメッセージにボタンを追加して、ユーザ操作を受け付ける。
* Slash Commands：Slackにコマンドを追加して、ユーザがコマンドを打ったときにアクションできるようにする。
* Event Subscriptions：Slackの何らかのアクティビティに対して反応できるようにする。
* Bots：ユーザからのメッセージに応答できるボットを追加する。
* Permissions：Slack APIとのやりとり用にアクセス権を設定する。

## workspaceへのappのインストール（Install your app to your workspace）
Slack APIとのやりとり用にtokenを生成するところ。認証に使う。permission scopeをクリックして、必要なpermissionのtokenを作る。
![slack-app-permission-scope.PNG](https://qiita-image-store.s3.amazonaws.com/0/188222/5e7dade4-14c2-e444-6e65-604516ca64c9.png)

permission scopeをクリックすると、OAuth & Permissionsの項目でOAuthの設定が上に出て来るので一瞬戸惑うが、スルーしてスクロールするとScopesの設定項目があるのでそこで設定を入れる。![slack-app-scopes.PNG](https://qiita-image-store.s3.amazonaws.com/0/188222/c3e2ac6b-1a4d-b538-4cbe-bdcbfd756128.png)

ここではSlack Appが呼び出せるAPIメソッドがどれなのかを定義する。これをSlack App Directoryに提出する場合、各scopeのリクエスト理由が確認されるので、適切なscopeを設定する。
scopeの種別については https://api.slack.com/scopes ここに一覧があるので要確認のこと。

# 雑記
この方法でSlack Appを作ることはできるが、単純にwebhookしたいだけなら[この記事](https://qiita.com/vmmhypervisor/items/18c99624a84df8b31008)の手順の方が楽かも。

# 参考URL
* https://qiita.com/ykhirao/items/0d6b9f4a0cc626884dbb
* https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21
* https://qiita.com/YumaInaura/items/0fc810e885a3d988f123
MacにPython仮想環境を導入する(condaを利用)

Pythonの仮想環境をMac上に構築するためのメモ。

実行環境:
MacBookPro, macOS Sierra 10.12.6
iMac, macOS Sierra 10.12.6

# ローカル環境にAnacondaパッケージをインストールする。
https://www.anaconda.com/download/#macos
導入する時点で最も新しいバージョンを導入すれば良い。

# condaを用いた仮想環境構築
下記作業は任意のディレクトリで作業して良い。

## 仮想環境を構築する
> conda create -n ENVNAME python=3.6 anaconda=4.4.0

このとき、外部書き出しした仮想環境の情報(yamlファイル)を読み込んで構築することもできる。
> conda env create -f env1.yaml 

他のマシンや過去のマシンの仮想環境を手元の環境に導入したい時に役に立つはず。

ENVNAME: 任意の仮想環境名を入れる。
ここでは、pythonのバージョンを3.6, anacondaのバージョンを4.4.0とする。

## 作成した仮想環境下に入る
> source activate ENVNAME

この一文を、~/.bash_profileに書いておくと、ターミナル環境に入ると同時に仮想環境に自動的に入る。

## 仮想環境から出る(ローカル環境(root)に戻る)
> source deactivate

## 仮想環境下のnotebook extensionをインストール
> source activate ENVNAME
> conda install -c conda-forge jupyter_contrib_nbextensions

# conda関連のコマンド集
## 作った仮想環境のリストを見たい
> conda env list

または

> conda info -e

\*がついている環境が現在の環境、activate, deactivateで*が切り替わる



## 作った仮想環境を削除したい
> conda remove --name env --all

## 現在の仮想環境の設定を書き出す
> conda env export > env.yaml

## condaで管理できるパッケージとバージョンを探す
例えば、scikit-learnのどのバージョンが使えるか知りたいとする。
> conda search scikit-learn

例えば、使えるpythonのバージョンが知りたい
> conda search python

例えば、指定した環境にconpatibleなパッケージを探したい
> conda search -p /anaconda/envs/ENVNAME

## (指定した)環境に入っているパッケージを表示
> conda list (-n ENVNAME)

## condaを使って仮想環境下に新しいパッケージをインストールする。
### condaのリストにあるパッケージの場合
> conda install PACKAGE

### 非condaパッケージのライブラリをインストールする場合
> source activate ENVNAME (仮想環境をアクティベートして)
> pip install PACKAGE==x.x.x (PACKAGEをインストールする(バージョン指定も可能))

## conda自身の更新
> conda update conda

## condaのパッケージアップデート
> conda update --all
GoでJSONのnullをいい感じに扱いたい

GoでJSONのnullをいい感じに扱いたいことがあるとします。しかしGoではnullを扱うのは容易ではありません。

Goには`nil`が存在しますが、これはポインタ型でしか使えません。よって`int`や`string`型では使用できません。Goは`int`や`string`型は初期化しなかった場合、ゼロ値に初期化されます。`int`のゼロ値は0、`string`のゼロ値は空文字列です。そのためJSONのnullをGoで扱おうとした場合、Goのゼロ値との区別ができません。

同じ問題はSQLでもあります。nullが存在するカラムから値を取得した際にnullとGoのゼロ値を区別する必要があります。そこでGoの`database/sql`では`NullString`のようなstructが定義されています。

```go
type NullString struct {
	String string
	Valid  bool // Valid is true if String is not NULL
}
```

`Valid`の真偽値を確認することで空文字列とnullを区別することができます。これと同じことをJSONでやるにはどうしたらよいでしょうか。

`json.Marshal`と`json.Unmarshal`の動きを変更するには以下のインタフェースを実装します。

```go:interface.go
type Unmarshaler interface {
	UnmarshalJSON([]byte) error
}

type Marshaler interface {
	MarshalJSON() ([]byte, error)
}
```

そこで以下のような実装をしてみました。

```go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
)

type NullSegments struct {
	Segments Segments
	Valid    bool // Valid is true if Segments is not NULL
}

type Range struct {
	From int `json:"from"`
	To   int `json:"to"`
}

type Segments struct {
	Status int   `json:"status"`
	Range  Range `json:"range"`
}

type Settings struct {
	Segments NullSegments `json:"segments"`
}

var nullLiteral = []byte("null")

func (s *NullSegments) UnmarshalJSON(b []byte) error {
	if bytes.Equal(b, nullLiteral) {
		return nil
	}

	err := json.Unmarshal(b, &s.Segments)
	if err == nil {
		s.Valid = true
		return nil
	}

	return err
}

func (s NullSegments) MarshalJSON() ([]byte, error) {
	if s.Valid {
		return json.Marshal(s.Segments)
	} else {
		return nullLiteral, nil
	}
}

func main() {
	b := []byte(`{"segments": {"status": 1, "range": {"from": 10, "to": 20}}}`)
	// b := []byte(`{"segments": null }`)

	s := &Settings{}

	json.Unmarshal(b, s)

	bb, _ := json.Marshal(s)

	fmt.Println(string(bb))
}
```

注意点としては`[]byte`を`string`にキャストするのはコストが高いので`bytes.Equal`などのメソッドを使います。

`bool`型のゼロ値は`false`なので`null`が来たときは何もしなくて大丈夫です。`null`以外が来た場合に`Valid`をtrueにする必要があります。
Botkitで毎分異なる発言を行うslackbotを作ろう

# 準備
まずはNode.jsとnpmを準備する。導入の仕方は調べればたくさん出てくるので割愛。

開発する上で、'botkit'と'cron'を使うので入れておいてください。
```
npm install --save botkit
npm install --save cron
```

# コード
あまり難しいことはしていません。
乱数を生成して、出た数によって発言する内容を決定しています。

```js
const Botkit = require('botkit');
var CronJob =require('cron').CronJob;
var controller = Botkit.slackbot();
var bot = controller.spawn({
  token: process.env.token
}).startRTM(function(err, bot, payload) {
  // 初期処理
  if (err) {
    throw new Error('Could not connect to Slack');
  }

  new CronJob({
    cronTime: '* * * * 0-6',
    onTick: function() {
      bot.say({
        channel: 'bot_test',
        text: randomText()
      });
    },
    start: true,
    timeZone: 'Asia/Tokyo'
  });
});

// 発言内容を決定し、そのまま返す
function randomText() {
  var max = 4;
  var min = 0;
  var message = "";

　// 0 ~ 4 の乱数を生成
  var result = Math.floor(Math.random() * (max + 1 - min)) + min;

  switch(result) {
    case 0:
      message = "ほげ";
      break;
    case 1:
      message = "hoge";
      break;
    case 2:
      message = "hogeeeeeeee";
      break;
    case 3:
      message = "fuuuuuuuuuuuuuuuuuuga";
      break;
    case 4:
      message = "ふが";
      break;
  }
  return message;
}
```

# 動き
毎分、`randomText`で設定した内容の内、いずれかを発言します。
発言される内容は毎分異なります。
自分の手でさらに改良を加えて見て下さい。
fullCalendar:カスタマイズメモ②

#カレンダーのカスタマイズ

##カレンダーのヘッダーにボタンをつける
・ヘッダーというのはカレンダーの上の、タイトルなどが記述されている部分です。

```
header:{
			left:'prev,next,today',
			center:'title,eventListButton',
			right:'month agendaWeek agendaDay'
		},
```

leftは左側、centerは中央、rightは右側に記述した要素が追加されます。

##ボタンにテキストを指定する

```
buttonText: {
			month:'月',
			week: '週',
			day:'日'
		}
```
fullCalendarが用意してくれているボタンにどのような文字を表示させるかは、ここで指定します。

##ボタンを自作する

```
customButtons:{
			eventListButton:{
				text: 'イベントリスト',
				click:function(){
					alert('イベントリスト!');
				}
			}
		}
```
customButtonsに記述すると、標準にないボタンを作成でき、ボタン押下時の処理も実装できます。

##カスタマイズ後のヘッダー
![fullCalendar_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/184079/bc0f7332-76ab-bac9-a2f3-c53e998d46ef.png)

このように、ソースで記述したとおりのボタンがヘッダーに表示されています。
【環境構築】KotlinでReactのWebアプリを作る

# 概要
Kotlin/JSでReactしたいと思っていたところ、`create-react-kotlin-app`の存在を知ったので動かしてみました。

# 環境
|ツール|バージョン|
|---|---|
|node|v9.0.0|
|npm|5.5.1|
|create-react-kotlin-app|1.0.4|
|IntelliJ|2017.3 EAP (Ultimate Edition)|

※ nodeはnodebrewでインストールしました。
※ npmのビルドをIDE上で実行するには、IntelliJのUltimate Editionが必要です。今回はFree trial版で。

# インストールとアプリ生成
こちらの通りです。
https://github.com/JetBrains/create-react-kotlin-app#quick-overview

コマンド一発で初期アプリの構築が完了です。(簡単！)
`$ create-react-kotlin-app my-app`

# Run/Debug Configuration (IntelliJのRun設定)

|設定項目|値|
|---|---|
|package.json|path-to-project/package.json|
|Command|start|
|Arguments|--scripts-prepend-node-path|
|Node interporeter|~/.nodebrew/node/v9.0.0/bin/node|

# ビルド
IntelliJでRunすると、localhost:3000で起動して、以下のような初期画面が表示されます。

<img width="526" alt="スクリーンショット 2017-11-03 20.04.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/63694/14997df2-f45b-119f-9ff0-29fbcf87d290.png">

# まとめ
今回は、環境構築してRunするところまで書きました。
次は何か作ってみたいと思います。
fullCalendar:カスタマイズメモ①

#はじめに
fullCalendarというJQueryプラグインを業務でカスタマイズした時のメモです。

#メモ
##カレンダーの表示

▼html側の記述

```html
<!DOCTYPE>
<html>
	<head>
		<meta charset="utf-8">
		<link rel="stylesheet" href="fullcalendar/fullcalendar.css"/>
		<script src="fullcalendar/lib/jquery.min.js"></script>
		<script src="fullcalendar/lib/moment.min.js"></script>
		<script src="fullcalendar/fullcalendar.js"></script>
		<script src="calendarCustomize.js"></script>
	</head>
	<body>
		<div id="calendar"></div>
	</body>
</html>
```
calendarCustomize.jsはライブラリをカスタマイズするために自分が作成したjsファイルです。

▼js側の記述
1.カレンダーの初期化

```js
$(document).ready(function(){

	$('#calendar').fullCalendar({
            //この中にいろいろカスタマイズしていきます。
　　　　　})
})
```

2.初期化後のカレンダー表示
![fullCalendar_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/184079/41880b64-bfc5-be6c-70ba-6dd62e668630.png)

カレンダーが表示できました。
SQLファイルの基礎

「SQLファイルを作れ」と言われたので、あれこれと調べたところ、先人の記事がたくさん出てきて助かったのだが、特に基礎的な部分について横断的な内容が寡聞にして見当たらなかったのでメモ。
ちなみに環境はMySQLを仮定。

# 作成
## SQLファイルとは
拡張子が.sqlなのがSQLファイル。中身はSQL文だが、やっていることはテキストファイルとそうは変わらない。

## 作成
一番てっとり早い方法としては、<strong>テキストファイルを作って拡張子を後から変更してしまう</strong>というのが楽だと思われる。
ちなみにツールとしては、MySQL Workbenchとかがあるが、数十行書くだけであれば、私はTerapadを使っている（SQL文に対応しているわけではない）。

# 編集
## 文字コード
SQLファイルとデータベースで文字コードが一致していないと文字化けするので注意。MySQLではstatusコマンドなどで確認できる他、文字コードの変更方法については調べれば出てくる（丸投げ）。

## コメントアウト
```SQL:1行コメント
-- 1行コメント
```

とか、

```SQL:複数行コメント
/*
 複数行
 コメント
*/
```

とかがある。
あと、バージョンによって挙動を変えるコメントとかもある（リンク先参照）。

# 実行（MySQL）
```SQL
source ファイルのパス
```
で動く。ちなみにSQLファイルは勿論、<strong>テキストファイルでも可</strong>。

# 参考
[.sql【拡張子】とは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](http://wa3.i-3-i.info/word11961.html)
[MySQL 文字化けを防ぐ、文字コードの確認と設定 | 渋谷生活](http://ext.omo3.com/linux/mysql_character_set.html)
[MySQLのコメント構文 - Qiita](https://qiita.com/ques0942/items/d89de1ff7c92b4810d10)
[【MySQL】 SQLをファイルから実行する方法 - Qiita](https://qiita.com/ydzum1123/items/219d8e60843a678be719)
vue-cliで作成したプロジェクトをVSCodeで編集するときの設定

# 目的
vue-cliで作成したプロジェクトをVSCodeを使用してフォーマットするとeslintでエラーとなってしまいます。（2017/11/03 時点）
VSCodeの設定を修正しエラーとならずに動作させるようにします。

# 環境
- vue-cli 2.9.1
- VSCode 1.17.2
 - vetur 0.10.1

# 結論
以下の設定を追加。

```json:ユーザー設定へ追加
{
    "vetur.format.defaultFormatter.js": "vscode-typescript",
    "javascript.format.insertSpaceBeforeFunctionParenthesis": true
}
```

# 事象
#### 正常動作確認

```bash:プロジェクト作成～起動
vue init webpack sample
cd sample
npm install
npm run dev
```

#### フォーマット
![image.png](https://qiita-image-store.s3.amazonaws.com/0/114225/95f94533-139b-0d50-f44b-54e706525eef.png)

```:エラー内容
 ERROR  Failed to compile with 1 errors                                                        18:53:18

 error  in ./src/components/HelloWorld.vue


  ✘  http://eslint.org/docs/rules/quotes                       Strings must use singlequote
  src\components\HelloWorld.vue:25:9
    name: "HelloWorld",
           ^

  ✘  http://eslint.org/docs/rules/space-before-function-paren  Missing space before function parentheses
  src\components\HelloWorld.vue:26:7
    data() {
         ^

  ✘  http://eslint.org/docs/rules/quotes                       Strings must use singlequote
  src\components\HelloWorld.vue:28:12
        msg: "Welcome to Your Vue.js App"
              ^

  ✘  http://eslint.org/docs/rules/semi                         Extra semicolon
  src\components\HelloWorld.vue:29:6
      };
        ^

  ✘  http://eslint.org/docs/rules/semi                         Extra semicolon
  src\components\HelloWorld.vue:31:2
  };
    ^


✘ 5 problems (5 errors, 0 warnings)


Errors:
  2  http://eslint.org/docs/rules/semi
  2  http://eslint.org/docs/rules/quotes
  1  http://eslint.org/docs/rules/space-before-function-paren

 @ ./src/router/index.js 3:0-49
 @ ./src/main.js
 @ multi ./build/dev-client ./src/main.js
```

##### 問題点
- シングルクォーテーションがダブルクォーテーションに変換されてしまう。
- 関数名の後ろにあるスペースが除去されてしまう。
- 文の最後にセミコロンが挿入されてしまう。

# 原因？
veturのデフォルトフォーマッタがjs-beautify⇒prettierへ変更されたから？（参考URL内のコメントより推察）

# 今後
prettier-eslintの対応が予定されている？ようなのでそのうち直るかもしれない。

# 参考
https://github.com/vuejs/vetur/issues/476
Railsアプリで Bootstrap 4 を利用する

![rails-bootstrap.png](https://qiita-image-store.s3.amazonaws.com/0/141934/10e5407e-276a-f1dc-dd38-c09cf3b88fa1.png)

# 注意点
本投稿ではWebpackerがインストールされてない**Rails5以前のアプリ**を対象にBootstrap4を導入する手順を掲載しております。

Webpackerが標準となった**Rails6アプリ**にBootstrap4を導入する際には以下の記事がとても参考になりました🙇‍♂️
[RailsでBootstrapとFont\-AwesomeはWebpackerで今時っぽく使おう \- Qiita](https://qiita.com/rhistoba/items/f724dae231d7e28bf477)

# はじめに
Bootstrap 4のComponentsの中にちょうど使いたいと思っていた部品があったので、Bootstrap 4をRailsに導入する手順を確認しました。

# 公式サイト
<a href="http://getbootstrap.com/">Bootstrap · The most popular HTML, CSS, and JS library in the world.</a>

# 注意点
投稿時点でのBootstrapのバージョンは~~`v4.0.0-beta.2`~~ `4.1.1`です。

# gem
これまでrailsにBootstrapを導入する際には`bootstrap-sass`を利用してましたが、READMEに「Bootstrap 4では`bootstrap-rubygem`を利用してね」と案内がありました。

| Bootstrap | Gem | GitHub |
| --- | --- | --- | 
| 2~3 | bootstrap-sass | [twbs/ bootstrap-sass](https://github.com/twbs/bootstrap-sass) |
| 4 | bootstrap | [twbs/ bootstrap\-rubygem](https://github.com/twbs/bootstrap-rubygem) |

# 導入手順

`bootstrap-rubygem`のREADME通りに進めていきます。

## Gemfile

Gemfileで`bootstrap`を指定してインストールする。
Bootstrapは`jQuery`に依存するため、(デフォルトでjQueryがインストールされない)Rails5.1以上では`jquery-rails`もGemfileに追記する。

```ruby:Gemfile
gem 'bootstrap', '~> 4.1.1'
gem 'jquery-rails'
```

```shell-session
$ bundle install
```

**注意点**
`sprockets-rails`が`v2.3.2.`以上である必要がある。


```shell-session:`sprockets-rails`バージョン確認方法
$ bundle show |fgrep sprockets-rails
  * sprockets-rails (3.2.1)
```

## application.scss

Railsアプリの作成時に生成される`application.css`を`application.scss`にリネームするなどして、`.scss`(Sass構文の場合は`.sass`)ファイルを用意する。

```shell-session
$ mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss
```

`app/assets/stylesheets/application.scss`でbootstrapをimportさせる。

```ruby:/assets/stylesheets/application.scss
// Custom bootstrap variables must be set or imported *before* bootstrap.
@import "bootstrap";
````

**注意点**
- Sassファイルでは`*= require`、`*= require_tree`を削除する
- Sassファイルではインポートに`@import`を利用する
- Sassファイルで`*= require`を利用すると他のスタイルシートではBootstrapのmixinや変数を利用できなくなる

## application.js

Bootstrapと依存関係を`application.js`に追記する

```ruby:app/assets/javascripts/application.js
//= require jquery3
//= require popper
//= require bootstrap-sprockets
```

**補足**
- Bootstrapのtooltipsやpopoverは`popper.js`に依存している
- `bootstrap`の依存gemに`popper_js`が指定されているため新たにインストールは不要
- コンパイルを高速化したい場合は`bootstrap-sprockets`の代わりに`bootstrap`を指定する

# さいごに

Bootsrap3のサイトで利用していたコードを今回構築したBootstrap4環境に適用してみました。見た目に大きな変化はありませんが、4のほうが色合いが鮮やかですね。

![bootstrap3-4.png](https://qiita-image-store.s3.amazonaws.com/0/141934/ded6bd8a-843f-a0c0-487e-56a886fb4c55.png)
Atom で .eslintrc を json として開く


[file-types](https://atom.io/packages/file-types) というパッケージを使う。

リポジトリ Readme から、 json の Scope Names は `source.json` なので以下のように設定する。


```
"*":
  "file-types":
    "^.eslintrc$": "source.json"
```

`^` は正規表現の先頭マッチ。独自のエスケープ記号ではないので注意。
`$`をつけないと `.eslintrc.js` も json と認識してしまうので注意。
GCP機械学習セミナーに行ってきた（GCPUG Tokyo ML Day）

# 20171101_GCPUG_MLDay_メモ

## これ何

- 2017/11/1にgoogleにて開催されたGCPUGのセミナーメモです
- GCPUG Tokyo Machine Learning Day November 2017
- <https://gcpug-tokyo.connpass.com/event/67845/>
    - 一部資料やtogetterも公開されてます！
- blog枠としての責務

## 自己紹介

- ユーザ系SIer, 機械学習関連チーム所属
    - 基盤からコーディング、ビジネス適用まで一通りやっている
    - BigQueryに憧れるが東京リージョンに来ないかな
- GCPトライアル＆勉強中、一通りサービスの知識はある

## 発表メモ

### Machine Learning on GCP: from pre-trained APIs to models trained on custom data by Sara

- <https://github.com/sararob>
- GCPにおける機械学習サービスは大きく分けて2種類。
    - 訓練済みモデルを使えるAPI
    - 自分でモデルを作れるPaaS(MLEngine)
    - <https://cloud.google.com/products/machine-learning/?hl=ja>

- 各種APIは想像以上のことができていた
    - 動画のタイムラインにキーワードをつけて、検索できるようにする
        - <https://www.youtube.com/watch?v=mDAoLO4G4CQ>
        - 興味ある動画は探せても、いつ〇〇は出てくるんだ？みたいなのが短縮できるのは夢があるサービス
    - wikipediaなどネットに転がっている情報とくっつけてくれる
        - JKローリングの別名でも単一のentityIdで返してくれる
- QAにもあったが、APIにユーザデータを食わせられるサービスはやはり欲しい
    - 実業務の活用の壁の一つ。専門用語など。これができるようになると、既存の日本語自然言語系サービスがどうなるか？

### LT

#### NLAPIを前処理に使ってみよう

- <https://twitter.com/hayatoy82>
- 参加型リアルタイムデモあり。映えますね。
- cloud datalabの各種サービス連結性は便利そう

#### Googleが開発したニューラルネット専用LSI「Tensor Processing Unit」by Kazunori

- <https://twitter.com/hayatoy82>
- tensorflow と xPUの間にはXLAというレイヤーがあるため、意識せず使い分けられる
    - xPU = CPU,GPU,TPU
- 7ms応答を99%保証して欲しい、というGoogle社内ユーザの声にもこれで応えた
    - レスポンス超高速のML系サービスなので、伏せられてはいたがおそらく、、
- フルタイム版の資料をゆっくりみたかったです

#### Milesさんから一言

- <https://www.linkedin.com/in/milesward>
- クラウドの10年前の段階が今の機械学習。これからだよ！
  - 最初はうまく動かないかも。暖かい目で見守ってフィードバックして
  - 今までの既存技術だって通ってきた道
  - 今からやっとけば食いっぱぐれない

### Cloud ML Engine by Jing Jing Long

- <https://www.linkedin.com/in/jing-jing-long-b8b36a84>
- Cloud ML Engine は Machine Learning as a Service
    - トレーニング、モデル管理、予測までをサービスで提供
    - TFはバージョンの更新が早いので、runtimeのバージョン対応追随は期待
    - ハイパーパラメータチューニング、バージョン管理など実務の辛さへのGoogleなりの解答だった
        - オンプレでやってますけど辛いからついついサボりがち
- QAぶっちゃけ系
    - python3対応、レスポンスや謎の裏基盤など。。
    - TFXで実現するML-opsにも組み込まれる？
        - <http://stevenwhang.com/tfx_paper.pdf>
        - Fig.1の機械学習プラットフォーム概念図が素敵
    
## 所感

- 機械学習を一連で行う上で、とにかく便利になっていきそうなGCP
    - datalabがjupyterにGCPサービス連結が集約されていきそう。
- 現在やろうとしている案件がAWSを使う前提にしているが、GCPも試せれば良いなと感じた
    - SOMPOの中林さんのような基盤を作りたい
        - <http://www.atmarkit.co.jp/ait/articles/1708/29/news031_2.html>
- 英語力。キレイな英語をみなさん話されていたので、頑張りたい
    - 最後尾の方だと少し聞こえづらかったり、見づらかったりしたので次はもう少し前に行こう
【Playcanvas】Image Elementのフェード処理【2D】

【Playcanvas】Image Elementのフェード処理【2D】

[チュートリアル](https://developer.playcanvas.com/ja/tutorials/flappy-bird/)

の「fade.js」では3Dオブジェクトにアタッチしたマテリアルのフェードアウト処理を行っています。
今回はこのスクリプトを改造し2D Screen上で表示する「Image element」のフェードアウト処理を実装します。
(タイトル画面やUIでは「Image element」の方が取り扱いやすいため調査した次第です)

「Image element」では「Texture」「Material」のいづれか一方を指定します。
両方とも対応した形になります。

※「Material」を使う場合はアタッチした「Material」の「OPACITY」の「Blend Type」を「Alpha」にしてください。
この指定がないと透過度が変わらないからです。


```js

var Fade = pc.createScript('fade');

Fade.attributes.add('event', { type:'string' });
Fade.attributes.add('type', {
    type: 'number',
    enum: [
        { 'In': 0 },
        { 'Out': 1 },
        { 'InOut': 2 }
    ]
});
Fade.attributes.add('duration', { type:'number', default: 0.25 });

// initialize code called once per entity
Fade.prototype.initialize = function() {
    var app = this.app;

    this.timer = 0;
    app.on(this.event, function () {
        this.timer = this.duration;
    }, this);
    
    this.displayType = 'none';
    this.model = null;
    
    this.model = this.entity.element;

    if (this.entity.element.material.name === 'Untitled') {
        this.displayType = 'texture';
    } else {
        this.displayType = 'material';
    }
};

// update code called every frame
Fade.prototype.update = function(dt) {
    if (this.timer > 0) {
        this.timer = Math.max(this.timer - dt, 0);

        // Normalize
        var x = (this.duration - this.timer) / this.duration;
        var y;

        switch (this.type) {
            case 0:
                y = x;
                break;
            case 1:
                y = 1 - x;
                break;
            case 2:
                y = Math.abs((x / 2 + 0.25) % 0.5 - 0.25) * 4;
                break;
        }
        
        var enabled = false;
        
        enabled = this.model.enabled;
        
        if (enabled && y === 0) {
            this.model.enabled = false;
            y = 1;
        } else if (!enabled && y > 0) {
            this.model.enabled = true;
        }        
        
        switch (this.displayType) {
            case 'material':
                var material = this.model.material;
                material.opacity = y;
                material.update();                
                break;
            case 'texture':
                this.model.opacity = y;
                break;
            default:
                break;
        }
    }
};

```
Circle-CI 2.0のcron triggerを使って、定期実行をする

Circle-CIでいつのまにcron実行する機能が追加されていたので試した。

* https://circleci.com/docs/2.0/configuration-reference/#triggers
* https://circleci.com/blog/manual-job-approval-and-scheduled-workflow-runs/

TravisCIには少し前から入っていた機能。

* https://docs.travis-ci.com/user/cron-jobs/

Circle-CIの場合、TravisCIほとさくっと使える感じではなかったのでメモ

# どんな時に使えるか？
例えばこんなユースケースが思いつく

* E2Eなど重くて全branchで実行するには辛いもの
* 外部のAPIに引きづられて落ちてないかのテスト
* masterを定期的にstagingと同期するdeploy処理

今回は一番上の「branchにCIは回したい、でも重いテストだけは一日一回にしたい」みたいな場合で考えてみる

# config

とりあえず最終的にどうなるかを記載。

```.circleci/config.yml
version: 2
jobs:
  test: # 普通のテスト
    docker:
      - image: node:8
    steps:
      - checkout
      - run: npm run test
  heavy_test: # 重いテスト
    docker:
      - image: node:8
    steps:
      - checkout
      - run: npm run heavy_test

workflows:
  version: 2
  normal_test_workflow:
    jobs:
      - test
  nightly_workflow:
    triggers:
      - schedule:
          cron: "0 1 * * *" # UTCで記述。この場合は朝10時
          filters:
            branches:
              only:
                - master
    jobs:
      - heavy_test
```

ポイントは下記の通り

* Circle-CIのconfigは2.0向けに書く必要がある
    * workflowを利用するので、workflow形式で。
* `trigger`の処理は、`job`ではなく、`workflow`に対して設定する必要がある。
    * 今回の場合だと、通常のbranch向けのjobとworkflowと、一日一回実行するjobとworkflowを記述する必要がある
    * 定期実行が通常のテストと同じで良いなら、jobを一つ、workflowだけ２つ書く感じになる。
    * それぞれでの共通化については、以前別記事を書いたので、必要があれば参考にしていただきたい
        * https://qiita.com/inuscript/items/3568690b5da29ab034dc
* Cronは普通にcrontab形式。ただし **UTC** なので注意。
* 記述を間違うと、失敗通知すら来ず無視されるのつらい
Codilityの練習問題を解きました。(FrogJmp)あと、Codilityを使う上での注意点も書きました

<h1>問題について</h1>
問題文はそのままここに書いてはいけない、(英文でした)自分なりの日本語を書います。
Q.カエルはとある場所に行きたい。カエルは現在X地点にいて、Y以上の地点に行きたい。カエルはジャンプ(移動)するたびにD動く。

<h1>初めてのCodilityで苦戦したこと</h1>
問題はすぐに理解できたので自分の開発環境でプログラムを書いて無事正しい答えにたどり着いたのですが、なぜかCodilityでの環境では異なる値が出力されるので何時間も悩んだ。

自分の環境ではまずループ使った方法でやってみたんですけど、Codilityでの環境ではなぜかSolution関数が1度しか呼ばれないのが自分の開発環境とCodilityで出力される値が異なる原因だった。

何故か関数が一度しか呼ばれないので、多分パフォーマンスの観点から呼び出し回数が制限がされているのだろうと予想して、やっぱり関数を何度も呼び出すのはパフォーマンス的にまずいのかと思って、指定されているSolution関数の呼び出しを一回だけにしてその中でループさせると無事に正しい値が出力されたが、新たに問題が発生した。

<h1>パフォーマンステストの存在</h1>
ループを使ったプログラムを提出すると、スコアは44%でした。
詳細を見ると、Correctness testsに関しては全問正解。
しかし、Performance testsに関しては「TIMEOUT ERROR 」
という結果が出ていました。
やっぱりループ使うのはパフォーマンス的にまずかったなぁ、、、って思って、再チャレンジしました。

答えはここには書きませんが、ループしないで答えを出す書き方をしました。計算の部分は一行のプログラムでできました。

<h1>結果</h1>
出力結果とパフォーマンスで100点出ました。
点数の仕組みを見たら、様々な値を自分が書いたプログラムに代入して、どのパターンでも正しい値が出力されるプログラムかどうかで点数は変わるので、どの値を入れられても正しい出力が出るようなプログラムを書いて、パフォーマンスの良いプログラムを書ければ100点になると思います。
<img width="1160" alt="スクリーンショット 2017-11-03 19.28.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/179803/1ab2ac6d-c6a1-7904-fe9e-ff8a3d471ee4.png">

<font color="DeepPink">ちなみに、他にも提出をストップされる原因がありました。</font>
<h1>余計な部分を無くさなくてはならない</h1>
ようやく正しい値が出力されて喜んだのだが、また赤い文字が。
「codility Producing output might cause your solution to fail performance tests. You should remove code that produces output before you submit your solution.」
Google翻訳使ったら、
「出力を生成すると、ソリューションがパフォーマンステストを失敗させる可能性があります。ソリューションを提出する前に、出力を生成するコードを削除する必要があります。」
↑
<font color="DeepPink">System.out.printlnなどの余計な出力がある時に表示されました。</font>


<h1>感想</h1>
このテストで求められていることは、
1.正しい値の出力
2.パフォーマンス
この二つを満たしているプログラムを頑張って書く必要があるので、もっと難しい問題がいっぱいあるそうなので、自分にはもっと勉強が必要だと感じました。
seabornのFacetGridとfactorplotについて

Pythonでのデータ視覚化の際に、seabornのfactorplotやFacetGridをよく用いるが、使い分けがイマイチ覚えられないので、まとめてみる。


## seaborn.factorplot
- 後述のFacetGridとcategorical plotを組み合わせた関数
- デフォルトではpoint plotを描画するが、"kind"によりbox plot, violin plot, bar plot, strip plotを指定可能
- グラフ要素どうしの距離が近いほど比較しやすいので、最も重要な比較は"hue"を用いるべき。二番目の比較には定量的な軸を共有すべき（垂直方向に並べるプロットなら"col", 水平方向なら"row"）
- 元のプロット関数を直接使う場合と違い、data frameはlong-formである必要（変数名を示す列と、値を示す列にまとめた形式。pandas.meltで変換可能）

### 主な引数
x, y, hue : 変数名
data : DataFrame
row, col : gridの作成に用いる変数名（optional）
col_wrap : int（optional）、列数を指定する
kind : {point, bar, count, box, violin, strip}、プロットの種類
share{x,y} : bool(optional)、x軸またはy軸を行内、列内で共有するか

### コード例
公式ドキュメントを参照。
https://seaborn.pydata.org/generated/seaborn.factorplot.html


## seaborn.FacetGrid

- FacetGridはPandas DataFrameを特定の構造でmatplotlib figureと結びつけるオブジェクト
- ある変数の異なる水準で条件付けられた同じ関係を表す複数の軸のプロットを描くために用いられる。グリッドの行、列に変数を対応させ、プロットの要素に異なる色を用いることで、最大で3つの変数による条件づけが可能

<基本的な流れ>
datasetとグリッドを構成する変数でFacetGridオブジェクトを初期化
→ FacetGrid.map()またはFacetGrid.map_dataframe()によりそれぞれのサブセットにプロット関数を適用

### 主な引数
data : （long-formの）DataFrame
row, col, hue : strings、グリッドの各部に描かれるデータのサブセットを決定する変数
col_wrap : int（optional）、列数を指定する
share{x,y} : bool(optional)、x軸またはy軸を行内、列内で共有するか

### コード例
公式ドキュメントを参照。
https://seaborn.pydata.org/generated/seaborn.FacetGrid.html#seaborn.FacetGrid

こちらも参考になる。
https://seaborn.pydata.org/tutorial/categorical.html
https://seaborn.pydata.org/tutorial/axis_grids.html

※ 棒グラフを作成する場合
factorplot()を用いるとfacet上の変数の順序の一致が保証されるので、FacetGridを直接用いるよりも安全。
Swiftの配列から部分列を取り出しすとArray型ではなくArraySlice型になる

## 環境

- Swift 3.2.0
- XCode: 8.3.1

## Q. String配列からRangeで取り出した部分列の型は[String]ではない :question: 

Swift 3で、配列からRangeオブジェクトを使って部分列を取り出す場合、以下のようなコードで実現可能です。

```map1.swift
let strs: [String] = [ "a", "b", "c", "d" ]
print(strs[0..<2]) // ["a", "b"]
```

次に取り出した部分列を変数へ代入することを考えます。
普段自分はSwiftを書くとき、型推論を使わずなるべく明示的な型指定をするクセがありました。
また部分列なので、**型も同じString配列だろうと思って次のようなコードを書いたところ**

```map.error.swift
let strs: [String] = [ "a", "b", "c" ]
let partOfStrs: [String] = strs[0..<2] // error: ambiguous subscript with base type '[String]' and index type 'CountableRange<Int>'
```

と怒られてしましました...

```
error: ambiguous subscript with base type '[String]' and index type 'CountableRange<Int>'
```

とは一体なんだ... :question:

普段Rubyなどを書いていて **String配列の部分列の型は当然 `[String]`** だろうという感覚だったので、なぜエラーになるのかわからずハマってしまいました :sweat: 

## A. Swiftの配列はArray型、Rangeで取り出された部分配列はArraySlice型

エラーを見ると取り出した部分列が `「[String]ではない」` と言われています。

そこで念のため型を調べてみます。

```type.swift
let strs: [String] = [ "a", "b", "c", "d" ]\
print(String(describing: type(of: strs)))
let partOfStrs:  = strs[0..<2]
print(String(describing: type(of: partOfStrs)))
```

結果

```shell-session
> Array<String>
> ArraySlice<String>
```

となり、 **ArrayではなくArraySlice** という型になっていました。

**実はSwiftでは配列から部分列を取り出した場合、ArraySliceという型でオブジェクトが生成されます :bulb:**
このArraySliceは**元のArrayとほぼ同じインターフェイスを持ちながら、実態としては元のArrayオブジェクトへのViewになっています。**

[Apple公式](https://developer.apple.com/documentation/swift/arrayslice) を見ると

> The ArraySlice type makes it fast and efficient for you to perform operations on sections of a larger array.　Instead of copying over the elements of a slice to new storage, an ArraySlice instance presents a view onto the storage of a larger array. And because ArraySlice presents the same interface as Array, you can generally perform the same operations on a slice as you could on the original array.

_訳: ArraySlice型は大きな配列の部分列に対する処理を高速で効率的にする。新しいストレージに要素をコピーする代わりに、ArraySliceインスタンスは元の大きな配列へのViewを表す。かつ、ArraySliceはArrayと同じインターフェイスを持っているので、大抵の場合において元のArrayにするのと同じような処理がスライスに対しても可能である。_

とあります。
なので**普段使っている分にはArrayとArraySliceの違いを気にする必要はない**ようです。

ただし先程のコードのように型推論を使わず、明示的に代入すると当然型が違うということで怒られていたわけですね :sweat_smile: 
細かいことですが、他の言語から来るとハマって「:question:」となるのでメモしておきます。

参考
---

- [ArraySlice \- Swift Standard Library \| Apple Developer Documentation](https://developer.apple.com/documentation/swift/arrayslice)
- [Swiftで配列から値を取り出そうとした時にエラー吐いた – てくのろ日記](https://www.nukoneko.info/blog/?p=483)
- [arrays \- Ambiguous Use of Subscript in Swift \- Stack Overflow](https://stackoverflow.com/questions/33642059/ambiguous-use-of-subscript-in-swift)
新人にPostgreSQLのシーケンスを理解してもらう

## 1. はじめに

新人向けの研修でPostgreSQLのシーケンスについて説明した内容です。シーケンスを使ったことがない人には役立つかと思います。新人向けに他にも記事を書いていますので興味のある方は参照ください。

* [新人に悲観ロックによる排他制御を体験してもら](https://qiita.com/5zm/items/cc33fa9f591892222153)
* [PostgreSQLでは以上、以下（=>、=<）が使えない！？](https://qiita.com/5zm/items/e418e3c17c489bb584b6)

## 2. シーケンスとは？

シーケンスとは連番となる一意な整数を生成するデータベースのオブジェクトです。
ちなみに、テーブル、ビュー、インデックス等もデータベースのオブジェクトです。
一般的にシーケンスは、ユーザIDや登録番号等の主キーを生成する際によく利用されます。
シーケンスはトランザクションのコミットやロールバックに関係なく、採番（取得）した時点でインクリメントされます。

## 3. シーケンスの作り方

シーケンスは`CREATE SEQUENCE`文で作成します。
ここでは1から99999999までの連番を生成する「CUSTOMER_CODE_SEQ」というシーケンスを作成してみます。

```sql:シーケンスを作成するDDL
CREATE SEQUENCE CUSTOMER_CODE_SEQ
    INCREMENT BY 1
    MAXVALUE 99999999
    START WITH 1
    NO CYCLE
;
```

> NO CYCLEが指定された場合、シーケンスの限界値に達した後のnextval呼び出しは全てエラーになります。
> https://www.postgresql.jp/document/9.3/html/sql-createsequence.html

## 4. シーケンスを取得する

シーケンスの取得には「`nextval`」関数を利用します。
シーケンス名を文字列として指定する点に注意してください。

```sql:シーケンスを取得するSQL
-- nextval('シーケンス名')
select nextval('customer_code_seq')
```

シーケンスは整数なので0埋めしたい場合やプレフィックスを付与したい場合、to_char関数や文字結合と合わせて利用します。

```sql:フォーマットを指定してシーケンスを取得するSQL
-- 0埋め8桁の形式で取得したい場合(例：00001234)
select to_char(nextval('customer_code_seq'), 'FM00000000')

-- プレフィックスとして'CSM'を付与した場合(例：CSM00001234)
-- select 'CSM' || to_char(nextval('customer_code_seq'), 'FM00000000')
```

## 5. シーケンスの現状を確認する

シーケンスの現状を確認したい場合、テーブルやビューのようにfromにシーケンスを指定して参照します。

```sql:シーケンスの現状を確認するSQL
-- select * from シーケンス名
select * from customer_code_seq
```

ここで注目すべきは現在のシーケンス値を示す`last_value`カラムと、シーケンス値の増分を示す`increment_by`カラムです。
次に取得するシーケンス値は「`last_value + increment_by`」になります。
仮にlast_valueが23、increment_byが1の場合、次に取得するシーケンス値は24になります。

## 6. シーケンスの削除

シーケンスの削除は`DROP SEQUENCE`文で行います。

```sql:シーケンスを削除するDDL
-- drop sequence シーケンス名
drop sequence customer_code_seq;
```

## 7. さいごに

今回はPostgreSQLのシーケンスについて説明しました。もちろんOracleなど他のRDBMSにもシーケンスは存在します。しかしRDBMSによってシーケンスの取得方法や確認方法は異なります。実際のシステム開発でもシーケンスはよく利用されるので、利用できるようにしていきましょう。
OpenVXも深層学習をとり込もうとしている(画像認識のAPIへの標準化)


[OpenVXって実装がされてきているんだ(画像認識のAPIへの標準化)](https://qiita.com/nonbiri15/items/b6007557fb995f6349e0)
に追記しました。

ニューラルネットワークの技術をOpenVXに取り込むための標準化をしようとしているらしいことをOpenVXのページのアナウンスに見つけたので追記してみました。

情報源
https://www.khronos.org/openvx/
PHPでautoload何それ美味しいの？という案件があったのでautoloadについて調べてみた。

# 概要
PHP5.3より以前のコードで動いているシステムを知り合いにみてほしいと言われ、require_once地獄を味わったので発狂しそうになったので、こんな便利なもんはいつからできたんだ！？となって調べてみた。
間違いなどがあれば、コメントまで。

# そもそもAutoloadとは？

オートロードとは「自動」でファイルを「ロード」してくれる仕組みのこと。

PHPではバージョン5から使われ始めた。

### PHP 4


``` php
require_once('require.php');
```

などといったように明示的に記述をすることで他ファイルのクラスやメソッドを利用していた。
他にも、「require」,「include」などがある。


### PHP 5.0.x
 __autoload() が使えるようになった。ただしこの時点ではまだ問題があり、
classの指定が面倒だといった問題があった。


### PHP 5.1.2 ~
#### spl_autoload_register() 

spl_autoload_register — 指定した関数を __autoload() の実装として登録する。
前よりもclassの指定などが楽になり、使いやすくなった。






# 参考
記事を書く上で以下の記事、サイトを参考にしました。
ありがとうございました。

[【PHP Document】spl_autoload_register](http://php.net/manual/ja/function.spl-autoload-register.php)

[PHPのオートロード(autoload)](https://qiita.com/atwata/items/5ba72d3d881a81227c2a)
(atwataさん)

[PHP で、spl_autoload_register を使って、require_once 地獄を脱出しよう](https://qiita.com/misogi@github/items/8d02f2eac9a91b4e6215)という(misogi@githubさん)
Flask  メモ　２

*ブラウザー側から配列をもらいたい*


##.ajax（）


`bad request 400` と苦戦した結果

### JavaScript側

```javascript

$("#finish").on('click',function(){
        $.ajax({
            url:"/finish",
            type:"POST",
            data:JSON.stringify(arrObj(action)),
            contentType: "application/json; charset=utf-8",            
            dataType: "json",
            traditional: true,

            success:function(){
                console.log(sent);
            },

            error:function(){
                console.log(err);
            }
        })
    });
```
### Python側

```python3

@app.route('/finish',methods=['POST'])
def getData():
    if request.method == 'POST':
        data = request.get_json(force=True)
        print(data)

    return render_template("result.html")

```