OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleのCloudVisionAPIを簡単に試してみる

（著：塩崎）

GoogleCloudVisionAPIの簡単な使い方です。

オフィシャルなドキュメントだと画像ファイルのパスとAPI種別を記載した
CSVを作成してそれを読み込んで処理するようになっているのですが、
とりあえずすぐに試したい場合は回りくどいので、直接画像ファイルを
指定してすぐに結果が試せるようにしてみました。

#事前準備

1.コンソールにてアカウント作成
2.APIをイネーブル化
3.APIキーを取得

詳細は下記サイトなどの情報を参考にしてください。

・GoogleCloudVisionをPythonで試すための最初の手順
[https://qiita.com/bobu_web/items/0fe215a26ecd4c883aab]

#APIを叩いてみる

APIキーを取得できたら、画像を用意して下記のコードを
実行すれば、結果のJSONファイルが表示されます。
画像はコードと同じフォルダに置いてください。

処理の流れとしては、画像ファイルを読み込んで
Base64でエンコードし、APIコール用のJSONファイルを
作成してPOSTするだけのシンプルなコードです。


```
'''
Google Cloud Vision API     T.shiozaki
'''

import base64
import datetime
import json
import requests

def makeJson(fpath, feature=0, max_results=10):
    with open(fpath, 'rb') as image_file:
        content_json = {
            'content': base64.b64encode(image_file.read()).decode('UTF-8')
        }

    feature_json = {
        'type': get_detection_type(feature),
        'maxResults': int(max_results),
    }

    request = {
        'features': feature_json,
        'image': content_json,
    }

    return {'requests': request}

#検出APIの種類一覧（0～10で指定）
DETECTION_TYPES = [
    'TYPE_UNSPECIFIED',
    'FACE_DETECTION',
    'LANDMARK_DETECTION',
    'LOGO_DETECTION',
    'LABEL_DETECTION',
    'TEXT_DETECTION',
    'SAFE_SEARCH_DETECTION',
    'DOCUMENT_TEXT_DETECTION',
    'IMAGE_PROPERTIES',
    'CROP_HINTS',
    'WEB_DETECTION'
]

def get_detection_type(detect_num):
    detect_num = int(detect_num)
    if 0 < detect_num < len(DETECTION_TYPES):
        return DETECTION_TYPES[detect_num]
    else:
        return DETECTION_TYPES[0]

def detect(fpath, feature=0, max_results=10):
    api_key = '***********'  #ここに自分で取得したAPIキーを記載する
    api_url = 'https://vision.googleapis.com/v1/images:annotate?key=' + api_key
    json_data = json.dumps(makeJson(fpath, feature, max_results))
    headers = {'Content-Type': 'application/json'}
    response = requests.post(url=api_url, data=json_data, headers=headers)
    return response.text

if __name__ == '__main__':
    print(detect('sample.jpg', 4, 50))  #引数：画像へのパス、検出用API種別ID、最大件数

```

#結果
試しに、下記の力士の画像でSAFE_SEARCH_DETECTIONを試してみました。

![sumo.jpg](https://qiita-image-store.s3.amazonaws.com/0/204591/a648b784-36f0-e289-5035-821523402a76.jpeg)

結果は、以下の通り。

```
{
  "responses": [
    {
      "safeSearchAnnotation": {
        "adult": "VERY_LIKELY",
        "spoof": "VERY_UNLIKELY",
        "medical": "UNLIKELY",
        "violence": "UNLIKELY"
      }
    }
  ]
}
```

adultが**"VERY_LIKELY"**となっており、アダルト判定されました。。。
確かに見事な巨乳ですからね（笑）。。。
Deep Models Under the GAN: Information Leakage from Collaborative Deep Learning「論文」


敵対生成モデルに対してリアルに攻撃する系の話。
ざっくりしか読んでないですのでツッコミなど歓迎です。

<img width="1019" alt="スクリーンショット 2017-09-28 17.08.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/64334/d81c0bff-b90c-2141-442a-02b1e52b15d7.png">

図aのモデルが中央サーバーにある場合は悪意を持ったユーザーは中央サーバーに入ってゴニョゴニョする必要があります。
図bの場合はモデル携帯などに分散されてて、パラメータのみ中央サーバーにある構成の場合。
そもそもこんな構成のシステムってどのくらいあるのだろうか。確かにリアルタイムで学習結果が適応される場合は困る。


<img width="373" alt="スクリーンショット 2017-09-28 17.11.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/64334/949d3578-2976-4404-510f-c3f7b3127253.png">
どなたかの画像データXを再構築してX'を作成。

<img width="1043" alt="スクリーンショット 2017-09-28 17.12.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/64334/7a2e4768-98c1-ca44-22c2-4b4ff5286364.png">

GANの深層学習に対する攻撃。 左が攻撃者。右は一般ユーザー。端末で学習したパラメータ値をサーバーに返してる。


<img width="409" alt="スクリーンショット 2017-09-28 17.16.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/64334/b9b6907f-f4e7-7491-198f-fd2719d2b45e.png">
MNISTデータセットで訓練されたCNNでmodel inversion attack（MIA）とgenerative adversarial network （DCGAN）を実行した場合の結果。 DCGANはうまくいってるが、MIAはよくない。


#参考
https://arxiv.org/pdf/1702.07464.pdf
【LINE DEV DAY 2017】セキュリティのためのデータ分析 / ログ分析プラットフォーム Monolith と LINE Spam対策の現状 #line_devday


# 概要
LINE セキュリティ室で行っているデータ分析事例を2つ紹介します。
ひとつはサーバ、PC、ネットワークといったインフラに関わるシステムログを収集し、不正侵入、高負荷、情報漏洩といったインシデントをいち早く検知するシステム、プラットフォームの構成と活用事例を解説します。
もうひとつは LINE での迷惑メッセージ(Spam)対策の現状と、ユーザーからの通報データをもとに、Spamらしさを分析し、自動でブロックするAnti-Spamシステムについてを紹介します。

# アジェンダ
* インフラセキュリティの話
* スパム対策の話
* キーワードはログ解析

# インフラセキュリティ Monolith
ログが色々なデバイスに保存されるため、それぞれのデバイスからログを収集する必要があった。
Kafka hadoop elastic連携してログの保存、監視。
機械学習(マシンラーニング)でログを監視し、危険度を可視化。

# スパム対策
2013年からスパム対策を実施して、件数は減少傾向。2015年から横ばい。
LINEではユーザがスパムを通報する機能があり、それを分析している。

各国別の通報件数
多い順に
* 台湾
* 日本
(ほぼ同じくらい)

スパムメッセージは国によって内容が大きくことなる傾向がある。

## ルールベースのフィルター
例えば、1秒間に1000人友達追加したら、みたいなルール。(実際にはこのルールは使われていないらしい)
当てはまれば、ほぼ間違いなくスパムであるものをルールで弾く。

## マシンラーニングベースのフィルター
ユーザからの通報データを元に自動的に学習と検知を繰り返す。
動かし始めれば自動的にルールが更新される。
ユーザからの通報メッセージは、80%は本当のスパムだが、残りの20%は誤報である。
ユーザからの通報が多いメッセージはスパムと判定するなどを実施している。

## 監視者自身のフィルター(モニタリング)
最後は人が判断するものが残る。
正常なユーザを誤検知することを避けるため、少しゆるめのルールで運用を行っている。
そのためフィルターから漏れたスパムに対して、人によるモニタリングが必要。
[Survey] Kaggle - Santander 11位解法まとめ

Kaggle - Santander Product Recommendation[^1]の11位解法[^2]の調査記事です．

Names: Rohan Rao, SRK
Kaggle Discussion: https://www.kaggle.com/c/santander-product-recommendation/discussion/26823
Code: https://github.com/rohanrao91/Kaggle_SantanderProductRecommendation



## 要点

- 24変数のうち19変数のみ利用(ahor, aval, deco, deme, vivは利用せず)
- 2015年6月と2016年5月を利用した2つのモデルを作成.(6月と5月のモデルはそれぞれ季節性と傾向を捉えるために利用)
- 新製品のみで作ったSRKのモデルは，データ全体を使って作ったモデルより性能がやや悪い程度だった．(原因は不明)
- 6月モデルでの主な特徴量: Lag1〜5(過去データの平均),前月の所有製品数,前月に所持していた製品を表す19桁の数字(各桁の0,1で製品の所持状況を表現)
- 5月モデルに別途追加した追加特徴量: Lag6,9,12(過去データの平均)
- Public LBへの過学習を避けるために10-foldでのCVスコアでローカル上は評価するようにした．
- baggingやパラメータチューニングでは改善されなかったため，特徴抽出の改善に従事．
- 2つのモデルのアンサンブルによってスコアは，0.0303から0.0306へと悪化．

## その他

季節性と傾向の2種類を見つけることが肝だった．

- 例
	- 特定の製品は2015年1月〜5月と比べて2016年5月の分布が結構違ってたので，季節性のある製品と考えた．
	- 特定の製品は2016年1月〜5月と比べて2015年1月〜5月の分布が大分異なってたので，傾向のある製品と考えた．

製品ごとに異なる重みを使用してアンサンブル

- 例
	- ccoとrecaは2015年6月にスパイクがあっため，傾向でのモデルより季節性でのモデルの重みを高めに設定

## References

[^1]: Kaggle, [Santander Product Recommendation](https://www.kaggle.com/c/santander-product-recommendation).
[^2]: Rohan Rao, [#11 Solution and Code](https://www.kaggle.com/c/santander-product-recommendation/discussion/26823)
水没ラズベリーで猛暑を乗り切ろう！（その後）

# 伝えたい この思い

ラズベリーパイくんが水没中に快適なSummer Lifeをenjoyできているかどうか、どうやって確認しよう。
離れていても、彼が元気な状態だということがこちらに伝わればいいんだよね。

そこで、
**hubot-cron** を使って、定期的に発言できるようにします。
###Kanaのインストール方法
1.　Gitとnodeのインストールをする。
[http://qiita.com/natacom/items/63cca20e24e3e864e485](http://qiita.com/natacom/items/63cca20e24e3e864e485) ← git
[http://qiita.com/setouchi/items/437e4b62e4210871496f](http://qiita.com/setouchi/items/437e4b62e4210871496f) ← node 

2.　git clone でkanaをクローンする
適当なフォルダで以下のコマンドを実行

```sh
git clone https://github.com/central-soft/hubot-kana.git
```

hubot-kanaフォルダが出来たことを確認

3.　依存関係のパッケージをインストール

```sh
cd hubot-kana
npm install
```

4.　slackトークン・タイムゾーンを環境変数にセット（exportで一時的にセットすればいいかも）
以下にコマンドを記載します。が、トークンは編集してあります。

```sh
export HUBOT_SLACK_TOKEN=xxcc-563268864214-xxxxyyyyzzzxghfdyh
export TZ=Asia/Tokyo
```

5.　BOT起動
slackアダプタを使用するオプションをつけて起動します。

```sh
bin/hubot -a slack
```

6.　定期的に呟くように命令する（Slackで実行）
呟かせたい部屋で以下のように入力（10分に1回設定だとこう）
![image2017-8-15_23-51-45.png](https://qiita-image-store.s3.amazonaws.com/0/197848/f5e32e15-927e-af88-18a5-5445148426c7.png)


#守りたい この思い
これで必要なモノは揃った！
心の準備はできた！

僕らの試みの今回のウリは、
「机上の作業ではない」ということ。

小学生の頃の理科の実験や、夏休みの自由研究に近いかも。

なにがスゴいって、ワクワク感がスゴい！
**よーし！やったるぞー！**
**Never Wet ぶっかけたるー！**



皆の盛り上がりが最高潮に達したその時・・・


###**<font color="Red">ドンッッ！</font>**
![neverwet2.jpg](https://qiita-image-store.s3.amazonaws.com/0/197848/a497ce83-7a8c-14c7-9afa-8a089e81a49d.jpeg)
###**<font color="Red">バンッッ！</font>**
![neverwet.jpg](https://qiita-image-store.s3.amazonaws.com/0/197848/7e89fa9f-09e7-a9cf-eb4a-8d4d6dbaca67.jpeg)


続け！
Elasticsearchを導入しようとしたらエラーで起動しても速攻死ぬ問題

# Elasticsearchを導入しようとしたらエラーで起動しても速攻死ぬ問題
Elasticsearchを起動したが、どうやら立ち上がってないようだった。
そこで `/var/log/elasticsearch/elasticsearch.log` に記述されているログを確認した

```
[2017-09-28T07:44:50,362][INFO ][o.e.n.Node               ] [5MEDJRz] starting ...
[2017-09-28T07:44:50,766][INFO ][o.e.t.TransportService   ] [5MEDJRz] publish_address {10.0.2.15:9300}, bound_addresses {[::]:9300}
[2017-09-28T07:44:50,829][INFO ][o.e.b.BootstrapChecks    ] [5MEDJRz] bound or publishing to a non-loopback or non-link-local address, enforcing bootstrap checks
[2017-09-28T07:44:50,850][ERROR][o.e.b.Bootstrap          ] [5MEDJRz] node validation exception
[2] bootstrap checks failed
[1]: max number of threads [1024] for user [elasticsearch] is too low, increase to at least [2048]
[2]: system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk
[2017-09-28T07:44:50,860][INFO ][o.e.n.Node               ] [5MEDJRz] stopping ...
[2017-09-28T07:44:50,995][INFO ][o.e.n.Node               ] [5MEDJRz] stopped
[2017-09-28T07:44:50,995][INFO ][o.e.n.Node               ] [5MEDJRz] closing ...
[2017-09-28T07:44:51,020][INFO ][o.e.n.Node               ] [5MEDJRz] closed
```

起動しても速攻落ちてるんかーい！

## 調べてみた
### 一つ目
`[2]: system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk`


> https://www.elastic.co/guide/en/elasticsearch/reference/current/system-call-filter-check.html

ふむふむ、これの対応として、以下を `/etc/elasticsearch/elasticsearch.yml` に追記すれば良いんですね
```bash
bootstrap.system_call_filter: false
```

### 二つ目
`[1]: max number of threads [1024] for user [elasticsearch] is too low, increase to at least [2048]`
> https://www.elastic.co/guide/en/elasticsearch/reference/master/max-number-of-threads.html

このやり方は正しくはないだろうが、 `/etc/sysconfig/init` に以下を追記しました。a
```bash
ulimit -n 65536
```

## 結果...
やったね！
redmine バージョン確認コマンド

### redmine バージョン確認

bitnami@ubuntu:~/apps/redmine/htdocs/lib/redmine$ cat /home/bitnami/apps/redmine/htdocs/lib/redmine/version.rb
require 'rexml/document'

module Redmine
  module VERSION #:nodoc:
    MAJOR = 3
    MINOR = 3
    TINY  = 1
3.3.1

### ruby バージョン確認
bitnami@ubuntu:~/apps/redmine/htdocs/lib/redmine$ ruby --version
ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux]

### rails バージョン確認
rails --version
gulp-sass で autoprefixer 組み合わせた時に sourcemap 見えない問題

### gulp-sass で autoprefixer を使うと sourcemap が表示されない。

```
"gulp-autoprefixer": "^4.0.0",
"gulp-sass": "^2.3.2",
"gulp-sourcemaps": "^1.6.0",
```

として

```

gulp.task("sass",() =>
    gulp.src([dir.src + "/**/*.scss"])
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(sass().on('error', sass.logError))
    .pipe(autoprefixer())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest([dir.env])
);

```
これだと、ソースマップは吐き出されてるけど、
console で見ても、css しか参照されない。



https://www.npmjs.com/package/gulp-sourcemaps

よくわからん。


ググったら、 魔法の2行を加えると動くとある。

https://github.com/gulp-sourcemaps/gulp-sourcemaps/issues/60#issuecomment-220313018

即`いいね`ボタン押してソースに反映してみる。

```

gulp.task("sass",() =>
    gulp.src([dir.src + "/**/*.scss"])
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(sass().on('error', sass.logError))
    .pipe(sourcemaps.write({includeContent: false}))
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(autoprefixer())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest([dir.env])
);
```

これで正確に sass の行数が参照可能。
autoprefixer の前に、sourcemaps のオプション使って、Mapをうまく継承してるっぽい。
sourcemaps が 2つ書き出されてた。すごい。



## minify もしておきたい。

gulp-sass の `Compressed` 使うと sourcemap の位置が崩れるのは変わらずなので、
別のプラグインで minify する。
`gulp-cssnano` 使うと minify した時に `" "` が外れる場合があるので、
`gulp-clean-css` 使って minify する。


```

gulp.task("sass",() =>
    gulp.src([dir.src + "/**/*.scss"])
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(sass().on('error', sass.logError))
    .pipe(cleancss())
    .pipe(sourcemaps.write({includeContent: false}))
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(autoprefixer({ browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']  }))
    .pipe(sourcemaps.write())
    .pipe(flatten())
    .pipe(gulp.dest([dir.env])
);

```
これで、デプロイと同じ minify されたcssファイルで開発できる。

以上。
キッチンタイマー買ったら作業効率が倍になった話

<img width="858" alt="Screen Shot 2017-09-28 at 16.46.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/29792/7edf5821-79f0-6409-7e43-3ebc920e1a7b.png">

(この記事を書き始める前にも25分のタイマーをセットしました。)

#### 今回使うタイマーは..
上限99分で時間が来ると無音&光で教えてくれるタイプのものです。
詳しい仕様は[こちら](http://amzn.to/2yv3yAb)から

それでは、タイマーを買ってとっても幸せになった話をしていきます。

## タイマーを使った作業のフロー
1~3まであります。

#### 1. 進めるべき作業を選択
ここで言う作業とは、「プロダクトAの作業を進める」や「溜まってる連絡を返す」などのざっくりした内容のことです。
#### 2. タスクに分解
タスクとは、「バグAのコードをする(プルリク作成は含まなない)」や「山田さんの連絡を返す」や「Qiitaにタイマー記事を投稿する」などです。
特徴としては

- チームで管理されてるものではなく、個人のメモのようなもの
- サイズが小さくてかかる時間が想像できる

といったものです。

#### 3. タイマースタート
選択したタスクにかかる時間を見積もってタイマーをスタートします。
正確である必要はなく直感的に決めれば良いです。
私の場合だと、5~30分の間になることが多いです。1日に二回くらい60分以上のタスクもあります。

#### 4. 時間内に終わらなければ、もう一度タイマーセット
時間内にタスクを終えられなくても全然大丈夫です。意味があるのはこのフローそのものなのです。
なので、時間を再見積もりして追加します。

## どう良いのか
結論から言うと**効率が倍**になりました。
理由は以下のような感じかと思います。

1. 常にタスクを**分解**するくせがつく
2. タスクに**かける時間**と**かけた時間**を意識できる
3. 途中で他の作業をせず、一つのタスクに集中できる

あと東大医学部の人もタイマーが良いって言ってました。
(ここでタイマーが光ったので、20分追加しました。)

## 意外としんどくないですよ
やる前はタイマーで自分を管理したらノイローゼになるのではくらいに思っていたのですが、全然そんなことないです。
タイマーを使う前は１日の作業をタスクまで分解できておらず、ただ漠然と忙しいなあと感じてました。
今思えば、そちらのほうが精神に与える負担は大きかったです。
タイマーは友達みたいなものです。音がならず光るだけのタイマーを使っているのでとても優しく時間を教えてくれます。

## タイマーの購入はこちらから
なんでもよいのですが、消音できて光だけで教えてくれるものです。音がなるとプレッシャーで疲れてしまいそうなので。
今回の用途には、私の使ってるキッチンタイマーがぴったりなのでリンクを張っておきます。

[Amazon 光と音で知らせる! ! デジタルタイマー](http://amzn.to/2yv3yAb)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/29792/596c039c-93a1-2335-3e81-6dc049fd421b.png)


## タイマー教としてのマインド
最近思うのは、時計って不完全だなと言うことです。
時計があれば、他人とリズムを合わせることはできますが、時間を感じる事はできません。
家をでるときに、待ち合わせ時間までのタイマーをセットする方が遥かに時間を感じれます。
自分でも何言ってるかわからなくなってきたけど、

タイマーを持ち歩くってめちゃくちゃ気持ちいですよ。


<img width="652" alt="Screen Shot 2017-09-28 at 17.02.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/29792/2b49be7b-c599-76af-aa26-3e2bb6a6ad80.png">
この記事を書くのにかかった時間は(途中で20分追加したので)45分でした。
測ってみると意外と時間ってかかってますよね。
この感じが[どう良いのか](#%E3%81%A9%E3%81%86%E8%89%AF%E3%81%84%E3%81%AE%E3%81%8B)で話した「2. タスクに**かける時間**と**かけた時間**を意識できる」です。
不可視文字を手っ取り早く確認する方法

## やりたいこと
不可視文字の正体を暴く

## コマンド
```
cat [ファイル名] | od -An -tx1c
```

### オプションの説明
-An：標準では左側に基数が表示されるが、いらないので非表示にする。
-t：表示のタイプを指定。
x：16進数表示。uにすれば10進数表示。
1：1byteずつ表示する。
c：文字を表示する。

x1はなくても大丈夫といえば大丈夫ですが、半角スペースが分かりにくくなるので
あった方がいいです。

## 実験＆少し説明
### 実験用ファイル作成
```
echo -e " a\n\rb\nc\nd\r\ne " | sed 's/ a/\ta/' >test
```

```bash:test
        a
b
c
d
e
```

### コマンドを実行してみる
```bash
cat test | od -An -tx1c
  09  61  0a  0d  62  0a  63  0a  64  0d  0a  65  20  0a
  \t   a  \n  \r   b  \n   c  \n   d  \r  \n   e      \n
```

すなわち、
aの前にあるのは半角スペースではなくタブ文字(LF改行)
bは先頭文字かと思いきや、キャリッジリターンからのb(LF改行)
cは特になにもなし
dはCRLF改行(捉えようによってはデータがd[CR]でLF改行)
eは即改行かと思いきや、最後に半角スペースあり(LF改行)

odには他の使い方もあるかもしれませんが、私はこの用途でしか使用していません。

ファイルが複数行ある場合は16byte毎に改行されて表示されます。

以上

## 参考にさせて頂いたサイト様
http://itpro.nikkeibp.co.jp/article/COLUMN/20060227/230853/
https://hydrocul.github.io/wiki/commands/od.html
Gitの学習メモ

Gitで学習したことをつらつらとメモ！！
------------

Gitで管理したい場所を設定するには…。

~/workspace/demo $ git init
Initialized empty Git repository in /home/ubuntu/workspace/demo/.git/

このコマンドでGitで管理する場所であるということを教えてあげる！
あとはこの場所にいろいろとファイルを追加していくことで、履歴管理をしていくよ。

------------

Gitで管理するファイルを修正したら、Gitに修正したことを教えてあげよう！

~/workspace/demo (master) $ git add <ファイル名>

これしないと、更新したことがわからないよ。

------------

ファイルを更新したら、どんな更新をしたかの記録をしよう！

~/workspace/demo (master) $ git commit -m "コメント"
[master (root-commit) b52e488] コメント
 1 file changed, 1 insertion(+)
 create mode 100644 sample.txt

※-m "コメント"を忘れると、コメント書いていないよ！と言われてviが開くよ
　コメントは忘れないようにしようね。


------------
基本的な流れ

1.ファイルを修正
2. git add でファイルに修正があったことを教える
3. git commit -m でどんな修正があったかを記録
4. git push でリモートリポジトリにファイルをアップする


------------

git log　は今まで記録してきた commit -m のコメントが確認できる。

~/workspace/demo (master) $ git log
commit 1c8c83b2d0ec2613bb924374ebcfd28120600753
Author: nkns <xxxxx@gmail.com>
Date:   Thu Sep 28 01:13:05 2017 +0000

    簡単さ追加

commit 087c64896f3474aceb448b3791e61b116a94040e
Author: nkns <xxxxx@gmail.com>
Date:   Thu Sep 28 01:08:02 2017 +0000

    句点を追加

commit b52e488e7e5b7aa5134861e0d8d9c7c0c95a704a
Author: nkns <xxxxx@gmail.com>
Date:   Thu Sep 28 01:05:54 2017 +0000

    はじめの一歩

------------

ファイルを消したときは？

$ git checkout <コミットID> <ファイル名>

コミットIDは、git log --oneline で確認できる。

git log --oneline
1c8c83b 簡単さ追加
087c648 句点を追加
b52e488 はじめの一歩
Docker HubのAutomated BuildsでGitタグを正規表現で置換してDockerイメージタグをカスタマイズしたい

タイトルが長いですが、一言でいうと
DockerfileのGitのタグが `v0.1.1` のときに、Dockerイメージのタグをvなしの `0.1.1` にしたいのです。
ただの好みの問題なんですけど。

やり方は公式ドキュメントには載ってないみたいなんですけど、同じことを思った人がIssueに上げてて、解決策が書いてありました。

[Bugfix - Trigger Wildcard Matches for Tags in Automated Builds #384](https://github.com/docker/hub-feedback/issues/384)

結論だけ言うと、Gitタグを `/^v([0-9.]+)/` で正規表現マッチさせて、 イメージタグを `{\1}` とすると、 `()` でキャプチャしたところだけ参照できるようです。

文字で説明してもなんだか分かりづらいので、参考までにDocker Hubの設定画面のキャプチャを貼っておきます。
Build Settingのところで、以下のように設定すればOKです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/61152/fae471da-12ec-b763-d10c-ec53ca023dda.png)

ビルドされたイメージを見るとちゃんとvがなくなってますね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/61152/195d12f0-8746-1f6b-18b2-34e3e415be22.png)

正規表現で置換できればだいたいなんでもできると思うので、Dockerイメージのタグを好みでいいかんじにカスタマイズしたい人の参考になれば。
RaspbianでOpenJTalkを使う


RaspberryPiに日本語を喋らせます。必要なパッケージを追加します。

```
sudo apt install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
```

音声合成には関係ないですが、日本語のテストをしやすくするために、フォントとIME(日本語の入力機能)を追加します。

```
sudo apt install ibus-mozc fonts-takao
```

辞書と音声ファイルを明示する必要があります。wav形式で保存します。

```
echo "こんにちは" | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -ow test.wav
```

テストには `aplay` というコマンドが利用できます。

```
aplay test.wav
```

上記でインストールしたのはOpenJTalkに標準で含まれる男性の声です。下記のサイトでは女性の声のサンプルを手にいれることができます。アーカイブを展開した中にある拡張子が `.htsvoice` のファイルを上記の `open_jtalk` コマンド実行時に指定してください。

https://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/MMDAgent_Example-1.7/
MCP資格を別のマイクロソフトアカウントに移すためにしたこと

# きっかけ
今の会社から転職することにしました。
しかし、取得したMCP資格が会社のメールアドレスで作成したマイクロソフトアカウントに紐づけられています。
自分のメールアドレスで作成したマイクロソフトアカウントが既に存在するため、メールアドレスを変更するという方法も使えません。
なので、MCP資格を別のマイクロソフトアカウントに移すことが可能なのかどうか調べてみました。

# 前例あるのか調べてみた
https://social.msdn.microsoft.com/Forums/en-US/23cd2ff5-b9a2-442a-814b-9adf465963a6/transfer-mcp-to-another-account?forum=CertGeneral

どうやら同じ悩みを抱えていた人はいたようです。
この質問の回答には「Contact your Microsoft Regional Service Center.」の一文。
なるほど、では問い合わせてみることにしましょう。

問い合わせ先はコチラ。
https://www.microsoft.com/ja-jp/learning/help.aspx
日本の問い合わせ先がありました。
営業時間は「月曜日～金曜日 9:00 ～ 17:30 (9:00 A.M. ～ 5:30 P.M.) 現地時間」だそうです。

# 問い合わせてみた
MCPを別のマイクロソフトアカウントに紐づけたいという旨の話をするとすぐにわかりましたと連絡がありました。
今のマイクロソフトアカウントに紐づいているマイクロソフト認定資格IDの紐付を外してこちらで紐付け直す必要があるそうです。

マイクロソフトさんが紐付を解除したのちに再紐付に必要なアクセスコードが書かれた英語のメールと、紐づけ方が書かれた日本語のメールを送ってくれます。
案内によると、日本語のメールから開いてもらい、アクセスコードが必要になったときに英語のメールを開いてほしいとのこと。間違えるとまた手間になりますしね。

# 移行してみた
1. 送られてきたメールを元に、アクセスコードとマイクロソフト認定資格IDを入力する
2. Nextのボタンを押す
3. おわり

おわりです。

本当にこれだけでした。びっくり。

# まとめ
想像していた10倍ぐらい簡単に終わりました。
もっと複雑怪奇なことをやらされるものとばかり。すごい。
feature specでActiveJobを実行する

RSpecで、featureのテストを書いていたときに、ActiveJobにファイルの生成を依頼して、生成できたらファイルをダウンロードするような処理を書いていたときに、ActiveJobが動いていなくてエラーになったので、どうやったらActiveJobをfeature specを実行中に動かせるかを調査した。

# 解決策

## ActiveJobを即時実行する設定にすればよい

実は、参考になる記事がすでにQiitaに書かれていた。

[RSpec でキューイングした ActiveJob を同期実行する](https://qiita.com/upinetree/items/41a2a8fe9e1dd7c291ab)

この通りにすればできた。非常にありがたい情報だった:pray:

# 別の解決策

上記の解決策でできたのだけれど、やはり冗長な感じがした。
もっとシンプルにしたいと思ったので、自分はshared_contextを利用する方式に変更した。

```rb:spec/support/perform_enqueued_jobs.rb
shared_context :perform_enqueued_jobs do
  around :each do |example|
    perform_enqueued_jobs { example.run }
  end
end
```

テスト側で、ActiveJobを使うfeatureのテストの場合は、include_contextを使う。

```rb:spec/features/foo_spec.rb
feature 'foo' do
  include_context :perform_enqueued_jobs

  scenario 'ActiveJobを使うシナリオ' do
    # なにかしらの操作
  end
end
```

こちらのほうが変更点も少なくてシンプルじゃないかなと思う
Movable Typeで関連記事を表示するプラグイン「SimilarEntries」をランダム表示にする

「SimilarEntries」は、カテゴリー・カスタムフィールド・タグなどが一致している記事を自動表示するMovable Type用プラグインです。

https://github.com/bit-part/mt-plugin-SimilarEntries

こちらの投稿で解説したとおり、関連記事の表示結果は固定順となります。
https://qiita.com/webbingstudio@github/items/588632a5f0bab9cee9b9
しかし、関連記事を導入する背景（サイト内の回遊率を増やす）を考えると、ランダム表示のほうが望ましいです。

この記事では、強制的にランダム表示に変更する方法について説明します。

#注意点

**かなり暫定的な方法です。**このため以下のリスクがあり、公開後に関与できないサイトでは導入をおすすめできないことを、あらかじめご了承ください。

- すべての表示結果がランダム表示となります。
- 表示結果の件数がlimitで指定した数値より少ないとランダムになりません（要検証）。
- プラグインのコアファイルを差し替えるため、バージョンアップ時に、該当ファイルの修正が都度必要となります。

#修正方法

以下のディレクトリにある、SimilarEntries.jsをエディタで開いてください。

Movable Typeをインストールしたディレクトリ/mt-static/plugins/SimilarEntries/js/SimilarEntries.js

30行目から60行目に「array.sort」を行っている箇所があるので、コメントアウトで無効化してください。

```js:SimilarEntries_sort.js
array.sort(function(obj1, obj2){
    for (var i = 0, l = sortCondition.length; i < l; i++) {
        var key    = sortCondition[i]['key'];
・・・
        return 0;
    }
});
```

その箇所に、以下のコードを挿入して上書き保存してください。
関連データが入っている配列を昇順ソートではなく、シャッフルするようになります。

```js:SimilarEntries_shuffle.js
var shuffle = function(arr) {    
    var n = arr.length;
    var temp, i;

    while (n) {
        i = Math.floor(Math.random() * n--);
        temp = arr[n];
        arr[n] = arr[i];
        arr[i] = temp;
    }
    return arr;
};
array = shuffle(array);
```

#参考

配列をシャッフルするロジック
http://javascript.step-learn.com/contents/J061-array-shuffle.html
sedで行（文字列）の最後のドットだけ括弧でくくりたい

　怪しげなIPアドレス・ドメイン・ファイル名などを資料に転記するとき、リンクとして機能しないよう、念のためドットを括弧でくくっている（慣例的に）。ドットを全部、“[.]”に置換すれば手間はないのだけど、見た目がごちゃごちゃするので、最後のドットだけを括弧でくくりたい（慣例的に）。

```
cat list.txt 
192.0.2.0/24
www.example.com
infected.exe
```

　これを、下のようにしたい。

```
192.0.2[.]0/24
www.example[.]com
infected[.]exe
```

　結論としては、

```:sed
cat list.txt | sed -e "s/\.\([^.]*\)$/[.]\1/"
```

　…だったのだけど、包括指定子とか後方参照子とか何？正規表現ワカリマセン。って感じだったで以下メモ。   
    
    
      
     
* 置換対象の文字列は、

```
\.           ドットで始まって、
[^.]*        「ドット以外の文字列」が後ろにあって、
$            しかるのち行末がくる
```

* で、↑こうやって指定する中で、

```:（包括指定子っていうのを入れてやる）
\(...\)     「ドット以外の文字列」を、再利用できる【カタマリ】にしておく。
            （上の例でいうと、それぞれ“0”、“com”、“exe”を取り出したイメージ）
```
　これで「sed/A/B/」のA部分が指定できた。

* 一方、「sed/A/B/」のB部分（置換後の文字列）は

```
/[.]        “.”を、“[.]”に置換する
```

　と指定したいのだけれども、そのまま実行すると、

```
cat list.txt | sed -e 's/\.\([^.]*\)$/[.]/g'
192.0.2[.]
www.example[.]
infected[.]
```

　と、素直に「最後のドット以降」をまるっと“[.]”にしてしまう。
　そこで、

```:（後方参照子っていうんだって）
\1            先ほどの【カタマリ】を参照させる
```

　ってやつを、“[.]”のお尻にくっつける。

```
/[.]\1        “[.]”に置換して後ろに【カタマリ】がくるようにする
```
  
* 実行してみる。

```:結論
cat list.txt | sed -e 's/\.\([^.]*\)$/[.]\1/g'
192.0.2[.]0/24
www.example[.]com
infected[.]exe
```

　…できた。  
  

* ちなみに以下は失敗例。

```
sed -e 's/\.\([^.]*\)$/\1[.]/g'
　→　www.examplecom[.]
「最後のドット以降（.com）」を【カタマリ（com）】に置換して、後ろに“[.]”をくっつける

sed -e 's/\(\.[^.]*\)$/[.]\1/g'
　→　www.example[.].com
「最後のドット以降（.com）」を【カタマリ（.com）】に指定しているので、ドットが１つ余る
```
  
  
参考にしました）
[正規表現 & sed & awk](https://qiita.com/yoshihikosuzuki/items/9c45bfc48512cbaef2b3)
UserDefaultsに保存したデータはiTunes/iCoudでバックアップ/復元されるのか？される。

記憶が曖昧になっていたので調査しました。

## UserDefaultsのドキュメント

まず、UserDefaultsのドキュメントを確認しましたが、こちらには記載させていませんでした。
https://developer.apple.com/documentation/foundation/userdefaults

## File Systemのドキュメント

次に、File Systemのドキュメントを確認しました。
https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html

こちらのドキュメントの`Table 1-1  Commonly used directories of an iOS app`のところにバックアップについて記載があります。

## UserDefaultsが保存されているディレクトリ

UserDefaultsに保存したデータがどのディレクトリに保存されているのか、公式ドキュメントを探しましたが見つからず、Qiitaの記事を信用することにしました。
https://qiita.com/dondoko-susumu/items/85f5e1449df94be20fa9

こちらによると`Library`の下に保存されるようです。

## 結論

File Systemのドキュメントでは`Library`ディレクトリはバックアップされると記述されています。  
UserDefaultsに保存したデータは`Library`ディレクトリの下に保存されるため、バックアップされます。

## 参考にしたページ

* https://gist.github.com/y-takagi/9f2cea659fb3f55b56aa04530bf0af39
【LINE DEV DAY 2017】HBase at LINE 2017 #line_devday


# LINEのトラフィックを支えるHBaseという技術について
LINEのメッセージングサービスにおけるHBaseエンジニアリングについて
運用環境の改善、HBase 0.90.6から1.2.5へのサービス無停止でのアップグレード、HBaseの新機能の活用事例などについて

# HBaseについて
LINEで使われているOSSのNoSQLデータベース

## どこで使っているか？
Messaging
GAME Platform
Timeline
Statistics

## どんなデータを入れているか？
user
addressbook
backup
など

## オペレーション
HBase運用専用チームはいない
Operator = Developer

## モニタリング環境
プロメテウス(Prometheus)を使用している
クラスターごとのPrometheusを集めるためのPrometheusも使用している。（こちらはポーリング間隔は長めにしている)

## HBase Versions
最新版は1.3。
今までLINEでは、安定版0.90.6-cdh3u5を使用していて、順次1.2へアップグレードしている。

### バージョン切り替え手順
dual write (0.9と1.2のDB両方に書き込み)
bulk copy (0.9のデータを1.2にコピー)
testing phase (移行したデータの確認)

## HBaseアップグレード当たって
パフォーマンスの測定
Kafka -> Shadow環境に本番運用とほぼ同じ負荷で測定可能にしている。

## HBase 0.90から1.20への切り替え
HBaseクライアントにパッチを当てた。
2～3週間はちゃんと動いていたが、徐々にレスポンスタイムが悪くなっていった。

## アップグレードして良かったか？
## BucketCache
昔はCacheをJVMのヒープに持っていたが、1.2からはヒープ外に持つようになったため、GCの対象にならずパフォーマンスがあがった。
しかし、移行は簡単ではなく色々な課題を解決する必要があった。

# まとめ
機能面でも性能面でも恩恵を受けている。
もうすぐHBase 2.0が出るという噂。
今後も継続してアップグレードしていく必要がある。
httpsでdeviseを使ってログイン機能を実装した話

自分用のメモなので見づらくて申し訳ないです...

# httpsでdeviseを使ってログイン機能を実装した話
railsでdeviseを使ってログイン機能を実装して本番環境にあげたら
真っ白いページが出てプロダクトが動きませんでした。

原因は本番環境はhttp(80番ポート)が閉じられていてhttps(443番ポート)しか
空いていませんでした。
なのでrailsがリダイレクトなどの処理を行うときにhttpでリダイレクトをしようとして
うまく動かなくなっていたみたいです。
なのでrailsとnginxにhttpsでリダイレクトをするという設定を追加しました。


config/enviroments/development.rb
または
config/enviroments/production.rb
の末尾に
````
config.force_ssl = true
````
を追加してrails自体の通信を強制的にhttpsで通信するように変えます。

ただ、このままではhttpとhttpsで何度もリダイレクトを起こしてしまうので
nginxの設定ファイルに
````
proxy_set_header X-FORWARDED_PROTO https;
````
を追加します。

これでnginxを再起動すれば動くはず!

解決するのに3日間もかかってしまったのは内緒

rails初心者なので補足などがあれば教えていただきたいです...


# 設定の詳細
````
config.force_ssl = true
````
[rubyonrailsのconfig.force_ssl = trueの時の挙動](http://api.rubyonrails.org/classes/ActionDispatch/SSL.html)
[HTTP Strict Transport Security](https://developer.mozilla.org/ja/docs/Web/Security/HTTP_Strict_Transport_Security)
1. httpのリクエストをhttpsにリダイレクトする
2. セキュアなクッキーを通知する
3. HTTP Strict Transport Security (HSTS)：ブラウザにhttpsでしか通信できないと通知する
````
proxy_set_header X-FORWARDED_PROTO https;
````
[proxy_set_header](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header)
要求されたヘッダーにhttpsの通信であることを追加している？
smartparensで言語ごとの設定

# smartparensでの言語ごとの設定
pareditを使ってたけど、シングルクオートなどを括弧として扱わないようにする方法が分からなかったので、smartparensに移行した。
そのついでに設定方法も調べたのでメモしておく。

```el:lisp-mode
(require 'smartparens)

(sp-with-modes '(lisp-mode lisp-interaction-mode slime-mode)
   (sp-local-pair "'" nil :actions nil)
   (sp-local-pair "`" nil :actions nil))

(provide 'smartpares-lisp)
```

lisp用の設定だとこんな感じにした。直接lisp用の設定ファイル中に書いてもよかったけど、smartparensにあったサンプルを参考にして分割してみた。実際に使う場合は`(require 'smartparens-lisp)`とする必要がある。
`sp-local-pair`は特定のmodeだけで有効になるpairを設定できて、既存のpairを上書きするらしい。
他にもactionを設定することでpairの補完を自由に拡張できるようになっていたり、unlessキーワードなんかもあるので文字列中ではpairの補完をしないようにしたりもできるようなので、使いやすくしていきたい。

pareditで使っていた機能は元々存在していたので、キーバインドを設定したりは問題なくできた。
pareidtのキーバインドを使うようにする設定もあるらしい。
iPhoneXだけSafeAreaLayoutGuideにConstraintsを貼るようにした

そうです。ゴリ押しです。

iPhoneXの発表を受けてDeveloperの皆様方いかがお過ごしでしょうか。

私はstoryboardに`safeAreaLayoutGuide`が追加されて、「ほーステータスバーとか出していく方針なのか」「まぁフルスクリーンだし無視して潜り込ませていこうか」とタカをくくっていたところXcode9 GM Seedまでひた隠しにされたiPhoneXにしてやられた形です。なんですかあの切欠きは。

そう、`SafeAreaLayoutGuide`。使って楽したいですよね。でもstoryboardに要件があるんです。
`DeployTarget >= 9.0`なんです。
ビジネス要件で9.0未満をサポートするパターンが苦境に立たされてます。Appleの圧力というやつです。

また、storyboardを使用する場合だとiPhone8ではフルスクリーン、iPhoneXではsafeAreaの範囲内、といった切り替えは手軽にできそうにないですね。その場合も、下記のようなコードベースで制約を貼り分けることで解決できるんじゃないかと思います。

# 前提

- コードベースでAutoLayoutを使用する

# 結論

```objc
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad]

    // フルスクリーンで表示するView
    UIView *fullScreenView = [UIView new];
    view.translatesAutoresizingMaskIntoConstraints = NO;
    view.backgroundColor = [UIColor greenColor];
    [self.view addSubView: fullScreenView];

    id relateBase = self.view;
    // iPhoneXだけsafeAreaLayoutGuideを使用したい
    // iPhoneXはiOS11以上が確定のはずなので、iOSバージョンチェックはいささか冗長
    NSArray<NSString*> *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
    if ([versionCompatibility[0] intValue] >= 11 ) {
        // ゴリ押しiPhoneX対応
        CGSize  screenSize = [UIScreen mainScreen].bounds.size;
        CGFloat shortDistance = (screenSize.width < screenSize.height)? screenSize.width:  screenSize.height;
        CGFloat longDistance  = (screenSize.width < screenSize.height)? screenSize.height: screenSize.width;
        CGSize portraitScreenSize = CGSizeMake(shortDistance, longDistance);
        CGSize iphoneXscreenSize  = CGSizeMake(375.0, 812.0);
        if (CGSizeEqualToSize(portraitScreenSize, iphoneXscreenSize)) {
            relateBase = view.safeAreaLayoutGuide;
        }
    }

    [target setTranslatesAutoresizingMaskIntoConstraints:NO];
    [view addConstraints:@[
        [NSLayoutConstraint constraintWithItem:fullScreenView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:relateBase attribute:NSLayoutAttributeTop multiplier:1 constant:0],
        [NSLayoutConstraint constraintWithItem:fullScreenView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:relateBase attribute:NSLayoutAttributeBottom multiplier:1 constant:0],
        [NSLayoutConstraint constraintWithItem:relateBase attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:fullScreenView attribute:NSLayoutAttributeTrailing multiplier:1 constant:0],
        [NSLayoutConstraint constraintWithItem:relateBase attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:fullScreenView attribute:NSLayoutAttributeLeading multiplier:1 constant:0],
    ]];    
}
@end
```

main Screenのサイズでゴリ押し。

hardware stringを基準にするとiOSシミュレーター時点で確認できないので手法から除外。
create_tableのブロックだけでDBにユニークインデックスを貼れないのか？

## 疑問
- create_tableのブロックだけでDBにユニークインデックスを貼れないの？
  - [RailsDoc](http://railsdoc.com/migration)では触れられてない…
  - こういう[SOの記事](https://stackoverflow.com/questions/21635825/how-to-create-a-new-table-with-a-unique-index-in-an-active-record-rails-4-migr
)とかあるけど本当にできないの？

## 結論
add_index と同じオプションが使える
-> `t.string :column_name, index: { unique: true }` と書ける

## Railsのコード読んでみた
- 環境：Rails 5.1.1

### create_table のブロック内部

https://github.com/rails/rails/blob/v5.1.1/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb

- 前段
  - ブロック引数は `class TableDefinition` のインスタンス。
  - `t.string` `t.integer` などは `t.column(name, type, options = {})` のシンタックスシュガー
  - (`module ColumnMethods`あたりを参照)

- create_table のカラム追加メソッド

  ```ruby
  def column(name, type, options = {})
    ...
    index_options = options.delete(:index)
    index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
    ...
  end
  ```

- indexの定義

```ruby
  # Adds index options to the indexes hash, keyed by column name 
  # This is primarily used to track indexes that need to be created after the table 
  # 
  #   index(:account_id, name: 'index_projects_on_account_id') 
  def index(column_name, options = {})
      indexes << [column_name, options]
  end
  ```
  
### create_table メソッド

https://github.com/rails/rails/blob/v5.1.1/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

create_tableじゃない方法で作成する時と同じ`add_index`を呼んでいる

```ruby
def create_table(table_name, comment: nil, **options)
  ...
  td.indexes.each do |column_name, index_options|
    add_index(table_name, column_name, index_options)
  end
end
```

### つまり
`add_index`で指定できるものは`create_table`内でも使える！
[swift] Cライブラリーのモジュール化


clangのmodule.modulemapファイルを用意することで、
cのライブラリーをモジュールとしてswiftソースファイルにimportすることができる。

# ディレクトリ構造
以下のようにlibtestライブラリをモジュール化してmain.swiftファイルにimportする方法を説明します。

```
Sample/-*-main.swift
        |
        *-libtest/-*-lib/-*-libtest.a
                   |
                   *-inlucdes/-*-test.h
                               |
                               *-foo.h
                               |
                               *-bar.h

```

```test.h
#include "foo.h"
#include "bar.h"
```

```foo.h
int foo();
```

```bar.h
int bar();
```


# module.modulemapファイルを作成する
libtestディレクトリ配下に以下を作成する

```module.modulemap
module libtest /*モジュール名*/ {
    header "include/test.h"
    export *
}
```


# 使用例

```main.swift
import libtest

var fooNum: Int32 = libtest.foo()
var barNum: Int32 = bar() //モジュールを指定する必要はなし
```

main.swiftファイルは以下のようにしてビルドします。

```
$ swiftc -I ./libtest -L ./libtest/lib -ltest main.swift -o a.out
$ ./a.out #実行
```

**NOTE:**
* -I = モジュールの検索パスを指定
* -L = ライブラリーの検索パスを指定
* -ltest = libtest.aライブラリをリンクするように指定


# 関連
* Clang Modulesについて
https://qiita.com/ysn551/items/6f783af2b65c2c4d4631

* [swift] swiftcコマンド まとめ 
https://qiita.com/ysn551/items/cf449cb28adafaed956b
threejsで座標変換行列の使い方を理解する

threejsのshaderMaterialで、自分で用意した行列を使い、MVP変換をやってみる。

# ３つの変換行列

|matrix |説明
|:-----------|:------------
|modelMatrix | ワールド変換行列とも呼ばれる。モデルの位置、モデルの回転、モデルの拡大縮小の情報を持たせる。
|viewMatrix | カメラを定義するためのもの。カメラの位置、カメラの注視点、カメラの上方向から作られる。
|projectionMatrix|スクリーンの縦横比や、クリッピング領域の定義、遠近法のような効果を加える。fov,aspect,near,farから作られる。

# 座標系
上記の各行列をpositionに掛け算することによって以下のように座標系が変換されていく。

|座標系 |説明
|:-----------|:------------
| オブジェクト座標系 |　モデルが原点の座標系 
| ワールド座標系 | 　ワールドな原点の座標系。オブジェクト座標にmodelMatrixを掛けると得られる。
| ビュー座標系 |  カメラを原点とするような座標系。ワールド座標系にviewMatrix( カメラのworldMatrixの逆行列 ) を掛けると得られる。
| クリップ座標系 |  遠近法的な処理が加えられ -1<x,y,z<1となるような座標系

### projectionMatrixによってクリップ座標系に変換される図

赤はカメラから見える領域（四角すいだい）

![image](http://www.opengl-tutorial.org/assets/images/tuto-3-matrix/nondeforme.png)

projectionMatrixをかけると、こうなる↓

![image](http://www.opengl-tutorial.org/assets/images/tuto-3-matrix/homogeneous.png)

引用元：
http://www.opengl-tutorial.org/jp/beginners-tutorials/tutorial-3-matrices/

# threejsで各行列を作り、計算する

いちから作ろうと思ったんですが、難しかったため、threejsが用意してくれてるものを流用。。

### threejsでの、各行列の取得の仕方
```js
var obj = new THREE.Object3D();
var cam = new THREE.PerspectiveCamera(fov,aspect,near,far);

//modelMatrix
var modelMat = obj.worldMatrix;

//カメラのモデルマトリックスの逆行列がviewMatrix
var viewMatrix = cam.worldMatrixInverse;

//カメラにすでに用意されているので、これを使う
var projectionMatrix = cam.projectionMatrix;

```

本当は[matrix.lookAtとかmatrix.perspectiveとか](https://wgld.org/d/webgl/w013.html)をつかってやりたかったが、また次回。


### あとはshaderMaterialへuniformを渡せばよい。

```js:uniform
	uniforms: {
	    modelMat: { type: 'm4', 	value: modelMat },
		viewMat: { type: 'm4', 		value: viewMatrix },
		projMat: { type: 'm4', 		value: projectionMatrix }
    }
```

```glsl:vertexShader
		uniform mat4 modelMat;
		uniform mat4 viewMat;
		uniform mat4 projMat;
		
		void main()
		{
			gl_Position = projMat * viewMat * modelMat * vec4( position, 1.0 );			
		}
```

# normalMatrixも計算してみよう

normalMatrixとはviewからみたnormalを得るためのもの。そんで、ライティングベクトルとのdotを取り、マテリアルへの影響を計算する。

normalMatrixはmodelViewMatrixの逆行列の転置行列らしい。なぜmodelViewMatrixではだめか、は[この記事](http://esprog.hatenablog.com/entry/2016/04/14/184423)が参考になる。

```
mat4 modelViewMat = viewMat * modelMat;
mat4 normalMat = transpose(inverse(modelViewMat));
```
transpose 転置行列
inverse 逆行列
https://github.com/glslify/glsl-transpose/blob/master/index.glsl
https://github.com/glslify/glsl-inverse/blob/master/index.glsl

ここではgpuでやっちゃったが、ふつうはcpuで計算しておくとよいらしい。





# 参考にしたページ

http://www.opengl-tutorial.org/jp/beginners-tutorials/tutorial-3-matrices/
https://wgld.org/d/webgl/w013.html
http://esprog.hatenablog.com/entry/2016/04/14/184423
Promise で排他制御を行う


Promise での非同期処理時、排他制御を怠ったばっかりにバグを出してしまった、そんな経験ありませんか。私はあります。

スレッドを使う場合、Mutex や synchronized 等々、大抵排他制御を行うライブラリや構文などがセットでついてくるのだけど、Promise/A+ には無いので自前で制御する必要がある。

なので、Promise で排他制御が出来るライブラリを npm から調べ、めぼしい物二つをピックアップしてみた。

## async-lock 

- https://www.npmjs.com/package/async-lock

- 一番メジャーっぽいライブラリ。ダウンロード数も多い。
- ロック取得時、key を指定する
  - redis の key の set のように、key ごとに排他制御したい場合に便利
- タイムアウトのサポート
- 待ち受けタスク数の上限のサポート

インターフェイスが、acquire の引数に排他処理の関数を書くタイプ。

```js
const lock = new AsyncLock();
await lock.acquire(key, () => {
  // 排他処理
});
```

## await-semaphore

- https://www.npmjs.com/package/await-semaphore

- セマフォを実現するライブラリ
  - [wikipediaセマフォの項](https://ja.wikipedia.org/wiki/%E3%82%BB%E3%83%9E%E3%83%95%E3%82%A9)ちゃんと書いてあるなぁ
- シンプルな実装
- TypeScript 対応
- `new Semaphore(n)` でアクセス出来る数を指定できることはもちろん、バイナリセマフォである`new Mutex()`なインターフェイスがあったりする

acquire と use という、Promise がロック解除用の関数を返すインターフェイスと、引数に排他処理で実行したい関数を書くタイプ二つがある。

```js
const mutex = new Mutex();
const release = await mutex.acquire();
try {
  // 排他処理
} finally {
  // release を呼び出さないとデットロックになる
  release();
}
```

```js
mutex.use(() => {
  // 排他処理
});
```

## どちらを使うか

用途に合わせて使えば良いのだけど、単にシンプルな Mutex での排他制御がしたいだけなら、await-semaphoreが、色々やりたかったら async-lock が良いと思う。
cybozu soap APIを叩いて、自分の本日のスケジュールを取得するサンプル(PHP)

```php:sample.php

$username='{cybozuのユーザー名}';
$password='{cybozuのパスワード}';

$today = date('Y-m-d');
$todayFrom = $today.'T00:00:00Z';
$todayTo   = $today.'T23:59:59Z';

// 送信先
$url='https://{サブドメイン名}.cybozu.com/g/cbpapi/schedule/api.csp';

// ヘッダ
$headers = [
    'Content-Type: application/soap+xml; charset=UTF-8',
    'action="ScheduleGetEvents"',
];

// リクエスト内容
$postdata =<<<EOF
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Header>
    <Action>ScheduleGetEvents</Action>
    <Security>
      <UsernameToken>
        <Username>{$username}</Username>
        <Password>{$password}</Password>
      </UsernameToken>
    </Security>
    <Timestamp>
      <Created>2013-06-01T00:00:00Z</Created>
      <Expires>2037-12-31T00:00:00Z</Expires>
    </Timestamp>
  </soap:Header>
  <soap:Body>
    <ScheduleGetEvents>
      <parameters start="{$todayFrom}" end="{$todayTo}">
      </parameters>
    </ScheduleGetEvents>
  </soap:Body>
</soap:Envelope>
EOF;


$curl = curl_init( $url );
curl_setopt( $curl, CURLOPT_POST, TRUE );
curl_setopt( $curl, CURLOPT_POSTFIELDS, $postdata);
curl_setopt( $curl, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true); // curl_execの結果を文字列で返す
$contents = curl_exec( $curl );
curl_close($curl);


$reader = new XMLReader();
$reader->XML($contents);

// 結果出力
// あとはDOM操作なので、適当にお好みの形に整形してください。
$scheduleArr = [];
while($reader->read()) {

    if( $reader->nodeType == XMLReader::ELEMENT &&
            $reader->name == 'schedule_event' &&
            $reader->getAttribute("event_type") != "banner")
    {
        $scheduleItem = [];
        $doc = new DOMDocument('1.0', 'UTF-8');
        $scheduleEvent = simplexml_import_dom($doc->importNode($reader->expand(),true));
        //echo print_r($scheduleEvent,1);
        if( $scheduleEvent['public_type'] == "public" ) {
            $scheduleItem['detail'] = (string)($scheduleEvent['detail']);
        }
        else {
            $scheduleItem['detail'] = "予定あり";
        }
 
        if( $scheduleEvent['event_type'] == "repeat" ) {
            $scheduleItem['start'] = (string)($scheduleEvent->repeat_info->condition['start_time']);
            $scheduleItem['end']   = (string)($scheduleEvent->repeat_info->condition['end_time']);
        }
        else if( $scheduleEvent['event_type'] == "normal" ) {
            $scheduleItem['start'] = strftime( '%T', strtotime( $scheduleEvent->when->datetime['start'] ) );
            $scheduleItem['end']   = strftime( '%T', strtotime( $scheduleEvent->when->datetime['end'] ) );
        }
        $scheduleArr[] = $scheduleItem;
    }
}
$reader->close();

/**
scheduleArrが
[
    [
        "detail" => "予定タイトル",
        "start"  => "開始時間",
        "end"  => "終了時間",
    ]
]
みたいな形になります。
*/
```
Pythonで2次元配列の重複行を一発で削除する

## したいこと
重複する要素を持つ2次元配列から、ダブりを削除したい。
つまり、これを、、、、

```
[[0, 0],
[1, 1],
[1, 0],
[1, 1],
[0, 1],
[0, 0]]
```


こうしたい！

```
[[0, 1],
[1, 0],
[0, 0],
[1, 1]]
```

## やりかた
1. 各要素をtupleに変換
2. setで重複を削除
3. listに戻す

※ポイントはtupleに変換するとこ。list型だとsetが使えない。


```Python
>>> arr = [[0,0], [1,1], [1,0], [1,1], [0,1], [0,0]]
>>> arr = list(map(list, set(map(tuple, arr))))
>>> arr
[[0, 1], [1, 0], [0, 0], [1, 1]]
```

なにか、ほかにいい方法あれば教えてください〜

## お世話になったページ
[集合型で2次元リスト中の重複した行を削除する](http://amalog.net/post/extract-unique-data/)
PHPからchatwork API v2を叩くサンプル

```php:sample.php

$chatToken = '{chatwork apiのトークン}';
$chatGroupId = '{投稿したいグループのID}';
$message = "This is test.\nMy name is test.";

$headers = [
    'X-ChatWorkToken: '.$chatToken
];

$option = [
    'body' => $message
];

$ch = curl_init( 'https://api.chatwork.com/v2/rooms/'.$chatGroupId.'/messages' );
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($option));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
$response = curl_exec($ch);
curl_close($ch);
```

投稿したいチャットグループには、そのトークンを保持しているユーザーが入っていないと投稿できませんので、注意です。

The user whose token was issued by chatwork should be included in the chatgroup of the chatGroupId.
If not, this program can't post a message to the chatgroup.
CognosでCQMからDQMに切り替えた時、どこを検証すればよいか

Cognosを使用していて、現行Compatible Query Mode (CQM)で動いているCognosのプロジェクトをDynamic Qeury Mode (DQM)に切り替えた際、なにがどう変わってどこに影響があるのか？が綺麗にまとまった資料がなかったのでまとめてみました。

CQM→DQMでの変更点は大きくサマリーすると下記5点になります。

1. レポート作成エンジン
2. データベース接続
3. キャッシュの使用
4. 監査ログ
5. ガバナーの設定

それぞれについて影響範囲と検証方法を見て行きたいと思います。

---
## 1. レポート作成エンジン
Queryモードを変更しているので変わって当たり前の部分ではありますがCQM→DQMの一番大きな変更点となります。

**変更点**

- CQM：32bitのBIBusTKServerMainプロセス
- DQM：64bitのjavaプロセス

**影響範囲ごとの考慮点**
**1-1. レポートサービスの使用可能なメモリー容量**
CQMのBIBUSプロセスは32bitプロセスなのでメモリー容量に1プロセスあたり2GBまでの制限がありました。
DQMでは64bitプロセスなので2GBの制限が無くなり、Query Serviceに割り当てられたJVMのヒープサイズの上限の中で利用可能になっています。そのため、CQMでは扱えなったや大量データを使用するレポートや、グラフやオブジェクトを多くレンダリングするようなレポートでも実行可能となっています。
ただし、メモリーの使われ方が変わるのでOut of Memory (OOM)発生時の影響範囲に注意が必要となります。

**1-2. レポートサービスOOM時の影響範囲**

- CQM：OOMを発生させたBIBUSプロセスで作成中のレポートにのみエラーが返っていました。他のBIBUSプロセスを使用しているレポートや新規にリクエストされたレポートは実行可能です。
このBIBUSプロセスはレポートリクエスト時に起動されるプロセスのため自然復旧が可能でした
- DQM：Query Serviceが使用するJVMでOOMが発生するため、他のレポートおよび新規リクエストのレポートも実行不可になります。復旧にはQuery Serviceの再起動が必要ですが、Cognosサービスを再起動する運用を検討するほうが望ましいです。


(検証方法/解決方法)
まずは、OOMが発生しないようなチューニングを検討します。Queryサービス用のJVM ヒープ・サイズ制限を引き上げますが、Cognosサービスに割り当てられるメモリーの上限を超えないように設定する必要があります。
また、Cognosサービスの再起動の担当者や実施方法などOOM発生時の運用方法についても検討しておくことが望ましいです。

**1-3. 発行されるSQL文**
集計や結合を頻繁に行う複雑なモデルやレポートではクエリーエンジンの解釈の違いにより生成されるSQLが変化することがあります。その結果、レポート実行時の値に影響を与えることがあります。

(検証方法/解決方法)
CQMで実行したレポートとDQMで実行したレポートで表示される値を見比べて検証する必要があります。

**1-4. 検証の厳格化**
DQMではCQMに比べて検証時の確認が厳格になります。CQMではエラーがなかったレポート定義でもDQMでレポート検証を実施するとエラーになる場合もあります。また、FMモデルにおいても同様になります。

(検証方法/解決方法)
エラーが発生した場合はメッセージに従い、レポート定義やFMモデルの修正が必要になります。

**1-5. レポートの見栄え**
レポート作成エンジンの違いによりレポートのレイアウトが崩れる発生する可能性があります。
レポートレイアウトを細かく指定しているレポートでは注意が必要です。

(検証方法/解決方法)
CQMで実行したレポートとDQMで実行したレポートでレイアウトを見比べて検証する必要があります。

※1-3, 1-5の検証時、目視による検証のほかにLCMを使った検証方法も検討するのもいいかもしれません。
LCM: (Cognos LifeCycle Manager) : Cognosのバージョンアップ時のレポートの出力結果を比較して同じ結果が生成されるかを検証する機能を提供している。環境さえあればCQM→DQMの前後比較にも使用可能です。

## 2. データベース接続
**変更点**
- CQM：NativeClient接続 または ODBC接続
- DMQ：JDBC接続

**影響範囲ごとの考慮点**
**2-1. 基盤構成**
\<Cognos Install Directory>配下にJDBCドライバーの配置が必要になる
　　Cognos Analyticsの場合：\<Analytics>/drivers
　　Cognos BIの場合：\<c10_64>/webapps/p2pd/WEB-INF/lib および \<C10_64>/v5dataserver

**2-2. データソース接続定義**
JDBCでのデータソース接続定義が無い場合は作成が必要になる

## 3. キャッシュの使用
**変更点**
DQMはキャッシュの再利用が可能になる

**考慮点**
キャッシュの再利用によりパフォーマンスの向上が見込まれる一方で、データ更新が頻繁な環境ではキャッシュの利用をOFFにするなどを検討する必要がある

## 4. 監査ログ

**変更点**
DQMではクエリーステートメントが監査ログに記録されない

**考慮点**
Audit DBを構築し、監査ログに出力されるクエリーステートメントを監査する運用を実施している場合、監査の運用方式の見直しが必要になる

## 5. ガバナーの設定
**変更点**
DQMではFramework Managerのガバナーの設定が適用されないものがある

**考慮点**
取得する行の最大数の制限などはQuery ServiceにTupleの上限数を設定するなど個別に対応が必要になる


---
レポート担当者や基盤担当者、運用担当などいろんな立場の視点からのお話をごちゃ混ぜに記載してしまいましたが、以上、CQMからDQMに切り替えた時の変更点と検証のポイントでした。




==============================================
## 個別事象 紹介
(2018.2.5 追記)
CQMからDQMに変更した際に遭遇した個別事象についてもまとめていますのでご紹介します。

[CognosでCQMからDQMに変更した際、複数選択ができなくなった場合の対処法](https://qiita.com/hayatoshi/items/8f8bc2441481936bdfb0)
ios11のsafariでmodal内のinputのカーソルがずれる

ios11のsafariではmodalの中で表示させるinput要素でカーソルがずれるバグがあるようです。

参考URLのように親となる要素に、「position: fixed」のスタイルをあてると治るようです。

参考URL

https://stackoverflow.com/questions/46339063/ios-11-safari-bootstrap-modal-text-area-outside-of-cursor

https://hackernoon.com/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8

# 10.26追記

ios 11.0.3(15A432)で再度確認したところ
カーソルを表示したときの大幅なずれは解消した模様
スクロールしたときにカーソルの位置がおかしくなる状態は以前あります。
[Objective-C]NSObjectとは何か

Objective-Cを勉強していますが、さっぱり分かりません。
学習のためまとめてみたいと思います。

#NSObjectとはなにか
##ランタイムシステム(Runtime System)
オブジェクトの動的な振る舞いを助けるシステムです。
単にランタイムと呼ぶ場合もあります。
これはObjective-C用のオペレーティングシステムのようなもので、
オブジェクトの生成や、メモリ領域の管理、メッセージに対応するメソッドの探索などを行います。

##NSObjectを通して利用する
ランタイムシステムの機能は、ルートクラスであるNSObjectから使用できます。
このクラスを継承しているすべてのクラスは、ランタイムシステムを利用できます。

##cocoaとはなにか
>CocoaはObjective-Cをコア言語とするオブジェクト指向フレームワークである。

wikipediaには、このようにありますね。
どうやら私はCocoaというフレームワークを利用するために、Objetive-Cという言語を利用しているようです。
cocoaはOPENSTEPを元に発展しているそうですが、OPENSTEPでNSObjectというクラスを使うようになったそうです。

##isa
NSObjectには、isaというClass型のインスタンス変数があるそうです。
すべてのインスタンスオブジェクトは、isaによって自分が属しているクラスオブジェクトを参照することができます。
isaの値をサブクラスから変更するのはNG。

#NSObjectのメソッド
詳細は省きますが、以上のような仕組みからNSObjectによってメソッドが提供されているんですね。

#参考文献
詳解Objective-C 2.0
[Coco - Wikipedia](https://ja.wikipedia.org/wiki/Cocoa)
DigitalOceanにDrone 0.8 をインストールする

[以前0.4で同じことをしました](https://qiita.com/naokazuterada/items/d040ad27e77b587ef49f)が、それのアップデートです。Droneのバージョンを最新の0.8.0にします。[docker-compose](https://docs.docker.com/compose/)を使って起動できるようになったようです。今回も[ドキュメント](http://readme.drone.io/admin/installation-guide/)に沿って進めました。ついでに[こちら](http://docs.drone.io/configure-lets-encrypt/)を参考に、SSL化もしました。

- DigitalOceanの One Click Appsで`Docker 17.05.0-ce on 16.04`を選択し、Dropletを作成
- 作成したサーバにsshでログインし以下の操作を行う

## docker-compose.yml の作成

```sh
vi /USERNAME/docker-compose.yml
```

- [GitHubの Settings > Developer settings > OAuth Apps](https://github.com/settings/developers) から、Drone用のAppを作成
- `callback url`は`https://DRONE_HOST/authorize`にして、発行されたclinet_idとsecretを、それぞれ下記の`DRONE_GITHUB_CLIENT`と`DRONE_GITHUB_SECRET`に設定
- `DRONE_SECRET`は、[ドキュメントによると](http://readme.drone.io/0.5/install/server/)任意で設定すれば良いようなので、random password generatorで作成して記入
- `DRONE_HOST`も環境に合わせて設定

> Create a secret passcode that will be used to authenticate your builds agents. We recommend using a [random password generator](http://correcthorsebatterystaple.net/) to create this secret passcode.

```yml
version: '2'

services:
  drone-server:
    image: drone/drone:0.8.0
    ports:
      - 443:443
      - 80:8000
    volumes:
      - ./drone:/var/lib/drone/
    restart: always
    environment:
      - DRONE_HOST=https://DRONE_HOST
      - DRONE_OPEN=true
      - DRONE_GITHUB=true
      - DRONE_GITHUB_CLIENT=DRONE_GITHUB_CLIENT
      - DRONE_GITHUB_SECRET=DRONE_GITHUB_SECRET
      - DRONE_SECRET=DRONE_SECRET
      - DRONE_LETS_ENCRYPT=true

  drone-agent:
    image: drone/drone:0.8.0
    command: agent
    restart: always
    depends_on: [ drone-server ]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_SERVER=ws://drone-server:8000/ws/broker
      - DRONE_SECRET=DRONE_SECRET
```

## 起動

```sh
docker-compose up -d
```

以上です。
NefryBT向けAmbientライブラリ紹介

# Nefry Ambientライブラリ

Ambientと呼ばれる、NefryのようなIoTデバイスから取得したデータを簡単にグラフ化できるWebサービスとなります。


紹介記事：https://dotstud.io/blog/nefry-data-show-graphically/

##どんなことができる？
センサーデータの蓄積、手軽なグラフ化ができます。

##関数情報

### begin

Ambientにつなぐために必要な初期化処理をします。**起動時に一度だけ呼び出してください。**
引数が違うものが2つありますがどちらか一つ呼び出してください。

####NefryのWebConfigで設定する値を設定する場合
ここの引数で設定した値がWebConfigで設定できる欄の値になります。

||||
|:---:|:---:|:---:|
|引数1|int|10-19の間で入力してください。デフォルトは10になります。チャンネルIDを入力する欄を選択します。|
|引数2|int|0-9の間で入力してください。デフォルトは0になります。WriteKeyを入力する欄を選択します。|
|返り値|bool|true:初期化処理成功　fales:初期化処理失敗|
|具体例||nefryAmbient.begin();|

####直接プログラム内で設定する値を設定する場合
プログラム内で直接値を設定する場合はこちらで設定することができます。

||||
|:---:|:---:|:---:|
|引数1|unsigned int|チャンネルIDを入力します。|
|引数2|const char*|WriteKeyを入力します。||
|返り値|bool|true:初期化処理成功　false:初期化処理失敗|
|具体例||nefryAmbient.begin(10000,"writeKey");|

### set

Ambientに送るデータをセットします。複数の型に対応しています。

||||
|:---:|:---:|:---:|
|引数1|int|Ambientで表示されるフィールドを選択します。1-12の間で選択してください。|
|引数2|int,double,const char*|Ambientで表示されるデータを入れます。複数の型に対応しています|
|返り値|bool|true:処理成功　false:引数かデータに問題があります|
|具体例||nefryAmbient.set(1,1000);|

### send

Ambientにデータを送信します。

||||
|:---:|:---:|:---:|
|引数|void|なし|
|返り値|bool|true:処理成功　false:引数かデータに問題があります|
|具体例||nefryAmbient.send();|

### clear

set関数で入れた値を削除します。

||||
|:---:|:---:|:---:|
|引数|int|Ambientで表示されるフィールドを選択します。1-12の間で選択してください。|
|返り値|bool|true:処理成功　false:引数かデータに問題があります|
|具体例||nefryAmbient.clear(1);|

###その他の関数について
そのほかにもデータをまとめて送ることのできる関数(bulk_send)やデータを削除する関数(delete_data)などがあります。使いかたはAmbient公式サイトに乗っているライブラリと一緒ですのでそちらを参照してください。
https://ambidata.io/refs/arduino/

##サンプルプログラム
A2ピンの入力値をAmbientにアップロードします。

```c++:NefryAmbient
#include <NefryAmbient.h>

NefryAmbient nefryAmbient;

void setup() {
  nefryAmbient.begin();//ambientを使えるように初期設定をします。
  Nefry.setProgramName("AmbientSimpleAnalog");//プログラム名を指定します。
}

void loop() {
  int analog;
  analog = analogRead(A2);//A2ピンの状態を取得します。
  Nefry.print("Analog:");Nefry.println(analog);//アナログの値を表示します。
  nefryAmbient.set(1, analog); //field,dataの順にセットします。
  nefryAmbient.send();//ambientにデータを送信します。
  Nefry.ndelay(1000);//1秒待つ
}
```