OmniAICreator/Qiita-1.07M huggingface dataset:
IPアドレスで打線組んでみた

## 初めに
   
こんにちは。[CYBIRDエンジニア Advent Calendar 2017](http://qiita.com/advent-calendar/2017/cybird)
18日目の@cy-katsuhiro-miuraです。17日目は@zonさんの[ArduinoとかRaspberry Piの入門キットがうまく組み立てられなくて入門できない問題](https://qiita.com/zon/items/e0e3b30423adb5b5b2f5)でした。僕も電子工作キットを買ってみたものの、LEDをピカピカさせて満足して終わる事が多いので、とっても共感できました！

----

さて、皆さんこんにちは。
今年のペナントレースもCSもいろんなドラマがあり、盛り上がりましたね。

ところで今年の前半"IPアドレス打線"というのが、ちょっと話題になっていたのご存知ですか？

皆さん思いますよね。　
「IPアドレス打線ってなに？」　
https://www.google.co.jp/search?q=IPアドレス打線

詳しくはググっていただきたいのですが、要は各選手の打率が.255以下というのをIPアドレス打線というようです。
上手いこと言いますね。

でも僕は初めてこの単語を見た時に、自分の好きなIPのアドレスで打線を組むやつだと思いました。
昔よくやりましたよね？山手線の駅で打線組む、とかおにぎりの具で打線組むとか。

まあ、そんなわけで、勝手に選んだIPアドレスで打線組んでみました。


１中　127.0.0.1/32
２遊　8.8.8.8/32
３二　192.168.0.0/16
４三　10.0.0.0/8
５右　255.255.255.255/32
６一　172.16.0.0/12
７捕　169.254.0.0/16
８投　192.0.2.0/24
９左　192.88.99.0/24

----

# １中　127.0.0.1/32
ローカルのループバックアドレス。
IPアドレス界のリードオフマン。
彼にPingが通らないようであればそもそもネットワーク以前の問題。

# ２遊　8.8.8.8/32
GoogleのPublic DNSのアドレス。
とりあえずDNSをここに設定しておけば、名前解決。
確実な進塁を望むなら。

# ３二　192.168.0.0/16
クラスCプライベートアドレス
小さめなネットワークならココで完結できるはず。
まずは１点。

# ４三　10.0.0.0/8
クラスAプライベートアドレス
彼に任せておけば、だいたいどんな環境でも大丈夫という安心感。
長打力ピカイチ。

# ５右　255.255.255.255/32
ブロードキャストアドレス
塁が埋まっていても、全ノードに一掃。

# ６一　172.16.0.0/12
クラスBプライベートアドレス
65534個までいけるという中距離ヒッター。
でもあまり登用されない印象。覚えづらいし。
クラスAでサブネットきればいいじゃん。

# ７捕　169.254.0.0/16
APIPAアドレス
DHCPないときに自動的に割り振られるアドレス。
Windowsオリジナル機能かと思いきや、RFCでもちゃんと定義されてる。
[RFC 3927](https://tools.ietf.org/html/rfc3927) Dynamic Configuration of IPv4 Link-Local Addresses
まあ最悪こいつで通信できるようにしておくってのはバッドノウハウなのか？
でも意外とこれでネットワーク構築してるご家庭とかあるんじゃないか。

# ８投　192.0.2.0/24 
ドキュメント用アドレス
[RFC5737](https://tools.ietf.org/html/rfc5737) IPv4 Address Blocks Reserved for Documentation
RFCで定義されてるので、使っちゃいけないやつ。
198.51.100.0/24 , 203.0.113.0/24 とかもそれ。
サンプルとかドキュメントにうっかり実IPアドレス書いちゃって、よく分からない人がホントにそれ使っちゃったらヤバイ、みたいなときにはこのIPアドレス書いておきましょう。

# ９左　192.88.99.0/24
IPv6 to IPv4 リレーアドレス
IPv6の時代がくる、そう思っていた時期が僕にもありました。
いちおうRFCでも定義されてる
[RFC3964](https://www.ietf.org/rfc/rfc3964.txt) Security Considerations for 6to4
こんなんまだまだ使わないだろ。


## 最後に
どうですか？
もちろん異論は認めますので、異論ある方はオリジナル打線組んでみてください。
ここにあげたアドレスは全部whois引けると思うので興味ある方はwhoisコマンド叩いてみても面白いかと思います。

[CYBIRD エンジニア Advent Calendar 2017](http://qiita.com/advent-calendar/2017/cybird) 明日は、爽やかスマイルでうちの娘達からも絶大な人気を得ている@cy-kenta-takahashi さん（いつも遊んでくれてありがとう:bow:）の[非エンジニア職の新卒に研修で技術とは何かを伝えるにはどうしたらいいか](http://www.cybird.co.jp/recruit/engineer/blog/advent-calendar2017cybird1219/)です！楽しみですね！
【C言語】glib g_strv_length()の使い方を盛大に間違えた話

# はじめに

glibで文字列の二次元配列を扱っていて、便利な関数がある！と思ったら盛大に使い方を間違った。
同じ過ちを、人類が二度と繰り返さないためのメモ。
問題に遭遇してから、解決までを時系列で書くので、g_strv_length()の使い方をまず知りたい人は、下の方から見てね。

# g_strv_length()

[g_strv_lenth API仕様](https://developer.gnome.org/glib/stable/glib-String-Utility-Functions.html#g-strv-length)
> guint g_strv_length (gchar **str_array);
> Returns the length of the given NULL-terminated string array str_array.
> Parameters:
>   str_array a NULL-terminated array of strings
> Returns length of str_array.

ふむふむ、NULL文字で終端された文字列の配列を渡すと、その長さを返してくれるとな！
（実はこの時点で間違っているのだが、言い訳は後でやる）

# やりたかったこと

read onlyなデータから、num個の文字列を読みだして、char型の二次元配列で色々処理したい。
とりあえず、自分の持ち物でないread_only_dataから、自分の持ち物であるstr_arrayに文字列をコピーしてくる。

```C
  gchar **str_array = g_new(gchar*, num);
  for (gint i=0; i<num; i++) {
    str_array[i] = g_strdup(read_only_data[i]);
  }
```

これ以降、str_arrayをg_strv_length()に渡してあげれば、numが返ってくるはずだ！
C言語で快適文字列配列ライフを満喫するぞ！

# とりあえず使ってみた結果

とりあえず、要素数が3のデータを用意してあげて、試してみる。
str_arrayにデータを詰めて、g_strv_length()の結果を見てみる。
（実際は、googletestでテストしたけど、再現が面倒なので省略）

```C
  g_printf("The length of array is %d\n", g_strv_length(str_array));

  g_strfreev(str_array); // 使った後は開放しないとね！
```

これで、*The size of array is 3*と出力され・・・
どーん！

```
./strv
The length of array is 6
Segmentation fault (core dumped)
```

長さが6と出力された上、g_strfreev()でセグメントエラーになった…。
どうしてこうなった…。

# 改めてAPI仕様を眺める

> Returns the length of the given NULL-terminated string array str_array.

怪しいのは、*NULL-terminated*なのだが、文字列なので、NULL文字終端ってことだよなぁ…。
同じページのAPIリファレンス内で、文字列をコピーするg_stpcpy()もnull-terminated stringって書いてあるし。
わからん…。

[g_stpcpy API仕様](https://developer.gnome.org/glib/stable/glib-String-Utility-Functions.html#g-stpcpy)
> gchar *g_stpcpy (gchar *dest, const char *src);
> Copies a nul-terminated string into the dest buffer

# 分からん時はソースを読もう

OSSでわからん時はソースを読むのが手っ取り速い。
さっそくglibのソースコードを拾ってくる。
どうやら、gstrfuncs.cに実装されているらしい。
どれどれ。

```C
guint
g_strv_length (gchar **str_array)
{
  guint i = 0;

  g_return_val_if_fail (str_array != NULL, 0);

  while (str_array[i])
    ++i;

  return i;
}
```

**ってNULL文字終端の文字列配列じゃなくて、NULLポインタで終端されている文字列配列を期待しとるやないかーい！**

念のため、strvを複製するg_strdupv()の実装を確認してみる。

```C
      i = 0;
      while (str_array[i])
        ++i;

      retval = g_new (gchar*, i + 1);

      i = 0;
      while (str_array[i])
        {
          retval[i] = g_strdup (str_array[i]);
          ++i;
        }
      retval[i] = NULL;
```

i+1の領域を確保して、最後にNULL詰めてるね、間違いないね。

# 正しい使い方

```C
  // NULL-termination requires +1 length 
  gchar **str_array = g_new(gchar*, num+1);
  gint i = 0;
  for (i=0; i<num; i++) {
    str_array[i] = g_strdup("test");
  }
  str_array[i] = NULL; // NULL pointer terminated.
  g_printf("The size of array is %d\n", g_strv_length(str_array));

  g_strfreev(str_array);
```

無事動いた！

```
./strv
The size of array is 3
```

# 反省

同じページ内で、NULL文字終端とNULL pointer終端をどちらも、Null-terminatedと表現してあったので混乱した。
でも、よくよく考えると、NULL文字終端は、対象が*a string*になっていたし、NULL pointer終端は、対象がarrayだった。
そもそも、NULL文字終端の文字列配列から、配列の長さを取るのって、無理じゃない？という警鐘が頭の中で鳴っていたのに、良く調べずに使おうとしたのが良くなかった。反省！

みなさんもお気をつけて！
Pythonの内包表記のスピードについて

# Pythonの内包表記の書き方とそのスピードについて
内包表記自体の速さについてはこちらを参照
[Pythonのリスト内包表記の速度 - Qiita](https://qiita.com/intermezzo-fr/items/43f90e07e4cebe63aeb6)


例えばこういう長さがNのリストがあったとします。

```python3
N = 10**8
foo = [None for i in range(N)]
```

新たにfooと同じ長さのリストを作るときに、
こうやって書くのか

```python3
bar = [None for _ in range(len(foo))]
```

それともこうやって書くのか

```python3
bar = [None for _ in foo]
```
好みの話です

ちょっと内包表記とは違いますが中身がすべて同じものに限って言えばこういう書き方もできますね。

```python3
bar = [None] * len(foo)
```


## 可読性について
**barの長さはfooと同じだよ**ってメッセージがコードから伝わってくるのは`range(len(foo))`のような気がします。

## 速いのはどちらなのか
比べてみましょう

```python3

import time

n = 10**8
foo = [None for _ in range(n)]

begin = time.monotonic()
bar = [None for _ in range(len(foo))]
end = time.monotonic()
print('len version {}'.format(end - begin))

begin = time.monotonic()
bar = [None for _ in foo]
end = time.monotonic()
print('iter version {}'.format(end - begin))

begin = time.monotonic()
bar = [None] * len(foo)
end = time.monotonic()
print('* version {}'.format(end - begin))
```

## 結果
```
len version 2.118436049000593
iter version 1.4381394569936674
* version 0.32011151099868584
```

`range`と`len`で括らないのほうが1.5倍くらい速いみたいです。
`len(foo)`の部分が時間かかってるんでしょうか。
空のリストとか作るときなら`[]*`の書き方が速くて良さそうです。
他にもこんな書き方あるよっていう人がいたら教えてください。
リダイレクトとして 2&>1 を使うと何が起きるのか?

# はじめに

初心者の頃によく混乱した Bash の「標準エラー出力を標準出力に流す」記法 `2>&1` についてです。
当時は意味もわからず間違って `2&>1` とかやってましたが、今改めてこの `2&>1` について挙動を確認してみます。

# そもそも `2>&1` とは

* 標準エラー出力 `2` を 標準出力 `1` と同じ設定にする (と覚えてます)
  * 結果、2つとも同じところ (標準出力) に出力される

# 叩いてみる

手っ取り早く標準エラー出力を出せる以下コマンド (?) を使います。

```bash
$ aaa
-bash: aaa: command not found
```

## :thumbsup_tone1: 正しい方法 `2>&1`

```bash
# 標準出力をファイルに保存
$ aaa > /tmp/stdout_check.log 2>&1
$ cat /tmp/stdout_check.log
-bash: aaa: command not found
```

確かに標準エラー出力が標準出力と一緒にファイルへリダイレクトされています。

## :thumbsdown_tone1: 間違った方法 `2&>1`

```bash
$ aaa > /tmp/stdout_check.log 2&>1
$ cat /tmp/stdout_check.log 
$
```

ファイルは空っぽ。
試しにファイルへのリダイレクトをなくしてみます。

```bash
$ aaa 2&>1
$
```

当然ながら何も出力されません。
ここでカレントディレクトリを見てみると

```
$ ls -l 1
-rw-r--r-- 1 togawa togawa 30 11月 24 13:57 1
$ cat 1
-bash: aaa: command not found
```

`1` というファイルができています。どうやら `1` というファイルにリダイレクトされてしまったようです。

# もう少し紐解いてみる

## 引数をとるコマンド grep で試す

```bash
$ echo test | grep test 2&>1
$ cat 1
grep: 2: No such file or directory
```

grep を使い test という文字列を検索してみます。
 `2: No such file or directory` というエラーメッセージを得ました。
想定では標準入力が検索対象となるはずでしたが、実際は `2` というファイルを読み込もうとしていたようです。

ここで、上記コマンドをスペースで整形すると以下のようになります。

```bash
$ grep test 2 &>1
```

紐解くと

* `grep test 2`: test という文字列を 2 というファイルから検索
* `&>1`: 標準エラー出力と標準出力を 1 というファイルにリダイレクト
  * `>1 2>&1` したのと同じ

となります。
つまり、`2&>1` は「2 という引数」と「&>1 というリダイレクト」に分解されることになります。

`aaa 2&>1` のときも、実は `aaa` に `2` という引数を与えていたのでした。

# まとめ

* 標準エラー出力を標準出力に流すための正しい書き方は `2>&1`
* 間違った書き方 `2&>1` は「2 という引数」と「&>1 というリダイレクト」に分解される
  * 標準エラー/標準出力いずれも "1" というファイルに書き込まれてしまう
* これに限らず、何事も丸暗記ではなくて根本から理解して使うと安全

# 参考

* [bashで標準出力と標準エラー出力の一括リダイレクト](https://qiita.com/r_plus/items/41fb31285fb64fb4be85)
NativeScriptで「Invalid bitcode signature」というビルドエラーが出たときの対処

NativeScriptで、iOSのモジュールをビルド時に以下のエラーメッセージが出たときの対処法です。
使っているプラグインでBitcodeをONにしているものがあると出るようです。

```
error: Invalid bitcode signature

clang: error: linker command failed with exit code 1 (use -v to see invocation)
```

そんなときは、以下のプラグインをインストールしましょう。
https://github.com/Essent/nativescript-disable-bitcode

以下のコマンドをプロジェクトルートで打ってインストールするだけです。

```
tns plugin add nativescript-disable-bitcode
```

これで、bitcodeがすべて無効化され、無事にビルドが通るようになります。
仮想仔猫ゲーム CryptoKitties のコントラクトを読んでみる

公式的なリポジトリを見つからなかったが、etherscanから直接にコントラクトソースを見えるので、読んでみます。

```javascript
contract Ownable
contract ERC721
contract GeneScienceInterface
contract KittyAccessControl 
contract KittyBase is KittyAccessControl
contract ERC721Metadata 
contract KittyOwnership is KittyBase, ERC721
contract KittyBreeding is KittyOwnership
contract ClockAuctionBase 
contract Pausable is Ownable 
contract ClockAuction is Pausable, ClockAuctionBase
contract SiringClockAuction is ClockAuction
contract SaleClockAuction is ClockAuction 
contract KittyAuction is KittyBreeding
contract KittyMinting is KittyAuction
contract KittyCore is KittyMinting
```
クラス図でまとめるとこんな感じ。
<meta property="og:image" content="https://qiita-image-store.s3.amazonaws.com/0/4777/a3373f16-f127-51d5-2d24-ac2715fa93ac.png">

<img width="849" alt="スクリーンショット 2017-12-14 19.42.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/4777/a3373f16-f127-51d5-2d24-ac2715fa93ac.png">

## 気になる箇所
- 全体：クラスを細かく分ける方針で実装されている
- 詳細の読解はこの辺が詳しい[How to Code Your Own CryptoKitties-Style Game on Ethereum](https://medium.com/loom-network/how-to-code-your-own-cryptokitties-style-game-on-ethereum-7c8ac86a4eb3)
- ERC721：トークン１つ１つにユニークであり、別のトークンと交替できないタイプのトークン。この猫とあの猫は、別々の特徴を持っていて、価値も違う。ゲームでよく使われそうな仕組み。
- 猫の外観などの画像は、やはりブロックチェーンに乗ってない。
    - これはおそらく今時のブロックチェーンの課題ですね。あるサービスに必要な内容を全部ブロックチェーンに載せるのはまだ無理な感じ。
    - やはりブロックチェーンの外側で、補完するデータや処理などを持つ必要がある
- 親猫と子猫の遺伝子生成方法は隠されている。よいかどうかは別にして、一応隠せることは証明されたので、活用できそう。
- [x] `GeneScienceInterface`のような、インタフェースみたいなかんじですが、使い方とかはまだ理解できてない。後で調査する　⇒　調べました [仮想仔猫ゲーム CryptoKitties のコントラクト解読その２ - Qiita](https://qiita.com/blueplanet/items/e257450834a5a32f0f10) 


## 参照記事
- [Ethereumブロックチェーン上で仮想仔猫の売買が流行、わずか数日で100万ドル以上の取引が行われた | TechCrunch Japan](http://jp.techcrunch.com/2017/12/04/2017-12-03-people-have-spent-over-1m-buying-virtual-cats-on-the-ethereum-blockchain/)
- フルソースは [etherscan.io](https://etherscan.io/address/0x06012c8cf97bead5deae237070f9587f8e7a266d#code) から参照できる
IFTTTのWebhookをGASのPOSTで受け取るときのパラメータ覚書

# はじめに
ほぼ自分用の覚書

# JSONの場合
## IFTTTの設定
- URL: `https://script.google.com/macros/s/XXXXXX/exec`
- Method: `POST`
- Content Type: **`application/json`**
- Body: **`{"value1": "moge", "value2": "もげもげ", "value3": "{{TextField}}}`**

## GASの実装

```javascript:sample.gs
function doPost(e) {
  var jsonString = e.postData.getDataAsString();
  var data = JSON.parse(jsonString);
  var value1 = data.value1; //moge
  var value2 = data.value2; //もげもげ
  var value3 = data.value3; //TextFieldの中身
}
```

# x-www-form-urlencodedの場合
## IFTTTの設定
- URL: `https://script.google.com/macros/s/XXXXXX/exec`
- Method: `POST`
- Content Type:**`x-www-form-urlencoded`**
- Body: **`value1=moge&values=hage&values=hoge`**

## GASの実装

```javascript:sample.gs
function doPost(e) {
  var moge = e.parameters["value1"][0];
  var hage = e.parameters["values"][0];
  var hoge = e.parameters["values"][1];
}
```
# text/plainの場合
## IFTTTの設定
- URL: `https://script.google.com/macros/s/XXXXXX/exec`
- Method: `POST`
- Content Type:**`text/plain`**
- Body: **`もげもげ`**

## GASの実装

```javascript:sample.gs
function doPost(e) {
  var body = e.postData.getDataAsString(); //もげもげ
}
```
GoogleAnalyticsのイベントトラッキングのコードを追加するのがめんどい

これは[Wanoグループ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/wano-group)の14日目の記事です。

表題の背景としては仕事で数十のサイトを開発・管理していて、効果測定の為にGoogleAnalyticsのイベントトラッキングも使うわけで、ただ新たに数字を取るとなると管理しているサイト全てにコードを追加するのはかなりめんどいです。

さすがにサイト自体はCMSで管理しているので、とりあえず特定のURLをクリックされた時は勝手にイベントトラッキングされる様にjs仕込む事にしました。

##準備
###1.GoogleAnalyticsのトラッキングコード
設置してください。

###2.イベントトラッキングさせたいリンクの作成
リンク内に特定のパラメータが入っていた場合に仕込んだjsが発火し、イベントトラッキングさせたいのでそれ用のパラメータが付いたリンクのaタグを作ります。
（実際にはCMSで登録されたURLがaタグに設置されるイメージ）

```html
<a href="/?event_category=Video&event_label=Campaign">リンク</a>
```
それぞれのパラメータがイベントトラッキングのイベントフィールドになります。

`event_category=Video`がeventCategory、`event_label=Campaign`がeventLabelです。
他のイベントフィールドも使用したければパラメータを追加してください。

###3.jsのイベント追加
jQery使ってしまってるのでjQeryも読み込んでください。

```JavaScript:
$(function(){
    $('a[href *= "event_category"][href *= "event_label"]').on('click',function(){
        var link = ($(this).attr('href'));
        var param = link.replace(/#.*$/,"");
        param = param.substr( link.indexOf('?')+1 );
        var key = param.split('&');
        var obj = {};
        for(var i = 0; i < key.length; i++){
            var key_value = key[i].split('=');
            obj[key_value[0]] = key_value[1];
        }
        if(!obj.page){
            ga('send', 'event', obj.event_category ,'click', obj.event_label);
        }	
    });
});
```
他のイベントフィールドも使用したい時はこっちも変更する必要があります。

あとは対象のリンクをクリックしてもらうだけですね。


##まとめ
この方法がベストだとは思ってるわけではないですが、今のところ煩わしさはないので良しとしています。
注意としてはリンクが生成されるタイミングと、jsのイベントが読み込まれるタイミングに差があるのでそこは工夫が必要です。
PostgreSQLメモ

# PostgreSQLで使ってて気付いたこととかをメモるところ

随時更新するよ．

## LIKEによるテーブル定義の流用

- 名前の意味
    - tblname: 作成するテーブル名
    - parent:  DDLを流用する元テーブル名
    - tblname: データをつっこむテーブル名
    - pkeycol: PRIMARY KEYに指定したカラム名（複数カラムに指定した場合は，多分，それら全部要る）
- やりかた

    ```sql:
    CREATE TABLE tblname (LIKE parent);
    ```

- 注意
    - 上の文ではPRIMARY KEYとかコメントとかついてこないので，振り直さないとだめ．
    - DEFAULT値とかはLIKE句の後ろにdefaultとかつけたらコピーできる．
    - 詳しくは[CREATE TABLE](https://www.postgresql.jp/document/9.5/html/sql-createtable.html)とか参照．
- おまけ
    - PRIMARY KEYを指定する場合

        ```sql:
        ALTER TABLE tblname ADD PRIMARY KEY (pkeycol);
        ```

    - コメントをつける場合は

        ```sql:
        COMMENT ON TABLE  tblname IS '←というテーブルを作ったそうな';
        COMMENT ON COLUMN tblname.pkeycol IS '←これPRIMARY KEYだから';
        ```


## なければINSERT，重複する場合はUPDATE

- 名前の意味
    - tblname: データをつっこむテーブル名
    - pkeycol: PRIMARY KEYに指定したカラム名（複数カラムに指定した場合は，多分，それら全部要る）
    - colname: データを入れたいカラム名
    - pkeyval: pkeycolのカラムに入れる値
    - value:   colnameのカラムに入れる値
- やりかた

    ```sql:
    INSERT INTO tblname (pkeycol,colname) VALUES (pkeyval,value)
    ON CONFLICT ON CONSTRAINT pkeyname
    DO UPDATE SET colname = value;
    ```

- 注意
    - CONSTRAINTで指定するPRIMARY KEYが必要．そらそーだ．
- おまけ
    - ちなみにMySQLでは，こんな感じらしい．  
      [レコードがなければINSERT,あればUPDATEをするSQL \- Qiita](https://qiita.com/yadok/items/fa72e8ae1d97033be218)
react nativeでメルカリのような横スクロールメニュー

メルカリのアプリに実装されているような
横スクロールするメニューを簡単につくれるライブラリはあるのでしょうか。

WEBだとAppleのスマホ版のような、数年前からよくみかける横スクロールするメニュー（ナビゲーション）です。

下記のようにScrollView のオプションで水平にしたら少しそれっぽくはなりましたが、ライブラリで良いのがあればご教授いただければ幸いです。
```
<ScrollView horizontal={true}>
　<TouchableHighlight><Text>メニュー1</Text></TouchableHighlight>
　<TouchableHighlight><Text>メニュー2</Text></TouchableHighlight>
　<TouchableHighlight><Text>メニュー3</Text></TouchableHighlight>
　<TouchableHighlight><Text>メニュー4</Text></TouchableHighlight>
</ScrollView>
```
PeerCast プログラミング配信 Advent Calendar 2017 14日目

#やったこと
【完】Pythonのプログラミングができる環境をつくりたい。
→Pythonのバージョン3.6.3のインストールをした。
【完】PythonでHello worldを表示させたい。
→pyファイルから呼び出して実行する場合と、対話モードで実行する場合の両方を実行することができた。
【完】演算をいくつかやってみる。
→四則演算を表示するプログラムを作成し実行した。
Androidアプリの開発中にUnsatisfiedLinkErrorで詰まった話（ネイティブライブラリ周り）

# Androidでネイティブライブラリ（VoiceText）を使った時にハマった話

# はじめに

新卒専用 Advent Calendar 2017 15日目の記事です💁

## なんのはなし

本当はSwift4でiOSアプリを作りたかったんだけど間に合いそうにないので、急遽Androidアプリ開発の仕事をしてたときのハマったことについて書きます。
（いつか投稿しようと思って、メモ書きしててよかった😅）

これからネイティブライブラリを使ったAndroid開発している人の参考になればと思います。😊

## 症状

実機では動く処理がエミュレータでは落ちる
(java.lang.UnsatisfiedLinkErrorの発生)

## 原因

|端末|アーキテクチャ|
|---|---|
|実機|arm系|
|シミュレータ|x86|

**使用していたネイティブライブラリがx86非対応だった。**

アプリが落ちる時に `java.lang.UnsatisfiedLinkError` としか出力されなかった為、つまった。

[UnsatisfiedLinkError (Java Platform SE 7 ) についてはコチラ](https://docs.oracle.com/javase/jp/7/api/java/lang/UnsatisfiedLinkError.html)

## 解決策

ネイティブ ライブラリの特定の ABI 設定のみをビルドおよびパッケージ化する

`build.gradle` ファイルを編集

```
android{
  ...
  defaultConfig {
      ...
      // 以下を追加
      ndk {
          abiFilters "arm64-v8a", "armeabi-v7a", "armeabi"
      }
  }
  ...
}
```

[参考リンク：プロジェクトへのC/C++コードの追加](https://developer.android.com/studio/projects/add-native-code.html?hl=ja)

以下、蛇足


## Android CPU/ABIについて

Androidのシミュレータ作成するときに、`x86` とか `arm64_v8a` とかいう文字を見ませんでした？

とりあえず適当にrecommendedのやつ( `x86` )選べばいいか😉　なんてやってませんか？

自分はやってました😅

そもそも、この `x86` とか `armXXX`　って何？って思って色々調べたら、ABI(ApplicationBinaryInterface)の事らしい（それすらも知らなかった）

AndroidのABIについては、以下の記事がわかりやすかったです。

[【本当に32ビット?】Android端末の CPU の ABI を特定する](https://android.benigumo.com/20161222/android_cpu_abi_arm_x86/)

まとめると、

- 端末ごと（CPU）ごとに違うABIが使われてる
  - GalaxyS7は `ARM64` (`ARM系統`)　
  - ASUS Zenphone2は `x86` を使っている　とか

標題のエラーが出た時もしやと思って調べてみたら、これが原因でした。

## ネイティブライブラリのインポートの仕方

ネイティブライブラリをインポートするやり方もメモってたのでついでに書きます。

### やり方

*.soファイルがあると思うのでそれを適切なパスへ配置する

１. app/src/main/jniLibs配下へアーキテクチャごとにフォルダを作って配置

- 例 x86向けhoge_foo_bar.soファイルを配置したい場合
 - app/src/main/jniLibs/x86/hoge_foo_bar.so 

２. インポート文を書く

``` 
// build.gradle
android{
   ...
   sourceSets {
        main {
            // ネイティブライブラリをインポートする用のディレクトリ設定
            jniLibs.srcDirs = ['src/main/jniLibs','src/main/jniLibs/']
        }
    }
}
```

## まとめ

- UnsatisfiedLinkErrorが発生した時は以下を確認する
 - ネイティブライブラリが正しくインポートされているか
 - ネイティブライブラリが実行した端末のアーキテクチャに対応してるか
- VoiceTextはARMのみ対応でx86は非対応　（2017/12/14現在)
- シミュレータのABIをarmにすると遅くてどうしようもないので、素直に端末買いましょう



## その他参考リンク

https://qiita.com/KawabataLemon/items/c9bd851deacc72a7458a

http://software.fujitsu.com/jp/manual/manualfiles/M050000/B1WN5031/03/msg43/msg09889.htm

https://android.benigumo.com/20161222/android_cpu_abi_arm_x86/
オプショナルの使い方について一言

kotlinでの開発も広まって来ているせいで、android界隈でもオプショナルを使うことが当然の様になってきていると思います。

自分は、C言語でコードを書いていた頃からnullチェックが嫌いでした。外部公開I/Fとかならやるんですが、privateな関数ではnullチェックを書いたら負けかなと思っていました。

kotlinで書く場合、nullチェックをしなくてもヌルポを発生させることもないコードを簡単に書くことができます。ただ、ちょっと考えて欲しいのですが、例えば次のようなコード、ある外付けデバイスに文字列を出力するメソッドとします。

``` kotlin
private fun foo(device: Device?, str: String) {
    device?.initialize()
    device?.output(str)
    device?.close()
}
```

これって、Javaで書くならこういうことでしょう。

```java
private void foo(@Nullable Device device, String str) {
    try {
        device.initialize();
        device.output(str);
        device.close();
    } catch(NullPointerException e) {
        // do nothing
    }
}
```

もうちょっとマシに見えるかもしれない書き方なら

```java
private void foo(@Nullable Device device, String str) {
    if (device == null) return;

    device.initialize();
    device.output(str);
    device.close();
}
```

どちらもヌルポで落ちることはないけれど、外付けデバイスに目的の文字列が出力されることはなく、しかも出力されない理由もよくわからないという結果になります。

引数にnullを許容する型をとっておきながら、nullを渡された場合のケアを全くしていません。JavaDocで `nullが渡されたらなにもしません`と書いておけば、それで十分でしょうか?

この場合、引数をnullを許容しない型にした方が使いやすいと考えます。

``` kotlin
private fun foo(device: Device, str: String) {
    device.initialize()
    device.output(str)
    device.close()
}
```

これで、javaコードからnullが渡されればヌルポが発生し、即座に不正箇所がわかりますし、kotlinからコールする場合はコンパイラがチェックしてくれます。

これは、ちょっと極端にした例で、おそらくjavaコードに`@Nonnull`や`@Nullable`などのアノテーションがない状態でコンバートして、そのままなんだと思いますが…
実際にコードレビューをしていて、似た感じのコードを見ることがあるので、こんなコードを書かないようにして欲しいと思います。

### 参考リンク
`@Nonnull`な引数のnullチェックについては、下記リンク先の考えがいいと思います。
[Android: NonNullアノテーション](http://yuki312.blogspot.jp/2016/02/android-nonnull.html)
Amazon Machine Learning でおすすめ商品リスト機能を実装しようとして断念した

# 結論
高すぎた。:moneybag:

# 実装したかった機能
amazonとか大体のECサイトにある、いい感じにユーザーにカスタマイズされた商品リストが表示される機能。

# Amazon Machine Learning　とは
https://aws.amazon.com/jp/aml/
ざっくりとは

- 機械学習についての高度な知識は不要で、機械学習による予測を使えるようになる
- マネージドサービスなので学習に使うサーバのリソースについては考慮不要(AWSが裏でよしなにやってくれる)

# 機械学習には大別して３種類ある
## 教師あり学習
データと正解を合わせて学習させて、どういうデータの時にどの答えになるかを予測させる手法。
これを使えば例えば、顧客のセグメントができたりする。
## 教師なし学習
正解は与えずデータだけ学習させる。データに存在する特徴を見つけ、グループ分けをする。
これを使えば例えば、ニュース記事のカテゴリ分けができたりする。
データにこれといった正解がない場合に有効。
おすすめ商品リスト機能を実装する場合、この教師なし学習を利用することが多いそう。

## その他
強化学習（※教師なし学習の一部だという考え方もあるそう）

# Amazon Machine Learning で実現できる機械学習

現時点(2017/12)では、上記のうち**教師あり学習のみ**がAmazon Machine Learningで実現できる機械学習です。教師なし学習は使えない。困った。

# やろうと思えば教師あり学習でも実装できるらしい

[Using AWS Machine Learning for Generating Recommendations](https://forums.aws.amazon.com/thread.jspa?messageID=617667)
1. 商品を買ったという正解＋ユーザーの情報＋商品の情報を１セットとする
2. 商品を買わなかったという正解+ユーザーの情報＋商品の情報を１セットとする
3. １.2.のデータを大量に用意し、学習させる
4. ユーザーの情報+商品の情報を１セットとして、予測させる
5. ユーザ✖️商品ごとに購入期待値（最大値１、最低値0）が返ってくる
6. ユーザーごとに期待値降順で5.のデータを並べて、上位n件の商品を表示する！

１.のデータは商品購入履歴としてシステム上に持っていたが、2.は持っていない。仕方がないから品切れ商品✖️その商品買っていないユーザーで適当に作った。

# 実装結果

ダメダメだったー:poop:

- どのユーザーでも上位に上がってくる商品がある
- 購入商品が全然違うユーザー同士でも、結果が似かよる

まぁ、これは学習させるデータを変えたり、[トレーニングパラメータ](https://docs.aws.amazon.com/ja_jp/machine-learning/latest/dg/training-parameters.html)を変えたりしたら改善の余地はあるのではないか、と思っている。
そんなことより以下のコストの面が問題だ。

# 予測コスト(おかね）
今回のやり方の場合、商品✖️ユーザーごとに購入期待値を予測させるので、全購入可能商品と全ユーザーを掛け合わせた数のデータを用意し全て予測させることになる。

今回のサイトの場合、

- 購入可能商品点数が**約6万**
- ユーザ数が**約8万** 
- つまり、全ユーザーに対して、全商品を元にしたおすすめ商品リストを作ろうとすると、
6万✖️８万　= 48億のデータをAmazon Machine Learningに予測させることになる。 
- 予測 1,000 件当たり の料金は 0.10 USD　([Amazon Machine Learning の料金表](https://aws.amazon.com/jp/aml/pricing/))
- 48億➗ 1,000✖️ 0.10 USD = 480,000 USD
- 1USD = 110　円として概算すると　 **５,２8０万円**
- しかもこれはある時点でのおすすめ結果を生成するに過ぎない。
新入荷商品はおすすめされないし、新規会員にも何もおすすめすることはできない。
新たな購入履歴をおすすめ一覧に反映することもできない。
- ・・ので、定期的に予測し直させる必要がある。一日一回再予測させるとすると・・ :skull::skull::skull:

# というわけで
他の方法を模索中です
AssumeRoleしよう（Terraform編）

Yasと申します。
人や環境によって色々ですが、企業ベースで利用する場合にはAWSアカウントを複数持って直接Deployする場合もあるかと思います。
そんな人の為の一助になれば幸いです。

###Terraformって何ぞや？
HashiCorp社の有名な構成管理ツールです。
インフラをコードで管理したい！という人は一度は目にしているのではないでしょうか。
詳しくは色々なサイトにいっぱい書かれているので省略します。

###で、何したいの？
AWS環境を複数管理するような人向けに、わざわざAccessKeyを書いたり切り替えたり管理したり***アーーーーッ！！！***となることを少しでも楽に
する為に
**IAMuserは１つだけ、あとはAssumeRoleで管理しよう**
的なことを目的としています。

##どうやるの？
基本的な流れは
＜AWS側のこと＞
1：AssumeRoleする別AWSアカウントにIAMRoleを作る（アカウントIDを仮に「987654321098」とします。）
２：操作用のIAMuserを作る（アカウントIDを仮に「123456789012」とします。）
＜Terraformのこと＞
３:Providerを登録する
です。

####１:AssumeRoleする別AWSアカウントにIAMRoleを作る
AssumeRoleをする先のアカウントにIAMroleを発行します。
なんで先にRoleを作るかというと、操作するアカウント側のIAMuserに作成したRoleのarnを記載する必要があるからです。
最近のコンソールはかなり簡単なので、最初に別アカウントでできるようになってます。
ロールの作成で「別のAWSアカウント」を選択→IAMuserを作る方のAWSアカウント番号（１２桁）を入力→権限を選んで作成
これだけです。
![assumerole.png](https://qiita-image-store.s3.amazonaws.com/0/216909/7c4df133-9249-d0ff-892d-edd1581443d2.png)
↑Roleの作成からここを選べばよいです。


ここでは分かりやすいように作成したIAMroleのarnを
arn:aws:iam::987654321098:role/AssumeRoleIAMrole
とします。
（次に使うのでメモっておきましょう。）


####２:IAMuserを作る
利用ユーザー用にAccessKeyとSecretKeyを発行します。
そして、作成したIAMroleにPolicyを追加します。

```IAMPolicy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::987654321098:role/AssumeRoleIAMrole"
        }
    ]
}
```
↑こんな感じです




####３:Providerを登録する
TerraformでCredentialを登録する際に以下のように登録します。
実体として登録するAccecckey・SecretKeyは2で作ったものを利用する形です。

扱うAWS環境が１つだけであれば以下でもOKです。

```
provider "aws" {
  access_key = "AWSのアクセスキー"
  secret_key = "AWSのシークレットキー"
  region     = "リージョン"
  assume_role {
    role_arn     = "arn:aws:iam::987654321098:role/AssumeRoleIAMrole"
  }
}
```

複数あったりセキュアにするならプロファイルで分けられた方が便利なので以下になります。


```
provider "aws" {
  profile = "適当なプロファイル名"
  region  = "${var.aws_region}"

  assume_role {
    role_arn     = "arn:aws:iam::987654321098:role/AssumeRoleIAMrole"
  }
}
```

これでIAMuserをたくさん作成して設定する必要や、複数アカウントのキーローテーションをする手間が省けるわけです。

どこかにいる誰かの一助になれば幸いです。



参考

https://www.terraform.io/docs/providers/aws/
UITableViewHeaderFooterViewの背景色の指定

# 概要

TableViewで利用する`UITableViewHeaderFooterView`の背景色の変更の方法でちょろっとはまったので備忘録

# 結論

`contentView`に設定する。

```swift
// NG
self.backgroundColor = .yellow
// OK
self.contentView.backgroundColor = .yellow
```

UITableViewCellとかと同じで`contentView`を持っているんですね。
csvデータをPostgreSQLのCOPYコマンドを使ってDBに取り込む（insert）方法


データを取り込む処理は既に実装されていたので最初は`rails runner`を使ってたのだが、遅い。

処理が全然終わらないので、直接DBへ取り込む形に変更した。

# rails runnerの場合
```terminal
> rails runner hogehoge.rb
```

# DBへ直接取り込む場合（COPY）
```sql
COPY shop_sales (sales_date,shop_id,sales)
FROM '/Users/taku/hogehoge.csv' with csv;
```

すげー簡単。ビックリ。
でも、何よりビックリしたのが、バカみたいに早い。
うん時間かかっていたのが、数秒で終わっちゃう。

はまった所としては、最初idのカラムを作ってしまっていたのだがRailsでは自動で採番してくれるようになっているので不要だった。

# まとめ

お互いメリット、デメリットがあって基本的にはやっぱり既存のコードを使う方が良い。
何故ならデータにミスがあってもバリデーションが働くから。

それに対して直接取り込む場合は、それが無いので

- nil それとも 0 ？
- 日付は正しい形式になってる？

などなど本当に正しいデータ形式なのかしっかり確認しておかないと思わぬ障害を作ってしまう。

なので、既存のコードで`save`される直前のデータを確認しcsvデータが同じ形式になっているかをチェックするようにしました。


そんな感じ。
Symfony FlexのRecipeの作り方

Symfony4.0から、Flexという仕組みが導入され、Bundleの有効化や初期設定が自動で行われるようになりました(4.0が主に宣伝されていますが、ltsの3.4でもFlexは使えます)。

たとえば

```
$ composer req orm-pack
```

みたいにコマンドを打つと、DoctrinBundleと関連ライブラリがインストール/有効化され、設定のyamlファイルがconfigディレクトリ以下に展開されます。あとは.envでDATABASE_URLを指定するだけで、すぐにDoctrineの機能が使えるようになります。

## Flexの仕組み

この自動化の処理は、Flexによって行われています。Flexは、[composerのプラグイン](https://github.com/symfony/flex)として実装されています。
やっていることはとても単純で、composerのrequireコマンドをフックし、

- パッケージ名(エイリアス)を[Flexのレシピサーバ](https://symfony.sh/aliases.json)に問い合わせて、packagistのパッケージ名に解決する
- packagistからライブラリのダウンロードを行う
- レシピをダウンロードする
- レシピに基づいて、バンドルの有効化や設定ファイルの展開を行う

という流れで処理をしています。

## レシピの作成方法

レシピの作り方については、[README](https://github.com/symfony/recipes)に説明の必要もないくらい全部書いてありました。。。

主要なところだけ紹介すると、以下のような感じです。

### レシピの種類

レシピは[公式](https://github.com/symfony/recipes)と[コントリビューション](https://github.com/symfony/recipes-contrib)の二種類があります。公式はSymfonyのコアチームによって管理されていますが、コントリビューションのレポジトリにはPull Requestすれば自分のレシピも登録してもらうことができます。Symfony Botによって、[一定の条件](https://github.com/symfony/recipes-contrib#contributing)を満たせば自動でマージされます。

一定の条件とは、以下の通りです。

- Pull RequestのタイトルにWIPが含まれていないこと
- Symfony Botのレビューを通っていること
- Pull Request送信者以外の誰かがPull Requestをapprovedすること
- その誰かとは、以下のいずれか
    - Symfonyのマージ権限を持つ人
    - そのパッケージのオーナー
    - そのパッケージのオーナーが属しているOrganizationのメンバー

基本的には全然関係ない人が他人のライブラリのレシピを登録することはできないようになっているみたいですね。

この条件だと、一人で開発しているオレオレライブラリを登録するのは無理なのかな？と思いましたが、レシピの信頼性を担保するためには仕方ないのかもしれません。

### manifest.json

レシピの定義は、`manifest.json`というファイルに記述します。
定義内容はオプションとコンフィギュレータで構成されています、

### オプション

現状、オプションとして定義されているのは`alias`のみです。
aliasを定義しておくと、`composer req [alias]`みたいに実行することができます。
ただし、コントリビューションのレシピでは使用できません(後述の非公開レシピだと利用可能です)。

### コンフィギュレータ

バンドルの有効化や、設定ファイルの展開は、コンフィギュレータで定義します。
以下の8つのコンフィギュレータが定義できます。

- copy-from-recipe
- copy-from-package
- bundles
- env
- composer-scripts
- gitignore
- post-install-output

例えばバンドルが自動で有効化されるのは、`bundels`で定義されています。

`manifest.json`に以下のように記述すると、

```json
{
    "bundles": {
        "Acme\\Bundle\\HogeBundle\\DebugBundle": ["all", true],
    }
}
```

config/bundles.phpに追記されます。

```php
// config/bundles.php
return [
    'Acme\Bundle\HogeBundle\DebugBundle' => ['all' => true]
];
```

他の定義については、[README](https://github.com/symfony/recipes)を参考にしてみてください。

ちなみにREADMEには、

```
There are eight types of tasks, which are called configurators: 
copy-from-recipe, copy-from-package, bundles, env, composer-scripts, gitignore, and post-install-output.
```

`There are eight types of tasks`て書いてあるけどどうみても7つしありません。

https://github.com/symfony/recipes#configurators

## 非公開のレシピを作成する

ここまでは、公開されているバンドルやライブラリのレシピについての説明でしたが、非公開のレシピも作成することができます。

非公開レシピの作成については以下で解説されていますので、ご参考まで。

http://fabien.potencier.org/symfony4-flex-private-repositories.html

非公開レシピの作成方法についても別の記事でまとめようと思います。

以上です。

それではよいFlexライフを！
DrQAを試してみる


Facebook開発のWikipediaをコーパスとする質問応答の深層学習モデルであるDrQAを試してみた。

* [論文](https://arxiv.org/abs/1704.00051)
* [github](https://github.com/facebookresearch/DrQA)

githubの方に、インストール手順と簡単な実行サンプルが記載されているので、そのままやってみた。

# PyTorchのインストール


[PyTorchの公式サイト](http://pytorch.org/)のGetStartedに従う。cudaのバージョンを調べてから、条件にあうものをインストールした。

```
nvcc --version
``` 

```
pip install http://download.pytorch.org/whl/cu80/torch-0.3.0.post4-cp35-cp35m-linux_x86_64.whl 
pip install torchvision
``` 

# DrQAの依存ライブラリのインストール

## 依存するPythonパッケージのインストール

githubのInstallを参照し、そのまま実行。

```
git clone https://github.com/facebookresearch/DrQA.git
cd DrQA; pip install -r requirements.txt; python setup.py develop
```

## Stanford CoreNLPのインストール

以下のコマンドだけでOK。
デフォルトで環境変数の.bashrcへの設定も行ってくれる。

```
./install_corenlp.sh
```

## 動作確認

動作確認をしてみる。
最初の2行でCoreNLPのライブラリを読みに行くパスを指定している。これは先程のCoreNLPのインストール時に環境変数で指定していれば不要。

```python3
import drqa.tokenizers
drqa.tokenizers.set_default('corenlp_classpath', 'data/corenlp/*')

from drqa.tokenizers import CoreNLPTokenizer
tok = CoreNLPTokenizer()
tok.tokenize('hello world').words()  # Should complete immediately
```

以下のようなリストが得られる。

```python3
['hello', 'world']
```

# データセットの取得

データセットをダウンロードする。学習済みのモデルも含まれている。以下のコマンドだけでOKだが、全部で25GBもあり、そこそこ時間がかかる。

```
./download.sh
```

# 実行してみる

CoreNLPの環境変数を設定したうえで、interactive.pyを実行するとインタラクティブモードになるので、クエリを投げることができる。
定期的にTimeOutErrorが表示される場合は、おそらく環境変数が間違っている。

```
export CLASSPATH=$CLASSPATH:data/corenlp/*
python scripts/pipeline/interactive.py
```

* What is question answering?

![スクリーンショット 2017-12-11 21.54.46.png](https://qiita-image-store.s3.amazonaws.com/0/101785/cf3fa80e-85d6-fc65-f50e-38c0bb4466ce.png "スクリーンショット 2017-12-11 21.54.46.png")

* What is the answer to life, the universe, and everything?

『銀河ヒッチハイクガイド』に出てくる「生命、宇宙、そして万物についての究極の疑問の答え」について聞いみると…

![スクリーンショット 2017-12-11 21.54.29.png](https://qiita-image-store.s3.amazonaws.com/0/101785/e57f87b0-49cb-d5b8-2948-7e466814b9cd.png "スクリーンショット 2017-12-11 21.54.29.png")

42!


* Who was the winning pitcher in the 1956 World Series?

![スクリーンショット 2017-12-11 21.55.05.png](https://qiita-image-store.s3.amazonaws.com/0/101785/f6ccc84b-6bed-3cbb-bbd2-c02af7fa1192.png "スクリーンショット 2017-12-11 21.55.05.png")

でも、こんな例もある。

* Who is Barack Obama?

![スクリーンショット 2017-12-11 21.55.17.png](https://qiita-image-store.s3.amazonaws.com/0/101785/a194268e-6adf-616d-479d-4743a6cb7643.png "スクリーンショット 2017-12-11 21.55.17.png")

オバマはヒラリーという回答に…。


# 感想

精度はともかく、論文を読んでネットワークを把握した上で自分で学習させてみたい。Tokenizerを変更すれば、日本語のwikipediaでもできるかも？
Pythonのsetを知る

#setの特徴

**１：setとはデータ型の１つ
２：データ型なので、タプルやリストを渡して作ることが出来る
３：値の重複がない
４：リストのようにindexの参照は出来ない**

#setを用いたデータの作り方！

setにリストやタプル、また波括弧を渡すことで、作成することが出来ます！

```py3

#リストを引数にする場合
x = set([1,2,3])
print(x)
# {1, 2, 3}

#タプルを引数にする場合
x_ = set((1,2,3))
print(x_)
# {1, 2, 3}

#波括弧で囲った値を変数に代入する方法
a = {1,2,3}
print(a)
# {1, 2, 3}

```

#本当にsetなんていうデータ型があるか確認してみましょう！

```py3
#先ほど作成したx,x_という変数を使います！

print(type(x_))
# <class 'set'>

print(type(x_))
# <class 'set'>

print(type(a))
# <class 'set'>

```

クラスはset型となっているので、今までのデータ型とは違うみたいですね！

また、波括弧を変数に代入する方法は、@shiracamus さんにおしえて頂きました！

以前はset関数という名前で投稿していましたが、setは関数ではないようです！

>setは型なので、厳密には関数ではなく、コンストラクタを呼び出してインスタンス生成してます。
他の言語なら new set(array)と書きます。
intやstrやlistも同じ。
関数とクラスを意識することなく使えるのがPythonのいいところですね。

shiracamusさん、ありがとうございますm(__)m

#次は本当に重複がないのか調べてみます！

```py3

y = set([1,2,2,3,3,3,4,4,4,4])

print(y)
#{1, 2, 3, 4}
```

本当に重複がないようです！

そのため、**重複を削除したい場合にsetを使う場合**もあるようです！

#index参照ができないか確認！

```py3
y = set([1,2,2,3,3,3,4,4,4,4])

print(y)
#{1, 2, 3, 4}

#yの二番目の要素を指定！
y[1]

"""
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support indexing
"""

```

エラーが出ました！

set型の各要素を取り出したい場合はリストに直してindexを指定する場合やfor文で取得することも出来るようです

```py3

#リスト関数に渡して、indexを指定!
y = list(y)

y[1]
#2

#リスト内包表記でリストに直して、indexを指定！
[i for i in y][1]
#2

```

#おわりに

set同士の演算もあるみたいなんですが、まだ触れていないので、今回はここまで触れました！

イケてない書き方や、もっといい方法がある場合はおしえていただけますと幸いです！
DiscordPHPを使って簡単なBotを作ってみる - 実践編

# Discord Advent Carendar 2017 16日目
今回は、[前回の導入編](https://qiita.com/alegriaghost/items/7b441cd81d3cf77bba6f)に引き続き実践編です。
※大したことはしないので、本当に触り程度の内容です。

# やってみますぞ
今回はBotの発言をやってみます。

## Botの発言
一概に発言といっても、Bot自ら発言するパターンやらメッセージに反応するパターンやら
色々ありますが今回はとても簡単なメッセージに反応するパターンです。

さっそくコードを見ていきましょう。

### メッセージに反応させるパターン

```php:run.php
<?php

// 一部のソースコードは省略しています

$discord->on('ready', function ($discord) {
    // Listen for events here
    $botUser = $discord->user;
    $discord->on('message', function ($message) use ($botUser) {
        if ($message->author->user->id !== $botUser->id) {
            $message->reply('こんにちはーっ！');
        }
    });
});
```

さて、上記ですが。。。

`'ready'` については特に詳しく触れません。というか特に詳しく書けません。
簡単にいうとBotが起動して準備できましたよ、ってことですね。

`$discord->on('message', callback)`
これはメッセージが来た時に走るイベントですね。
今回は、メッセージに反応したいので、ここのcallbackの処理に色々書いていきます。

上記の処理では、何かメッセージがきたら「こんにちは」と返すだけの簡単な処理です。
ただ、これだと「すべてのメッセージ」に対して反応してしまい、自分の発言したメッセージに対しても反応して無限ループになってしまいます。

ですので、 `if ($message->author->user->id !== $botUser->id)` と書いて自分以外のメッセージの場合のみ返信するようにしています。
(もしかするともっと良い制御があるかもしれませんね。)

実際に実行してみると、こんな感じになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44541/5fbe2800-3bbb-a1ed-babe-4dd3422c343c.png)
なんて元気のいい返事でしょう。可愛いですぞ！

さて、 `message` イベントのcallbackに何かしら処理を書けば、メッセージに対して反応してくれるということがわかりました。

もう少し改良してみましょう。

### メンションの条件をつけてみる

```php:run.php
<?php

// 一部のソースコードは省略しています

$discord->on('ready', function ($discord) {
    // Listen for events here
    $botUser = $discord->user;
    $discord->on('message', function ($message) use ($botUser) {
        if ($message->author->user->id !== $botUser->id) {
            if (isset($message->mentions[$botUser->id])) {
                $message->reply('こんにちはーっ！');
            }
        }
    });
});
```

さらに「自分宛のメンションがついているときのみ」という条件を追加してみました。
あまり綺麗ではないですね。突っ込まないでください。

実行してみますぞ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44541/4832d01f-6539-60e5-365e-e2138e350bb9.png)
メンションがない場合は、反応していません。
メンションがある場合は、またまた元気に挨拶してくれますね！

`isset()` で使っている `$message->mentions` ここにメンション対象のUserクラスが配列として詰められています。

そのキーとして、UserのIDが設定されていますので、
今回はそのIDにBotユーザIDが含まれているかどうか、という判定をしています。

### 言い訳
普段はdiscord.jsで書いているので `isMemberMentioned` という便利なメソッドがあるのですが、PHPはないのですかね。
泣く泣く `isset()` なんていう判定にしてしまいました。

# まとめ
こんな感じで反応の条件をカスタマイズできます。

色々いじっていけば
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44541/b993329e-0f3f-a9dc-277e-b7f2a130ff97.png)
こんな感じでお話もすぐできそうですね！

# おわりに
DiscordPHPはDocumentもあまり充実してる気がしないので、
PHPを読める人はライブラリの中を直接読んでしまった方が理解が早いかもしれませんね。
まぁ、正直なところnodeで書く方が色々楽だなと思いました。

明日は[ryo-yamaoka](https://qiita.com/ryo-yamaoka)さんの順番ですー。
サイトの収益方法を考える（簡易）

# 月額料金をユーザーに払ってもらうタイプ。
ニコニコ動画や、新聞社のサイト等。
# サイトに広告を埋め込むタイプ。
ブログ、アフィリエイト
# 動画を見ることによって会社からサイトとユーザーの両方に金が渡るタイプ
YouTuber
# 投げ銭をしてもらうタイプ。
YouTuber

# 他のサイトへ誘導するためにリンクを貼るタイプ。
2ch、5ch

# サイトからスクリプトを動かしてもらってローカルで金を生成するタイプ。
広告や料金を一切せずにサイト上のスクリプトを動かしてもらう
これは画像１枚を読み込むぐらいの電力で数回回せるだろう。
仮想通貨
「crypto-jacking」（クリプトジャッキング）

参考
人気動画サイトが閲覧者の端末を「採掘」に利用、10億人近くに影響のおそれ
https://japan.cnet.com/article/35111934/

上記の記事はユーザーの合意を取っていないから問題なのであって、
ユーザーと合意の元でならWin-Winの関係になるだろう。

この方法は広告など他のサイトへのリンクを貼ることがない、
サイト内の場所をとることもなく、バックグラウンドで動いているだけなので普段はユーザー側にストレスがかからない点で
アフィリエイトや広告などよりも上だ。

弱点は巨大サイトでないとリターンが少ない。

サイトの運営側も画面配置に気を使わないで良くなる。
特にスマホ全盛の今は、この狭い画面を十二分に有効活用したいので、バックグラウンドでサイト運営が出来るのならば十分価値がある。

無駄に電力消費を要するためエコロージではないという声もあるが
Proof of Stakeという仕組みがある。

（そもそもアフィリエイトや広告はユーザーの同意を取っていない、リンクをクリックするのはユーザーの責任だが、表示してみせるのはサイト側の責任だ。）

将来サイト運営用のブロックチェーン技術を用いた仮想通貨が出てくるだろう。
リアルマネーと直結しないタイプの仮想通貨も出てくるだろう。

この方法は、拒否反応のほうが最初は大きいだろうが、
次第に浸透していくだろう。
Railsで課題となっているソースを抽出する方法（TODO、FIXME、OPTIMIZE）


あとあと見返した際に、これなんだって時などに使うのがアノテーションというそうです。
コードに`# TODO`などと書いておくと後で一括で抽出できるので、リリース前とかに確認すると良いかもですね。

```ruby
# controller
class ApplicationController < ActionController::Base
# TODO コントラーラーです。
  def show_image
  end
end


# model
class Message < ApplicationRecord
  belongs_to :topic
  # TODO モデルです。
end


# view
<% #TODO ビューです %> #<%=とするとダメっぽいです。
<div class="row">
  <h1>テスト</h1>
</div>
```

```terminal
$ rails notes
app/controllers/application_controller.rb:
  * [4] [TODO] コントラーラーです。

app/models/message.rb:
  * [4] [TODO] モデルです。

app/views/topics/new.html.erb:
  * [1] [TODO] ビューです
```


それぞれの単語の意味は、こんな感じだそうです。

- TODO：やらなければならないこと
- FIXME：ここ誰か直して
- OPTIMIZE：最適化が必要

参考にさせていただいたサイト
https://permanent-til-me.ssl-netowl.jp/archives/1184
SubsonicをLet's Encryptでhttpsアクセス可能にする(CentOS7+Nginx)

* [Subsonic](http://www.subsonic.org/pages/index.jsp)
* [Let's Encrypt 総合ポータル](https://letsencrypt.jp/)

# 環境

* CentOS7
* nginx 1.12.2

nginx + Subsonicで、Subsonicを動かしたいドメインで起動できるようになっていること前提。
`subsonic.example.com` というドメインでアクセスしたいとする。

# 導入方法

## Certbotクライアント入手

Let's Encryptの導入のため、Certbotクライアントを入手。

````bash
curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
chmod 700 /usr/bin/certbot-auto
````

## nginx設定 (認証用のpathへのアクセス)

Let's Encryptは `/.well-known/acme-challenge` に一時ファイルを作成して認証を行うため
 `subsonic.example.com/.well-known/` 以下にアクセスがあった場合はSubsonic側を見に行かないようにしておく。

今回はSubsonic用のconfを`/etc/nginx/conf.d/subsonic.conf`に記載しているので、該当ファイルに下記のように記載。

````nginx:/etc/nginx/conf.d/subsonic.conf
server {
    listen       80;
    server_name  subsonic.example.com;
    root         /usr/share/nginx/html/subsonic.example.com;

    location /.well-known/ {
        alias /usr/share/nginx/html/subsonic.example.com/.well-known/;
    }
}
````

## 証明書発行

Certbotクライアントを実行して、証明書を発行する。

成功すると `/etc/letsencrypt/live/subsonic.example.com/` 以下に `cert.pem` `chain.pem` `fullchain.pem` `privkey.pem` のシンボリックリンクが作成される。

````bash
certbot-auto certonly --webroot -w /usr/share/nginx/html/subsonic.example.com -d subsonic.example.com --email youraddress@example.com

ls -l /etc/letsencrypt/live/subsonic.example.com/
# シンボリックリンクの作成確認
````

## nginx設定 (SSL設定)

`/etc/nginx/conf.d/subsonic.conf`にSSLの設定を行う。
`/.well-known` 以下は更新時にもアクセスするディレクトリなので、設定はそのままにしておく。

````nginx:/etc/nginx/conf.d/subsonic.conf
server {
    listen       443 ssl;
    server_name  subsonic.example.com;
    root         /usr/share/nginx/html/subsonic.example.com;

    ssl_certificate      /etc/letsencrypt/live/subsonic.example.com/cert.pem;
    ssl_certificate_key  /etc/letsencrypt/live/subsonic.example.com/privkey.pem;

    location /.well-known/ {
        alias /usr/share/nginx/html/subsonic.example.com/.well-known/;
    }

    location / {
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header Host              $http_host;
        proxy_max_temp_file_size           0;
        proxy_pass                         http://127.0.0.1:4040;
        proxy_redirect                     http:// https://;
    }
}
````

諸々完了したらnginxを再起動。

````bash
sudo systemctl restart nginx
````

## 自動更新

証明書の更新は下記のコマンドで実行可能なので、これをcronによきタイミングで設定すればOK。

````bash
certbot-auto renew --post-hook "systemctl restart nginx"

# `--dry-run` で起動すると動作のみが確認出来る
certbot-auto renew --dry-run
````


# 参考

* [ユーザーガイド - Let's Encrypt 総合ポータル](https://letsencrypt.jp/docs/using.html)
* [Subsonic - ArchWiki](https://wiki.archlinux.jp/index.php/Subsonic)
* [Let's Encryptを使ってSSL証明書を自動更新する(AWS/Amazon Linux/Apache) - Qiita](https://qiita.com/takahiko/items/a08895550727b95b6c36)
処理待ち調査のチェックポイント

この記事はHamee Advent Calendar 2017の17日目の記事です。

# 概要
処理が止まる系(または、リロードしてるっぽい挙動がずっと続く)の調査をして見たので抑えていたところをまとめて見た。足りないところがあればコメントお願いします。

# 前提

ローカルで処理待ちが再現する。
ローカルで再現しない時に本番にログを仕込まねばならず、
調整(社内での政治的なあれこれ・・・)についてはベテランの方にお任せしましょ。

# 疑うべき点をざっくり

#### 1. ネットワークが遅い
#### 2. クエリが遅い
#### 3. データベース側でテーブルをロックしている（デッドロック)
#### 4. プログラミング言語の処理が遅い


# 1. ネットワークが遅い

これは言わずもがなかもしれません。

```
ping -l [データサイズ] [調査するURL]
```

などで少し大きめのpingを送って見て遅いようならまずこれが原因となっているかも。


# 2. クエリが遅い

クエリが遅いかどうかは発行されているクエリが見れれば良いです。
スロークエリを出すようにしておけば、基本的には見れるはず。

スロークエリの設定についてはMySQLにログインした状態で

```SQL:
show variables like 'slow%';
```

例としては以下の通り。

| Variable_name       | Value          |
|:---:|:---:|
| slow_launch_time    | 2              |
| slow_query_log      | OFF            |
| slow_query_log_file | mysql-slow.log |

slow_query_log がOFFになっているとスロークエリの出力は行われない。

#### スロークエリ出力の設定方法

```SQL
set global slow_query_log_file = '/tmp/mysql-slow.log';
set global long_query_time = 5;
set global slow_query_log = ON;
```

### my.cnfの設定

```
$ sudo vim /etc/my.cnf
```

```my.cnf
[mysqld]
slow_query_log 
slow_query_log-file = /var/log/mysql/mysql-slow.sql # これらを追加する
long_query_time = 5
```

**設定を変更したら反映させるためにrestartする。**

# 3. データベース側でテーブルをロックしている（デッドロック)

これは実はなってました。パターンもあるので必ずチェックしておく。

まずはデッドロックがログで出力されるかを見る。

```SQL
show variables like 'innodb_print_all_deadlocks';
```


| Variable_name              | Value |
|:---:|:---:|
| innodb_print_all_deadlocks | OFF   |

### 設定方法

```SQL
mysql> set global innodb_print_all_deadlocks=ON;
 
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'innodb_print_all_deadlocks';
```

| Variable_name              | Value |
|:---:|:---:|
| innodb_print_all_deadlocks | ON    |

### my.cnf設定

```
sudo vi /etc/my.cnf
```

```mysql

[mysqld]
innodb_print_all_deadlocks=ON # この行を追加する
```

# 4. プログラミング言語の処理が遅い

## フロント側

Javascript系統 => for文、while文や処理が重そうなところにtimeを仕込んで計測。またはconsole.logで中身を表示させることで重くなっている原因となりそうな要素がないかを探す。この辺りは自分の中でうまくまとまっていないので後日まとめ出すかも。

[フロントエンドデバッグの参考 @mo4_9 さん](https://qiita.com/mo4_9/items/c241043fcb17ca543df1)

## バックエンド側

PHP => こちらもMVCフレームワークなど使っていれば、使っている箇所はわかりやすいのでその辺りにログを仕込んでいく。(仕込めるという前提ではある)

最初のログの設計時点でこれをしなくて良いようにするのが最善。

[参考(ログ設計指針) @nanasess さん](https://qiita.com/nanasess/items/350e59b29cceb2f122b3)
APIを使って、Qiitaの記事を表示する。Part.1

## 背景
iOSでAPIについて学ぶついでに、Qiitaの新着記事を表示させました。また、記事をタップした時に当サイトに飛ぶようにしました。このアプリで学んだことをいくつかに分けて説明します。

## 参考にしたもの
[AlamofireとSwiftyJSONでAPIを叩くチュートリアル]
(https://qiita.com/yutat93/items/1b6dfe34fa8537cf3329)

[[iPhone] Web ブラウザを作る]
(https://i-app-tec.com/ios/web-browser.html)

[APIって結局何なの？初心者向けに徹底解説します！]
(https://blog.codecamp.jp/api)

[Homebrew]
(https://brew.sh/index_ja.html)

[Carthageを使ってビルド時間を短縮しよう]
(https://qiita.com/yutat93/items/97fe9bc2bf2e97da7ec1)

## 準備
Xcode 9.2
Swift 3.2

##完成図
アプリに表示
<img width="375" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/179470/d4f604ee-e7bb-4b7a-7d5c-e23d21a30629.png">

タップした後
<img width="375" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/179470/f4c6cbf7-8a60-7c99-90ad-7c1d32256887.png">

## APIについて
### APIとは、、、
"Application Programming Interface"の略。
簡単に言うと、ソフトウェアとプログラムをつなぐもの。

### APIを使うには
今回は、"SwiftyJSON"と"Alamofire"というライブラリを導入します。

## プロジェクト作成と導入
### プロジェクト作成
Xcodeを起動して、"Create a new Xcode project" -> "Single View App"を選択します。
プロジェクト名はQiitaViewerApp。（任意）
保存先はDeskTopへ（わかりやすいため）

### ライブラリ導入
今回は、Carthageを使って導入します。
ターミナルを開いてください。

#### Carthageの導入
Homebrewを入れていない方は以下のコマンドを実行してください。

```
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
以下のコマンドを実行してcarthageをインストール。

```
brew install carthage
```
#### ライブラリの導入
ライブラリをプロジェクト（先ほど作ったプロジェクト）に導入したいので、ターミナルで作業します。

```
cd ~/DeskTop/QiitaViewer
```

```
touch Cartfile
```

```
vi Cartfile
```
このコマンドを実行すると、"Cartfile"をターミナル上で編集できます。
このファイルに以下のように編集して保存します。

```
github "Alamofire/Alamofire"
github "SwiftyJSON/SwiftyJSON"
```
`i`で入力モードになります。
入力モードを終える時は、`esc`。
その状態で`:wq`を実行すると、保存して終了し、`:q!`を実行すると、保存せずに終了します。

編集できたら、以下のコマンドを実行してライブラリをビルドします。

```
carthage update --platform iOS
```
ビルドが終了したら、プロジェクトの方でライブラリを追加します。
プロジェクトファイルの"General"から"Linked Frameworks and Library"の+ボタンを押します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/179470/6b421f36-c3df-5da2-4921-c9fc8a9320d6.png)

Frameworksを選択する画面になるので、"Add Other"を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/179470/f939e1f6-0f88-c14b-835a-4ebc54386377.png)

プロジェクトのディレクトリ内から、QiitaViewer/Carthage/Build/iOSのAlamofire.frameworkとSwiftyJSON.frameworkを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/179470/40138904-e268-b0e3-3368-354a0b511b7c.png)

追加できたら、Build Phasesタブに移動し、＋ボタンから"New Run Script Phase"を選択します。
"Run Script"が出てくるので、"Shell"に

```
/usr/local/bin/carthage copy-frameworks
```
"input Files"に

```
$(SRCROOT)/Carthage/Build/iOS/Alamofire.framework
$(SRCROOT)/Carthage/Build/iOS/SwiftyJSON.framework
```
を書きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/179470/1280d1d1-035e-b17b-ce36-f54991ca612e.png)

これで、無事プロジェクトにライブラリが導入されました。

##Part.2へ
次は、Main.storybordを使って画面を構成していきます。
[APIを使って、Qiitaの記事を表示させる。Part.2]
(https://qiita.com/shun6510/items/64d5d44ffa98b12858d4)

## 追記(2018/11/19)
以下、これらのコードを以下に公開しています。

**https://github.com/shxun6934/QiitaViewApp**
シートを半透明に

# 半透明Window
一部の[テキストエディター](https://jp.emeditor.com/)や、[疑似端末ソフト](https://ttssh2.osdn.jp/)などは、ウィンドウを半透明設定することができます。背景で何か動いているのが見えるとか、メリットはそれぞれあると思いますが、何かを参照しながら入力するときに、半透明だと、入力画面からデータが透けて見えるようなメリットがある場合もあります。

# VBAでWindowを半透明化
VBAからでもWindowsのAPIを使って、Windowの透明度を変更することができます。あまり薄くすると見えにくいとか、調整が難しいのですが、特定のシートだけ半透明にするようなことができれば、もっと使い方が広がるかも！と思った次第。

まずは以下のコードを**標準モジュール**内に書きます。

```vbnet:
Const LWA_COLORKEY = &H1
Const LWA_ALPHA = &H2
Const GWL_EXSTYLE = (-20)
Const WS_EX_LAYERED = &H80000

Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hwnd As Long, ByVal color As Long, ByVal bAlpha As Byte, ByVal alpha As Long) As Boolean

' 不透明度opacityは0（透明）から1（通常）の間
Sub SetOpacity(opacity As Double)

    On Error GoTo DoNothing
 
    Dim h As Long
    Dim attr As Long
 
    h = Application.hwnd
    attr = GetWindowLong(h, GWL_EXSTYLE)
    SetWindowLong h, GWL_EXSTYLE, attr Or WS_EX_LAYERED
    
    SetLayeredWindowAttributes h, RGB(0, 0, 0), CByte(opacity * 255), LWA_ALPHA
 
DoNothing:
 
End Sub
```

使い方は簡単で、引数に0から1の間の数値を渡すだけです。0.5を渡せばちょうど半分透明になり、0.7ならそれより濃く、0.3ならそれより薄く表示されます。

# シートごとに透明度を指定
シートごとにopacityという名前を定義して、ブック（ThisWorkbook）に以下のコードを入れると、シートを切り替えるごとに、それぞれのシートのセル（%フォーマットにしておくのが良いですね）に書かれた不透明度が自動設定されます。

```vbnet:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    On Error GoTo Opac
    SetOpacity Evaluate("opacity")
    Exit Sub
Opac:
    SetOpacity 1
End Sub
```

opacityの名前を設定していないシートは自動的に100%になるので、半透明化したいシートだけ、opacityを定義しておけば良いようになっています。

# 実行例
Sheet1を50%、Sheet2を75%、Sheet3を90%、Sheet4/Sheet5は設定なしとした実行例です。
![translucent.gif](https://qiita-image-store.s3.amazonaws.com/0/220842/a4412516-f464-7a24-59f5-327d5425024b.gif)

# シート範囲の名前をまとめて定義
名前はそれぞれのシートに定義しても良いし、各シート範囲のopacityを別シートに一括設定するのも、ひとつの方法です。

文章で言ってもわかりにくいので、すべてのシートを80%透明度として一覧のopacityシートを作成するVBAコードを最後に書いておきます。シートごとの範囲名って、別シートに定義できるんですね。

```vbnet:
Sub CreateOpacityList()
    Dim sheet As Worksheet
    On Error Resume Next
    Set sheet = Worksheets("opacity")
    If sheet Is Nothing Then
        ' opacityシートがなければブックの最後に追加する
        Worksheets.Add after:=Worksheets(Worksheets.Count)
        Set sheet = ActiveSheet
        sheet.Name = "opacity"
    End If
    ' 1行目は見出し
    sheet.Range("A1").Value = "シート名"
    sheet.Range("B1").Value = "不透明度"
    Dim cell As Range
    Set cell = sheet.Range("A2")
    For Each sheet In Worksheets
        If sheet.Name <> "opacity" Then
            cell.Value = sheet.Name
            With cell.Offset(0, 1)
                .Value = 0.8
                .Style = "Percent"
            End With
            sheet.Names.Add Name:="opacity", RefersTo:=cell.Offset(0, 1)
            Set cell = cell.Offset(1, 0)
        End If
    Next
End Sub
```

上記コードを実行して生成されたopacityシートには、シート名ごとに80%と書かれているので、この値を変更することで、シートごとの不透明度を設定することができます。
iOS11.1.2でrootを取ってデバイスの解像度を変更する

<font color=red>あくまで自己責任で</red>

iOS11.1のexploitを検証できるコードが公開されました。

https://github.com/benjibobs/async_wake

このexploitでiOS11.1の64bitを含む全ての端末でroot権限を獲得することが出来ます。

また、async_wakeのサンプルでは端末の解像度設定が書き込まれているcom.apple.iokit.IOMobileGraphicsFamily.plistを書き換えるデモが入っており簡単に試す事ができます。

https://github.com/benjibobs/async_wake

からソースを落としたら、xcodeでプロジェクトを開きます。

デフォルトではrootを取るログを出すまでのサンプルになっているので、下記のフラグを解除して解像度の書き込みデモの処理を通らせます。

```c:async_wake.c
bool shouldChangeResolution = false;
```
https://github.com/benjibobs/async_wake/blob/master/async_wake_ios/async_wake.c#L931

あとは実機で実行してデバイスをリブートすれば解像度が変わっているはずです。

<img width="414" alt="IMG_0001.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/24979/4330498c-9e29-14de-bd15-16d919f458df.png">

解像度設定は同梱のplistに記載されています。
【リベンジ】KNN（K近傍法）を実装してみた

Nuco Advent Calendar 14日目の記事です。

[前回の記事](https://qiita.com/ishigero/items/e50100bf593a1b830d60)を書いた翌日、数人の方から「おい、何だよあの記事ww」と言われました。
今回はリベンジです。

#KNN？
>特徴空間における最も近い訓練例に基づいた分類の手法であり、パターン認識でよく使われる。

分類手法の一つですが、[こちら](https://qiita.com/NoriakiOshita/items/698056cb74819624461f)の記事が分かりやすかったです。

#ソースコード
[こちら](https://github.com/ishigero/nearest_neighbor_algorithm)です。jupyter使いました。

#分類データ
今回は以下のようなアヤメのデータセットを使いました。
データ数が150件だったので、30件をテストデータとしました。

| 萼片の長さ      |       萼片の幅 |    花弁の長さ    |花弁の幅    |アヤメの種類    |
|:-----------------|------------------:|:------------------:|:------------------:|:------------------:|
|　　5.4|3.7　|1.5|0.2|setosa |
|　　5.7|2.6　|3.5|1|versicolor
|　　6.9|3.2　|5.7|2.3|virginica

#パラメータから分類できそうか確認
![final.png](https://qiita-image-store.s3.amazonaws.com/0/186503/443da239-3f94-1024-124d-a1b26f18b4fd.png)

プロットした結果から、petal（花弁）の長さと幅にしました。
左上です。

#k=8の場合
accuracy 0.97でした
`actual: virginica, predict: versicolor, result: 外れました`

#k=1の場合（最近傍法）
accuracy 0.93でした
`actual: virginica, predict: versicolor, result: 外れました`

#まとめ
データセットが少ないですが、よく成長したversicolorと、あまり成長していないvirginicaは見分けにくいということが分かりました。