OmniAICreator/Qiita-1.07M huggingface dataset:
温度センサから値を取得して値を確認する画面をサーバーレスで構築する

オフィスIoTで温度センサを取得して、それをモニタリングしようということになりました。
ただEC2を建てると高いんでサーバーレスで何とかできないかと考えました。
今回は手順というよりどんな構成だったらできるかなーと考えた過程です。

# 対象読者
・AWSちょっとかじったことある人
・サーバーレスでWebサイトを構築してみたい人
ちなみに私のスペックですが
・AWSはじめて半年強
・プログラムちょっとしか書けない
・Webサイト作ったことほとんどない
PGというより上流SE的なことやってたんで、今の会社来るまでは設計しかできないレベルでしたのでそれぐらいのレベルです。

#画面のイメージ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/743e2a79-a50c-edc3-be5a-17c0b1a5c164.png)

オフィスの至るところにセンサーを置いて、現在の温度であったり時間を指定することでその時刻の温度が見れたらなと考えております。

#アーキテクトの検討
今回考えなければならない点は以下の2点です。
・温度センサの値をどこに格納するか
・静的Webサイトから温度センサをどうやって取得して表示させるか

##温度センサの値をどこに格納するか
AWSのストレージサービスは主に以下のものがあります。
・RDB(RDSなど)
・NoSQL(DynamoDBなど)
・DWH(Redshiftなど)
・ファイルストレージ(S3など)

要件として、
・センサーの値が温度なのでそんなに頻繁にデータは取得しない（5分に1回ぐらい）
・センサーの数は20個前後
・データは廃棄せず溜めておく
・静的Webサイトから値が取れる

とりあえず
・RDSは高い（前に痛い目にあいました）、別に値を取ってくるだけなので、便利さはいらない
・Redshiftも高そう（すみません、よくわかってないです）
・S3は静的Webサイトから値をうまく取れると思わない
ということで消去法でDynamoDBになりました。RDS使ってたらオフィスIoTレベルの簡単なシステムならDynamo使ってねとチクリと言われたのも決め手になったと思います。

##考えた構成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/fdc843b8-78c9-61bd-b28e-3df9e1ff6a37.png)

AWS IoTから直接Dynamoに入れてもよいですが、センサーデータがバイナリなので、Kinesis FirehouseでLambdaを呼び出して、データを整形してからDynamoに入れます。

##静的Webサイトから温度センサをどうやって取得して表示させるか
調べていたら静的Webサイトと言いつつも、LambdaをAPI Gateway経由で呼び出せるらしい。
そこで以下の構成にしました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/ade202fe-bd46-2693-84dd-dcf2bb2d1b96.png)

## まとめ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/a4446b91-8250-8766-44fb-deac161361ef.png)

よっしゃこれで行けんじゃねと思って、先輩に意見をもらいに行きました。

…

### **Dynamo高くない？？**

私「先輩、オフィスIoTのアーキテクト考えたんで見てもらってよいですか？」
先輩「おお、ええで。」
私「こうでこうで、どうでしょうか？」
先輩「んーまぁこれでもいいけど、Dynamo高くない？S3でいいんじゃね？」
私「え、でもS3にするとLambdaで取得する処理が煩雑になりそうじゃないですか？」
先輩「Athena使ったらいいと思うよ。知らんけど」

…とりあえずAthena調べました。

##Athenaとは
*Amazon Athena はインタラクティブなクエリサービスで、Amazon S3 内のデータを標準 SQL を使用して簡単に分析できるようになります。Athena はサーバーが不要です。そのため、セットアップや管理のためのインフラストラクチャがなく、即座にデータ分析を開始できます。データを Athena にロードする必要もありません。S3 に保存されているデータと直接連携します。*

とりあえず、S3をDBとしてSQLが書けるサーバーレスのサービスということだけ理解しました。

##新しく考えた構成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202761/92a07215-f65c-19e0-83f2-ff3e9ff1b18e.png)
先輩はAPI GatewayからAthena呼べるかもしれないと言っていましたが、調べてみたら無理そうでしたので、Lambda経由で取得するようにしています。

##アーキテクトを考慮する点
上のやり取りだけを見るとDynamoの案が悪いように見えてしまいますが、そうではありません。
・データのサイズ
・Webサイトへのアクセス頻度（10分に1人なのか、1秒に10人なのか）
・Webサイトのユーザの滞在時間
などいろいろな要素を検討して、DynamoよりもAthenaの方が良いのではないかと判断しています。
今回オフィスIoTでそれほどアクセス頻度も高くないので、クエリに対する料金が課金される体系のAthenaの方がよく
データサイズは時間が経てばまぁまぁなので、DynamoよりはS3に溜めた方が良いのではないかという上でアドバイスしていただきました。
実際には上記のことを仮でもよいので、設定して考えなければならないとのご指摘も受けました。

##まとめ
そうはいってもまだ机上の話になるので、実際にシステム構築していろんな障害があるのだろうなと思いつつ今回終わり。
次回は実際作った過程での苦労話なんかができたらいいなと思っております（まだまだ先の話ですが）。
個人的にはAthena使ったときのレスポンスとか大丈夫なんだろうかと思っています。

##参考
[BLEゲートウェイとSORACOMとAWSを使ってデータ収集基盤を作ってみた](http://blog.serverworks.co.jp/tech/2017/04/13/monoconnect_soracom_iot/)
[AWS DynamoDB の料金がわかりにくいので、最小テーブルの月額を計算してみた](https://qiita.com/YU81/items/e1e336990ed8cfb938d9)
[Amazon API GatewayとLambdaを利用したサーバレスなWebアプリを作ってみた](https://www.cresco.co.jp/blog/entry/445/)
[Amazon AthenaをAWS Lambdaから操作できるようにしてみた](https://qiita.com/kojiisd/items/3466cfca55b8894b5ca0)
Twitterで自分宛てに送ったDMをPocketに追加する

DM取得のAPIエンドポイント変更に伴いコードを変更した(2019/02/22)

# 概要
TwitterでDirectMessageを用いて自分にShareすると、後から探すことが難しい。本記事ではPocketの検索及びタグ機能を用いてこれを改善したプログラムを紹介する。

# 準備
本記事で説明するコードは事前に以下の準備が必要である。本記事での説明は省略する。

* GoogleSpreadSheetIdの取得
    * https://docs.google.com/spreadsheets/d/[この部分]/edit#gid=0
* [Pocketの認証](http://realtor-readyabooks.hatenablog.com/entry/20140329/1396092391)
* [Twitterの認証](https://kijtra.com/article/twitter-api-for-google-apps-script-without-oauthconfig/)

# 実装
Pocket認証及びpocket_add関数は[Lhankor_Mhy様](http://realtor-readyabooks.hatenablog.com/entry/20140329/1396092391)、Twitter認証は[kijtra様](https://gist.github.com/kijtra/f4cdd8775277372d42f7)のプログラムを流用している。
本プログラム単体では動作しない。

``` javascript:code.gs
function main() {
  var spreadsheet = SpreadsheetApp.openById('spreadsheetIdをここに記入');
  var sheet = spreadsheet.getSheets()[0];
  var res = Twitter.getDM();
  getOwnDM(sheet,res);
  delete_duplicate(sheet);
  post_pocket(sheet);
}

function post_pocket(sheet){
  var lastrow = sheet.getLastRow();
  var array = sheet.getSheetValues(1, 2, lastrow, 4);
  var post={};
  for(var i in array){
    if(array[i][2]=="" && (array[i][0]+"")!="text"){
      // このスクリプトで追加されるアイテムの共通タグ
      var tags = ["DM"];
      if((array[i][1]+'').length>0){
        var tag=(array[i][1]+"").split(/\s+/);
        Array.prototype.push.apply(tags, tag);
      }
      post.url = array[i][0];
      post.tags = tags;
      pocket_add(post);
    }
  }
  sheet.getRange(1,4,lastrow,1).setValue("Done");
}

//重複削除
function delete_duplicate(sheet) {
  var arr_data=sheet.getDataRange().getValues();
  var values = [];
  var no_overlapped = arr_data.filter(function (e){
    if (values.indexOf(e[0]) === -1) {
      values.push(e[0]);
      return e;
    }
  });
  sheet.clearContents();
  sheet.getRange(1,1,no_overlapped.length,no_overlapped[0].length).setValues(no_overlapped);
}  

// URLかどうかの判定,タグとURLの分離
function checkType(text){
   url=text.match(/(https?)(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)/);
  if(url!=null){
    url=url[0];
    text=text.replace(url,"");
    return [url,text];
   }else{
     return ["text",""];
   }
}

function getOwnDM (sheet,jsonData){
  var response = [];
  for (i in jsonData){
    if(jsonData[i]["message_create"]["sender_id"]==jsonData[i]["message_create"]["target"]["recipient_id"]){
      var res=[jsonData[i]["message_create"]["message_data"]["text"]];
      Array.prototype.push.apply(res, checkType(res[0]));
      response.push(res);
    }
  }
  var rows = response.length;
  var cols = response[0].length;
  var lastrow = sheet.getLastRow();
  sheet.getRange(lastrow+1,1,rows,cols).setValues(response);
}

Twitter.getDM = function () {
  var path = "direct_messages";
  var data = {"count":200,"skip_status":true,"include_entities":false};
  var res = this.api(path, data);
  return res;
}

```
Project Euler 22「名前のスコア」

## Problem 22 「名前のスコア」
5000個以上の名前が書かれている46Kのテキストファイル [filenames.txt](http://odz.sakura.ne.jp/projecteuler/index.php?plugin=attach&refer=Problem%2022&openfile=names.txt) を用いる. まずアルファベット順にソートせよ.
のち, 各名前についてアルファベットに値を割り振り, リスト中の出現順の数と掛け合わせることで, 名前のスコアを計算する.
たとえば, リストがアルファベット順にソートされているとすると, COLINはリストの938番目にある. またCOLINは 3 + 15 + 12 + 9 + 14 = 53 という値を持つ. よってCOLINは 938 × 53 = 49714 というスコアを持つ.
ファイル中の全名前のスコアの合計を求めよ.

```python
def hoge(path):
    ans = 0
    names = []
    with open(path) as f:
        for line in f:
            if line.strip() == '':
                continue
            names += (line.strip().replace('"', '').split(','))
    names.sort()
    score = { chr(i): i-64 for i in range(65, 65+26) }
    for i, name in enumerate(names, start=1):
        ans += sum([ score[n] for n in name ]) * i
    return ans

print hoge('./names.txt')
プログラミングをよく知らない初心者がSublimeText3を使ってみた話

# はじめに
プログラミング初心者です。
以前に「プログラミングをよく知らない初心者が～」シリーズで2個くらい記事書きました。
[シリーズ第1弾](https://qiita.com/minakenty321/items/da213cac83bce9884a67)
[シリーズ第2弾](https://qiita.com/minakenty321/items/08b901b1d9d7fabda565)
初心者でポンコツなので生暖かい目で見守ってください。

# SublimeTextとは？
僕もようわからんですがたぶんテキストエディタです。
サクラエディタとか秀丸とかAtomとかそういう類の奴です(ちがったらごめんなさい)
無料で使えるエディタで、様々なプラグインを入れることができるのが可能です。そして軽い気がします！サクッと起動できます。
(ググってみると「恋に落ちるエディタ」とか出てきますが僕は恋に落ちませんでした。)

# SublimeText3の良さ
↑と被ってしまいますが
・プラグインを入れることで自分好みのカスタムが可能！
・とりあえず軽い
・プロジェクトを保存して複数案件抱えていても対応可能
・範囲選択(？)が可能

これらは他のエディタでも同じかもしれませんね。知らなくてすみません…

# SublimeText3のここがダメ
・なんかセーブした後に通知みたいなのが来てうざい
→最新バージョンの薦めなのかな？そんな通知しなくていいわ。

#おすすめ機能
文字列を選択 → ctrl+D で選択した文字列を選択できるんです。(何を言っているかわからんってか)

まぁこういうのがあるとするじゃないですか
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/213596/379beafd-105c-a5ef-c83b-ad677b7c0fbb.png)

\$aっていう変数名変えたいなってときは、まず$aという文字列を選択
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/213596/5fd58074-b85e-ddbc-5621-9d0983150a3a.png)

ctrl+Dを押す。そうすると選択した文字列と同じものを選択してくれる(押した分だけ選択できます)
![キャプチャ3.PNG](https://qiita-image-store.s3.amazonaws.com/0/213596/095bba1f-6ca3-d08c-e91d-03f3fe9d9a02.png)

選択できたらあとは編集しちゃえばOK
![キャプチャ4.PNG](https://qiita-image-store.s3.amazonaws.com/0/213596/9fa861d5-f5d9-93f4-d514-0d11ef943e24.png)

僕の場合、変数名は後でちゃんとしたものに変えるので、最初は適当にgetaaaとかinsertaaaとかっていう変数名にしちゃうんですよね。めっちゃ適当。
なので後でちゃんとしたものに変えたい場合は使えますね。

## 他に使う機能
ctrl+P : ファイル検索
ctrl+F : 開いているファイル内での検索
ctrl+shift+F : 検索場所を指定して検索
ctrl+G : 行数指定
ALT+shift+2 : 2画面に分割

#まとめ
ざっくりですがSublimeText3について説明してきました。sublime使ったことない方はぜひ触ってみてください。

また、みなさんはどんなエディタをお使いでしょうか？
おすすめの物があればぜひ教えてください。
DFP 広告枠がスクロールで画面外にいったらリロードする

***縦長ページでスクロールしていて広告枠が上下どちらかの画面外に切れたらその広告枠をリロードし、スクロールアップなどで再びその広告枠を見た時は新しい広告を表示***

```html
<script>
	googletag.cmd.push(function() {
		var lastScrollTop = 0;
		var slot = googletag.defineSlot('/XXXXXX/REC_300x250', [[300, 250]], 'dfpad').addService(googletag.pubads());
		googletag.pubads().enableSingleRequest();
		googletag.pubads().disableInitialLoad();
		googletag.enableServices();
		googletag.display('dfpad');
		googletag.pubads().refresh([slot]);
		window.addEventListener("scroll", isScrolledIntoView, false);
		function isScrolledIntoView() {
		    var rect = document.getElementById('dfpad').getBoundingClientRect();
		    var st = window.pageYOffset || document.documentElement.scrollTop;
		    //スクロール方向によって挙動を変える
		    if (st > lastScrollTop){
		    	var elemBottom = rect.bottom;
			    if (elemBottom < 0 && elemBottom > -100) {
			    	//発火の範囲は100px内に
			    	googletag.pubads().refresh([slot]);
			    }
		    } else {
		    	var elemTop = rect.top;
			    if (window.innerHeight < elemTop && elemTop < (window.innerHeight + 100)) {
			    	//発火の範囲は100px内に
			    	googletag.pubads().refresh([slot]);
			    }
		    }
		    lastScrollTop = st;
		}
	});
</script>
<div id="dfpad"></div>
```
Windows 10 でプロダクトキーを知りたいとき

#プロダクトキーが知りたくなったらパワーシェルで

Windows10のＯＳを再インストール時でもプロダクトキーが必要ないようです。
個人的に忘れたころに必要になることがあります。その時用のために手順を書きます。

1. Windowsデスクトップ画面の左下に「ここに入力して検索」というスペースに「power」と打ちます。
2. パワーシェルのアイコンが上のほうに表示されるので、そこで右クリックします。
3. 管理者として実行を選択します。
4. 下の一行をコピーし、powershell上にペーストしてエンターキーを押します。

```powershell:windows
(Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey
```

何も表示されない場合は、OA3xOriginalProductKeyの値になにも与えられていないことを意味します。それを確認するには以下のラインをコピーしてpowershell上で実行させます。

```powershell:

get-wmiobject -query 'select * from softwarelicensingservice'

```
# Excel のオートコレクト(スペルチェック)を抑制する方法

# はじめに

Excel によるバグ管理表は健在です、 綴りの誤りに関する報告をしようにもオートコレクトが機能しており正しい報告が出来ない事が起きます。

例えば `agreement が agreemeet になっている。` とセルに記入すると
エクセルさん `agreement が agreement になっている。` となんだかわけのわからない報告になってしまいます。

他にもアスキー文字のみの文章情報として `(C)DEADBEEF ` と打ち込んだところ `©DEADBEEF` と変換され利用出来ない文字による事故に見舞わてしまします。

# 抑制方法

[MS本家 大文字/小文字の設定、スペルチェック、記号のオートコレクト オプションを選択する](https://support.office.com/ja-jp/article/%E5%A4%A7%E6%96%87%E5%AD%97-%E5%B0%8F%E6%96%87%E5%AD%97%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%80%81%E3%82%B9%E3%83%9A%E3%83%AB%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%80%81%E8%A8%98%E5%8F%B7%E3%81%AE%E3%82%AA%E3%83%BC%E3%83%88%E3%82%B3%E3%83%AC%E3%82%AF%E3%83%88-%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E9%81%B8%E6%8A%9E%E3%81%99%E3%82%8B-e7433b94-f3de-4532-9dc8-b29063a96e1f)

Excel 2010 の例

![オプション.png](https://qiita-image-store.s3.amazonaws.com/0/59404/bf72de0b-8d2f-5575-39e1-83d7b201cc47.png)

ファイル => オプション

![オートコレクト抑制.png](https://qiita-image-store.s3.amazonaws.com/0/59404/ee4db68f-e3e6-c436-3b7c-dbe56708ffb9.png)

文章校正 => オートコレクトのオプション => 入力中に自動修正する チェック無し => Ok => Ok
Nginxでサブドメインを使う場合のRoute53の設定

# 環境
Amazon Linux AMI 2017.09.1 (HVM), SSD Volume Type 
Nginx 1.12.1

# Nginxの設定
Nginxの設定を以下のように設定しました。
上がsample.comののサブドメイン、sub1.sample.comの設定です。

```/etc/nginx/conf.d/virtual.conf
server {
    listen 80;
    server_name sub1.sample.com;
    root /var/www/html/sub1
 
    location / {
      index index.html
    }
}
server {
    listen 80;
    server_name sample.com;
    root /var/www/html/sample
 
    location / {
      index index.html
    }
}
```

# Route53の設定
AWSにログインし、Route53を開きます。
sample.comのHosted zoneを開きます。
Crate Record Setを押して、AレコードをAliasをYesで追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/52386/c4760d1b-cd14-5350-2d9b-b92379eea2cb.png)

# HTMLファイルの配置
以下に、HTMLを区別がつくように配置します。
/var/www/html/sub1
/var/www/html/sample

# 確認
http://sample.com
http://sub1.sample.com

以上となります。
Google クラウドプリントをシェルスクリプトで

Google クラウドプリントをcurlでPDFをアップロードし，任意のプリンタで印刷 or Google ドライブに保存する．

## やりかた
```bash

f=ファイルパス

bn=$(basename $f)

curl -H "Authorization: OAuth アクセストークン" -F title="$bn" -F ticket='{"version": "1.0", "print": {}}' -F contentType="application/pdf" -F printerid="プリンタID" -F "content=@$f;type=application/pdf" "https://www.google.com/cloudprint/submit"

```


## トークンの取り方
トークンを取得する方法は以下が一番見やすかった．
https://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5

```bash
#!/bin/bash

CLIENT_ID=ほげ.apps.googleusercontent.com
CLIENT_SECRET=ふーばー
REDIRECT_URI=http%3A%2F%2Flocalhost%2F
SCOPE=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloudprint

echo "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=$SCOPE&access_type=offline"
```

エンドポイントである`http://localhost/ほげ`に飛ばされるので，`ほげ`のコードを以下で入れて，再度叩く．

```bash
#!/bin/bash

CLIENT_ID=ほげほげ.apps.googleusercontent.com
CLIENT_SECRET=ふーばー
REDIRECT_URI=http%3A%2F%2Flocalhost%2F
SCOPE=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloudprint
# 以下に入れる
AUTHORIZATION_CODE=ほげ

curl --data "code=$AUTHORIZATION_CODE" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "redirect_uri=$REDIRECT_URI" --data "grant_type=authorization_code" --data "access_type=offline" https://www.googleapis.com/oauth2/v4/token
```

これでアクセストークンが貰える．

## macOSのAutomatorで遊ぶ
PDF プリントプラグインにシェルスクリプト実行をぶら下げて，以下を入れる．

```shell
for f in "$@"
do

bn=$(basename $f)

curl -H "Authorization: OAuth アクセストークン" -F title="$bn" -F ticket='{"version": "1.0", "print": {}}' -F contentType="application/pdf" -F printerid="__google__docs" -F "content=@$f;type=application/pdf" "https://www.google.com/cloudprint/submit"



done
```
シェルは`/bin/bash`，また受け取り方は`引数として`を選択する．
たったこれだけで，共有プリンタのできあがりである．
Goで違うmapであることをテストする

Goにおけるmapは実体ではなく参照として扱われる。
故に、代入によっては実体はコピーされず参照だけがコピーされる。
よって、mapを複製する際は新しいmapを作ってそこに内容をコピーする必要がある。

しかし、これを素直にテストしようとすると困ったことになる。
というのも、 `invalid operation: m2 == m1 (map can only be compared to nil)` と怒られてしまうのだ。

https://play.golang.org/p/5e8dUMpU_ky

```go
package main

func main() {
	m1 := map[int]int{}
	m2 := m1
	if m2 == m1 {
		println("m2 is same as m1")
	} else {
		println("m2 is different by m1")
	}

	m2 = map[int]int{}
	if m2 == m1 {
		println("m2 is same as m1")
	} else {
		println("m2 is different by m1")
	}
}

```

これでは困ってしまう。
`reflect.ValueOf` から  `Value.Pointer` を呼び出すことでポインタを得ることができるのでこれを比較することで解決できそうだ。
https://golang.org/pkg/reflect/#Value.Pointer

https://play.golang.org/p/MrpS6SeBXIf

```go
package main

import (
	"reflect"
)

func main() {
	m1 := map[int]int{}
	m2 := m1
	if reflect.ValueOf(m2).Pointer() == reflect.ValueOf(m1).Pointer() {
		println("m2 is same as m1")
	} else {
		println("m2 is different by m1")
	}

	m2 = map[int]int{}
	if reflect.ValueOf(m2).Pointer() == reflect.ValueOf(m1).Pointer() {
		println("m2 is same as m1")
	} else {
		println("m2 is different by m1")
	}
}
```

動いた！
もうちょっと良い方法ないもんかなー。
最近のiOS開発から離脱していたエンジニアの iPhoneX・iOS11対応 記事まとめ

ここ最近、業務系iPadアプリやら、Androidアプリ開発などで、iPhoneX・iOS11以降の環境での注意点がさっぱりだったので、自分向けにリストアップしました。


# iPhoneX対応系
主にiPhoneXに対応するためのデザインガイド、StoryBoard設定、対応コードなどが紹介されていました。

## [Apple - iPhone X用にアプリケーションをアップデートする](https://developer.apple.com/jp/ios/update-apps-for-iphone-x/)
* 本家のドキュメント
* デザインについて
* Face IDについて
* [Human Interface Guidelines](https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/)

## [【随時更新】iPhoneX完全対応マニュアル](https://qiita.com/cokaholic/items/6a8ee3852c8ed28ea2aa)
* セーフエリアについて
* iPhoneXの下のバーを消したい
* セーフエリアに対応済みのレイアウト系ライブラリ一覧

## [iOS11 + Xcode9.0でedgesForExtendedLayoutの値を空にしていると、UITableViewのドリルダウンでアニメーションが崩れる](https://qiita.com/kazuhiro4949/items/db2cbcd5bc06c3e0009e)
* iPhoneXにて、ScrollView、TableViewが画面遷移時に上に上がる問題を回避する方法
* セーフエリアに対応しないアプリを作るときに起きたので、参考にしました

## [ＬisＢエンジニアブログ - コードベースのiPhone X対応で行った5つのこと](http://blog.lisb.direct/entry/2017/12/11/100000)
* カスタムViewのセーフエリア対応方法
* レガシーな実装をiOS11に対応させる方法

# iOS11対応系 

# xcodeバージョンアップ系

## [LCL Engineers' Blog - Swift 4とiPhone Xの対応をしました](http://techblog.lclco.com/entry/2017/10/31/113215)
* Xcodeの設定
* Swift4への変更
* UITableViewのドリルダウンでアニメーションが崩れる対応
* UITableViewのHeader、Footerの設定
* NavigationBarのサイズが小さくなる問題に対応

# おまけ

## [iPhoneXの下のバー(Home Indicator)を常に見えないようにする方法](https://qiita.com/homyu/items/4e03a9787b8032dc7d46)
* 審査には引っかかると思いますが、やってみたらできたので、小ネタとして紹介させてください。
How to tell Windows version 

###

```
In C:\windows.old\system32, open the properties for any system file, like 'ntoskrnl.exe'. On the Details tab, you see the Product Version:

    10.0 = Windows 10
    6.3 = Windows 8.1
    6.2 = Windows 8
    6.1 = Windows 7
    6.0 = Windows Vista
    5.2 = Windows Server 2003
    5.1 = Windows XP
    5.0 = Windows 2000
    4.0 = Windows NT 4
```

cf. https://superuser.com/questions/642316/how-can-i-determine-what-version-of-windows-in-the-windows-old-folder
Provably Fairとその悪い使い方

# Provably Fair

ここ数年でビットコイン等を賭けたりする、オンラインカジノで利用されているアルゴリズムのプロバブリーフェア[^1] (立証可能なフェア)について説明します。

またその悪い使い方についても解説します。

## 1. プロバブリーフェアとは

オンラインカジノなどでは、やろうと思えばゲームホスト側が意図的に勝てるようにすることができます。

そこでフェアにする為のアルゴリズムがプロバブリーフェアです。

先にサーバー側がロール(振り目、乱数、シード値)をハッシュ化しプレイヤーに伝えるこどで、後で不正をすることが出来ないということを保証します。

MegaDice[^2]で利用されている一例を説明します。

![chart.png](https://qiita-image-store.s3.amazonaws.com/0/77253/a0ca16aa-cf0f-7b45-8064-35bd7b50ef23.png)

### ① ゲームの開始

ゲームを開始します。

### ② サーバーのロール

サーバー側が始めに振り目を決めます。

また、Saltというハッシュ化する際に特定を難しくする為のランダムな文字列も決めます。

以上の2つを組み合わせ、SHA-2等の暗号学的ハッシュ関数でハッシュ化します。

このハッシュをクライアントに渡し、次に進みます。

```javascript:サーバー.js
const Random = Math.random() * 100000        //→ 80719.44569750382
const Salt = RanmdomString()                 // RanmdomStringはランダムな文字列作る架空の関数
const Hashed = SHA256(Random + '_' + Salt)   // SHA256は文字列をハッシュ化する架空の関数
//→ 98fd4c46069842474adef848863e8eaca4af1cce2dede172af2ea5e9a0f20969
```

この時点ではホスト側は必ず振り目とソルトを隠します。

### ③ クライアントのロール

クライアントはハッシュを受け取り、これはフェアなゲームだと確認した上で振り目を決めます。

プレイヤー側は値をそのままサーバーに送信します。

```javascript:クライアント.js
const ServerRollHash = '98fd4c46069842474adef848863e8eaca4af1cce2dede172af2ea5e9a0f20969'
const ClientRandom = Math.random() * 100000
//→ 53127.75250042807
```

### ④⑤ ゲームの最終乱数値と結果 

サーバー側はクライアントの決めたランダム値とサーバーのランダム値を合わせます。

```javascript:サーバー.js
const MaxNumber = 65536  // ゲームのさいころの最大値
const RecivedClientRandom = 53127.75250042807
const Result = Math.floor( (RecivedClientRandom + Random) % (MaxNumber + 1) )
//→ 2773
```

これでゲームの(大きな)さいころの振り目が決まります。

### ⑥ 振り目の検証

最後にクライアントはサーバーが使っていた乱数とソルトを知ることができます。

この情報を元に検証し、このゲームがフェアだったことを確認することができます。

```javascript:クライアント.js
const MaxNumber = 65536  // ゲームのさいころの最大値
const RecivedServerRandom = 80719.44569750382
const RecivedServerSalt = 'f89034eh89ghdfhgu904u8ujgri0sjgkl23j'
// ハッシュの検証
console.assert( ServerRollHash === SHA256(RecivedServerRandom + '_' + RecivedServerSalt), 'Fraud!' )
// 結果の乱数の検証
const Result = 2773
console.assert( Result === Math.floor( (ClientRandom + RecivedServerRandom) % (MaxNumber + 1), 'Fraud!' )
```

ハッシュ関数で作られた文字列は改ざん不可で、それから元の値を知ることはできないとされています。

その為これはフェアだったと確認することができました。

## 2. フェアではない見せかけのプロバブリーフェア

一見するとフェアですが、少し違う方法をとっているとフェアでない場合があります。

以下のフローがフェアではない一例です。

![scam.png](https://qiita-image-store.s3.amazonaws.com/0/77253/3ca73004-a458-8122-09a6-0d022568c36f.png)

しっかりハッシュ化されたサーバーの振り目を伝えていてフェアに見えます。

しかしながら、クライアントが振ったランダムな値が利用されていません。

つまりホスト側は最初から結果を知ることが出来ます。悪用例を挙げてみます。

### 悪用例

あるカジノではコインフリップというゲームがあります。

プレイヤー対プレイヤー(PvP)方式で、賭けた額の割合が勝率になります。

* プレイヤー1とプレイヤー2がいます

* ここでは同じ額賭けたことにします（50:50）

* どちらにも予めサーバーの値のハッシュが伝えられます (Probably Fair)

* さいころは整数で1..100の範囲です

* サーバーが決めた値の範囲に入っている人の勝ちになります

以上の設定を図にします。

![scamex.png](https://qiita-image-store.s3.amazonaws.com/0/77253/3d904611-4198-bf25-9636-e3287fe39f96.png)

この状況で、さいころの数値が30だった場合はプレイヤー1の勝ち、70だった場合はプレイヤー2の勝ちになります。

このゲーム上で、サーバーが既に振り目を知っているとサクラ(bot)を入れて意図的に運営が勝ちをかっさらえるようになります。

実際に、運営がBOTをプレイヤーに見せかけ儲けを得るというのもありました。[^3]

## 3. 注釈等

ギャンブルはやめとこうね

悪用例の方法ですが、PvP方式でない場合は問題がないかもしれません。

[^1]: https://en.wikipedia.org/wiki/Provably_fair
[^2]: https://www.megadice.com/provably-fair/
[^3]: http://www.twitlonger.com/show/n_1sqclek
Unity2017.3 AWSSDKエラーの回避



#Unity2017.3でのAWSSDKエラーについて
Unity2017.2系で正常に動作していたのに
Unity2017.3.0p4でAWSSDK(正確にはlambdaを使ってた）を使用すると 下記のようなエラーが発生して動作してくれません。

OS:macOS 10.12.6
Unity:Unity2017.3.0p4

>Amazon.Lambda.AmazonLambdaException: The request signature we calculated does not match the signature you provided. >Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

AWSSDK.NETのgithubにも同様のissueがあがっていました。
https://github.com/aws/aws-sdk-net/issues/820

#原因
いろいろ、調査しましたが どうやら UnityWebRequestの動作が変わったのが影響しているようです。
(AWSConfigs.HttpClient = AWSConfigs.HttpClientOption.UnityWebRequest; を設定してAWSSDK使用している）

UnityEditorからUnityWebRequest(AWSSDKを使用せずシンプルなコードで)を使って送信内容を確認してみると、Unity2017.3.0p4にのみ`Transfer-Encoding: chunked`のHeader情報が追加されていました。
どうやらこの影響で、エラーが発生しているようなのです。
(chunkedになることによって、signatureの作成がおかしくなってるんでしょうね。いろいろ調査しましたが。。まあ割愛）

Unity2017.2.0f3
>Content-Length: 19
>Content-Type: application/json
>Accept: */*
>Accept-Encoding: deflate, gzip
>Host: www.kojikoji.net
>User-Agent: UnityPlayer/2017.2.0f3 (UnityWebRequest/1.0, libcurl/7.51.0-DEV)
>X-Unity-Version: 2017.2.0f3

Unity2017.3.0p4
>**Transfer-Encoding: chunked**
>Content-Length: 19
>Content-Type: application/json
>Accept: */*
>Accept-Encoding: deflate, gzip
>Host: www.kojikoji.net
>User-Agent: UnityPlayer/2017.3.0p4 (UnityWebRequest/1.0, libcurl/7.51.0-DEV)
>X-Unity-Version: 2017.3.0p4

#回避コード

``` csharp
public class HogeHoge : MonoBehaviour
{
    private void Awake()
    {
         // AWSSDKの初期化後に今回のエラー回避用のコンポーネントを追加している
         UnityInitializer.AttachToGameObject(gameObject);
　　　　  // this bug workaround code
         // https://github.com/aws/aws-sdk-net/issues/820
         gameObject.AddComponent<CustomUnityMainThreadDispatcher>();
　　　　　// その他の初期化処理など..
         AWSConfigs.HttpClient = AWSConfigs.HttpClientOption.UnityWebRequest;
                                ：
    }
}
```
CustomUnityMainThreadDispatcherコンポーネントのコード
https://gist.github.com/housei/b38cc93d6e8fe7caa2764d5b0dc34393

修正内容としては本来AWSSDKのUnityMainThreadDispatcherコンポーネントが処理している
web request処理をよこどりして
CustomUnityMainThreadDispatcher側で実行させ、UnityWebRequest.chunkedTransfer = falseに設定することで'`Transfer-Encoding: chunked`が追加されないようにしています。

AWSSDK側の修正が入るまでは、この回避方法でしのぎます。
awssdk-netのソースコードを修正してunitypackage化するのが正攻法ですね。
(私の環境がmacでして,Windowsでvisual stduio使えればこのへんサクッとできるかもしれませんね）
【凡ミス禄】origin masterへgit pushできなかったとき行った対処


```
 $ git push origin master

Warning: Permanently added 'github.com,192.30.253.113' (RSA) to the list of known hosts.
ERROR: Repository not found.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

ありゃ。なんで。
```
$ git remote add origin　-リポジトリURL-
```
で設定したはずなのに。
前日[リポジトリ名変更](https://qiita.com/hisurga/items/583e8dbe4970bc8c25c8)したからかな？

そこで、上記記事をちゃんと見てみる。

あー、ローカルだけでなく、Github上でもリポジトリ名をrenameしなければならないのね。
勝手に反映してくれるものかと思ってました。
理解。



参考：[GitHubのリポジトリ名変更方法 -qiita](https://qiita.com/hisurga/items/583e8dbe4970bc8c25c8)
CentOS7.4にてOpenStack Newton ダッシュボード(Horizon)表示エラー対応

# 背景
OpenStack NewtonをCentOS7.4にてアップグレードした際に、ダッシュボードが正常に表示されません。
日本語情報が少ないので参考情報として投稿してます。

# 修正方法
ApacheのHorizon設定ファイルに１行追加します。

````
$ sudo vi /etc/httpd/conf.d/15-horizon_vhost.conf
 WSGIApplicationGroup %{GLOBAL}
````
ダッシュボード関係サービス再起動

````
$ sudo systemctl restart httpd.service memcached.service
````

# 参考情報
Bug 1481265 - Horizon Dashboard gives Error 500 after initial install on 7.4
https://bugzilla.redhat.com/show_bug.cgi?id=1481265
Azure IoT Hub に Node.js で publish

Arch Linux と Raspbian で動作を確認しました。

ライブラリーのインストール

```bash
sudo npm install azure-iot-device
sudo npm install azure-iot-device-mqtt
```

５秒毎にメッセージを送るサンプルです。
connectionString　は変更して下さい。

```js:azure_publish.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	azure_publish.js
//
//					Feb/06/2018
//
// ---------------------------------------------------------------
var devicemqtt = require('azure-iot-device-mqtt')
var device = require('azure-iot-device')
//
// ---------------------------------------------------------------
function printResultFor(op) {
	return function printResult(err, res) {
	if (err) console.log(op + ' error: ' + err.toString())
	if (res) console.log(op + ' status: ' + res.constructor.name)
	}
}
// ---------------------------------------------------------------
function define_data_proc ()
{
	const jikan= new Date()
	const hour = jikan.getHours()
	const minute = jikan.getMinutes()
	const second = jikan.getSeconds()
	const current_time = "" + hour + ":" + minute + ":" + second
        const tt = (20 + (Math.random() * 15)) * 10
        const temperature = Math.round (tt) / 10
        const hh = (60 + (Math.random() * 20)) * 10
        const humidity = Math.round (hh) / 10
        const ddx = { deviceId: 'dev001', time: current_time, temperature: temperature, humidity: humidity }
        const data = JSON.stringify(ddx)
	return data
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
//
var Message = device.Message;
 
const connectionString = "HostName=iot-aa.azure-devices.net;DeviceId=pansy;SharedAccessKey=2eQ2wF5O123456789G3CGJNXF123TfAnMJbZ8wtJPu4="
 
var client = devicemqtt.clientFromConnectionString(connectionString)

var connectCallback = function (err) {
if (err)
	{
	console.error('Could not connect: ' + err);
	}
else
	{
	console.log('Client connected')

	setInterval(function()
		{
		const data =  define_data_proc ()
		var message = new Message(data)
		console.log("Sending message: " + message.getData())
		client.sendEvent(message, printResultFor('send'))
		}, 5000)
	}
}

client.open(connectCallback)

console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```
UINavigationControllerにコードからカスタムNavigationBarとViewControllerを設定する

##### １．イニシャライザでカスタムNavigationBarを指定する

```swift
let navigationController = UINavigationController(navigationBarClass: CustomNavigationBarClass.self, toolbarClass: nil)
```

##### ２．RootViewControllerをセットする

`UINavigationController`にviewControllerのスタックが積まれていない時、`setViewControllers`メソッドに指定した１件目のViewControllerがRootViewControllerとして扱われます。

```swift
navigationController.setViewControllers([UIViewController()], animated: false)
```

---

イニシャライザが`init(rootViewController:UIViewController)`と`init(navigationBarClass:AnyClass?, toolbarClass:AnyClass?)`しか存在していないので両立は無理なのかと思っていましたが、そういうわけでもなく、`setViewControllers`を利用することで両立可能なのでした。
超基礎SQL覚えようリスト

#概要
SQLって何から覚えたらいいの？人向け
最低限覚えたほうがいい項目を記述してます。

使い方や詳細などは別の書籍などで確認してね。

#SQL分類を覚えよう
SQLには大きく分けて、3種類存在する。

* DML　(Data Manipulation Language データ操作)
    * データ作成、読み取り、更新、削除を行う
* DDL　(Data Definition Language データ定義)
    * テーブル作成、更新、削除を行う
* DCL　(Data Control Language データ制御)
    * 権限管理をする

DDLとDCLは管理者寄りのコマンドなので、
DML > DDL > DCLの順番で覚えていこう。

#DMLの基本を覚えよう
##DMLの分類を覚えよう
DMLの操作命令には大きく分けて、４つある

* SELECT
    * データを読み取る
* UPDATE
    * データを更新する
* DELETE
    * データを削除する
* INSERT
    * データを作成する

Railsなんかでよく言われるCRUDと同じだと思ってくれればいい。
まずは使用頻度の高いSELECTから覚えていこう。

##SELECTの基本を覚えよう
基本の文法は以下の通り

```
SELECT 取得対象列名
  FROM 取得対象テーブル名  
```

テーブルを指定し、更に列名を指定することで、
全行の指定した列のデータを取得することが出来る。

また複数列も指定出来る。

```
SELECT 取得対象列1, 列2, 列3, ...
  FROM 取得対象テーブル名  
```

全ての列を指定したい場合は「*」を使えば良い。

```
SELECT *
  FROM 取得対象テーブル名  
```

##UPDATEの基本を覚えよう
基本の文法は以下の通り

```
UPDATE 更新対象テーブル名
   SET 更新対象列名=代入後の値
```

テーブルを指定し、更新したい列名に更新値を指定することで
全行の指定した列のデータを更新出来る。
複数列も更新出来る。

```
UPDATE 更新対象テーブル名
   SET 更新対象列1=代入後の値, 更新対象列2=代入後の値, ...
```

##DELETEの基本を覚えよう
基本の文法は以下の通り

```
DELETE
  FROM 削除対象テーブル名
```

指定したテーブルの全行を削除
テーブル自体を消すわけではなく、テーブルの中身を消すだけ。

##INSERTの基本を覚えよう
基本の文法は以下の通り

```
INSERT INTO 作成対象テーブル名
            作成対象列名1, 列名2, 列名3, ...
VALUES      作成後の値1, 値2, 値3, ...
```

作成対象テーブル内にデータつまり行を作成
どの列にどの値を入れるかを順番に指定していく。
↑の例だと、列名1に値1が入り、列名3に値3が入る。

#条件分岐の基本を覚えよう
↑の基本だけでは、明らかに実践に使えないことが何となく分かるかと思う。
例えば、↑の基本通りDELETEを使うと、全データが消えてしまうので、
Qiitaで例えると、ある記事の削除ボタンを押したら、全ての記事が消えてしまうようなものだ。

ということで、ある条件に一致した（TRUEとなる）データだけ消したり、更新出来るようにしたい。

条件分岐の基本は以下の通り

```
INSERT以外の命令
WHERE 条件式
```

INSERTにはWHEREを使うことは出来ない。
条件式はTRUEorFALSEになるように記述しよう。

```SQL:
WHERE weight > 60 
```

例えば、↑の例だと、列名1が60より
大きいデータの場合、TRUE
それ以外のデータの場合、FALSEとなります。

↓のテーブルに対して使うと、
田中さんはFALSE
山田さんはTRUE
渡辺さんはTRUEとなります。

テーブル名：weight_table

| name       | weight |
|:-----------------|------------------:|
| 田中       | 55 |
| 山田       | 64 |
| 渡辺       | 70 |

このテーブルを使って、
SELECT,UPDATE,DELETEを使ってみよう。

##SELECT（条件分岐あり）を覚えよう

条件分岐ありSELECT

```sql:
SELECT name
FROM   weight_table
WHERE  weight >= 65
```

得られたデータ

| name       |
|:----------|
| 渡辺       |


##UPDATE（条件分岐あり）を覚えよう

```sql:
UPDATE weight_table
SET    weight=80
WHERE  name='山田'
```

更新後のテーブル

| name       | weight |
|:-----------------|------------------:|
| 田中       | 55 |
| 山田       | 80 |
| 渡辺       | 70 |

##DELETE（条件分岐あり）を覚えよう

```sql:
DELETE 
FROM   weight_table
WHERE  weight < 60
```

削除後のテーブル

| name       | weight |
|:----------|------------------:|
| 山田       | 64 |
| 渡辺       | 70 |

##比較演算子の基本を覚えよう
条件式に使える「>」などを比較演算子という
↑では何となく感覚的に使っていた比較演算子だが、
使えるものは決まっているので、覚えよう。

| 比較演算子 | TRUEになる条件 |
| :--------|-----:|
| = | 両辺の値が等しい |
| < | 左辺より右辺の値が大きい|
| > | 左辺より右辺の値が小さい|
| <= | 左辺は右辺の値以下|
| >= | 左辺は右辺の値以上|
| <> | 両辺の値が等しくない|

「<>」は少し見慣れないかな。
「!=」とかはよく見るけど。
mrubyブリッジの作り方


# mrubyブリッジ

mrubyブリッジは，TECS CDL の signature 記述に基づき，mruby と TECS コンポーネントをブリッジする，「mruby の C 言語実装クラスであり TECS のセルタイプとなるコンポーネント」です．


# 実装

## コンポーネント記述 (.cdl)

### tButton.cdl

```c:tButton.cdl
import_C("gr_peach.h");

signature sButton {
	bool_t isPressed(void);
};

celltype tButton {
	entry sButton eButton;
};
```

### bridge.cdl

```c:bridge.cdl
...
import(<tButton.cdl>);

/*
 * シグニチャプラグイン MrubyBridgePlugin の呼び出し。
 */
...
generate( MrubyBridgePlugin, sButton, "" );

/*
 *  サンプルプログラムの定義
 */
...
cell nMruby::tsButton BridgeButton {
	cTECS = Button.eButton;
};

...
cell tButton Button {};
```

## セルタイプコード (.c)

tecsmerge を使用して作ったテンプレートに実装する

```c:tButton.c
bool_t
eButton_isPressed(CELLIDX idx)
{
	CELLCB	*p_cellcb;
	if (VALID_IDX(idx)) {
		p_cellcb = GET_CELLCB(idx);
	}
	else {
	} /* end if VALID_IDX(idx) */

	return gr_peach_get_button();
}
```

## mruby (.rb)

クラスの継承。Rubyっぽくする。

```rb:Button.rb
class Button < TECS::TsButton
	private
	def initialize()
		super "BridgeButton"
	end
	@@instance = self.new

	public
	def self.pressed?
		@@instance.isPressed
	end
end
```

## VMの設定

作ったクラスをVMに追加する

```c:VM1.cdl
cell nMruby::tMruby Mruby {
	mrubyFile =
		"$(MRUBY_LIB_DIR)/RTOS.rb "
		"$(MRUBY_LIB_DIR)/LED.rb "
		"$(MRUBY_LIB_DIR)/Button.rb "
		"$(MRUBY_APP_DIR)/button_sample.rb";

	cInit = VM_TECSInitializer.eInitialize;
    cSerialPort = SerialPort1.eSerialPort;
};
```
## サンプルアプリケーション

```rb:button_sample.rb
begin
    loop do
        LED.color = :red
        LED.color = :blue if Button.pressed?
    end
rescue => e
    puts e
end
```
Logic Apps, Azure Functions を使い 全自動ついふぁぼ機をサーバーレスで作った。

勉強会を主催したときに参加者の人がイベントページをつぶやいてくれた時に **ふぁぼりたい★** というのはよくあると思います。

そんな時に、気軽に自動ふぁぼプログラムを作れるようにサーバーレスで作成してみました。

# 作成にかかった時間

- 1時間

# 使用したもの

- Azure Functions 
- Logic Apps
- NodeJS
- npm Twitter module

# プログラムの構成図

1. Twitter より新しい呟きを Logic Apps で検知
2. 呟きの情報を Azure Functions へ
3. Azure Functions は呟きの情報を使い **ふぁぼ！**

![プレゼンテーション1.png](https://qiita-image-store.s3.amazonaws.com/0/143354/257eebd5-3bfd-2d9e-4a3e-eebfaa3171f9.png)

# 内容

## 新しい呟きを Logic Apps より取得

![2018-02-06_15-27-16[1].png](https://qiita-image-store.s3.amazonaws.com/0/143354/c3b021d7-7789-7c7d-6258-787fd2c89fdb.png)

Logic Apps のTwitterトリガーを使い新しいツイートがされるたびに起動するようにしています。
工夫した点は、検索文字列の「ブイアールサンダー lang:ja -RT」で 

- **lang:ja** にすることで日本語ツイートに限定
- **-RT** にすることでリツイートは除外しています

あとは、 Azure Functions を Logic Apps から呼び出しています。

## ツイートの情報を利用していいね！

Azure Functions 側の話に移ります。

JS で作成しています。

### Twitter をJSから叩けるパッケージの導入

Azure Functions のコンソールより適当に npm の導入とパッケージのインストールを行います。

```sh
npm init -y
npm install Twitter
```

パッケージの公式ドキュメントを参考にしました。

https://www.npmjs.com/package/twitter

### 環境変数のセットアップ

コードにTwitterとの接続情報を記入してもいいのですが、環境変数に記入することで Azure Functions を使いまわせるかなと思ったのでそうしました。

``` Azure Functions > アプリケーション設定 ```

より導入しました。

![2018-02-06_15-33-48[1].png](https://qiita-image-store.s3.amazonaws.com/0/143354/fd15a875-f732-fc0b-7684-36e473e37638.png)

### Azure Functions の コード

```js
module.exports = function (context, data) {
  // Twitter パッケージの導入
  var Twitter = require('twitter');
  
  var input = data;

 // Twitter クライアントの作成
  var client = new Twitter({
        consumer_key: process.env.TWITTER_CONSUMER_KEY,
        consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
        access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
        access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET
   });

  client.post('favorites/create.json', {id: input.tweetId});

    context.done();
};
```

# まとめ

Logic Apps を利用してツイートをトリガーにするのは楽。
npm の Twitter パッケージを使うと楽。
pandasのカテゴリカル変数をダミー変数に変換する関数

#ダミー変数
　データ解析をしていると、ダミー変数を使わないといけない場面に多く遭遇すると思います。例えば性別のデータを扱う時などは、そのままだとコンピュータが扱えないので、男=1、女=0といった感じで数値に変換してやる必要があります。
　pythonのpandasには、カテゴリカル変数をダミー変数に変換するためのパッケージがあるのですが、自分で変換する列を指定したりといろいろ扱うのが面倒なので、dataframeを投入するだけでカテゴリカル変数をダミー変数に変換してくれる関数を作成しました。

```python3:dummy.py
def dummy(df):

    # ダミー変数を格納するための空のdataframeを作成する
    df_empty = pd.DataFrame(index=df.index, columns=[])
    # カテゴリカル変数の変数名を格納するため
    index = []

    for i in range(len(df.columns)):
        # 変数のデータ型を確認する
        data_type = df.iloc[:,i].dtype
        # object型をダミー変数に変換する
        if data_type=="object":
            df_empty[df.columns[i]] = df.iloc[:,i]
            index.append(df.columns[i])

    # ここでダミー変数に変換する
    df_dummy = pd.get_dummies(df_empty, drop_first=False)
    # 元のdfとdf_dummyを結合する
    df_new = pd.merge(df_dummy, df, left_index=True, right_index=True)
    # まだダミー変数に変換前のカテゴリカル変数が残っているので削除する
    df_new = df_new.drop(drop_col, axis=1)

    return df_new
```
#まとめ
まだまだプログラミングを始めて日が浅いので、改善点がありましたらどんどん指摘してください！
Sublimetext3で糞コードを可視化する

# はじめに
pythonistaたるものPEP8に準拠していない糞コードはあってはならない！
と、いうことでネタ記事となります。
結論をいうとエラーと警告のアイコンをう〇こに変えます。


# 使うもの
- Sublimetext3
  - 私が普段使用しているエディタです。
- SublimeLinter
  - 文法チェックを自動で行ってくれるプラグインです。
  - SublimeLinterのフレームワーク上に各言語のプラグインをのっけて使用します。
  - 冒頭でpythonistaｶﾞｰって言ってるのでpythonを対象とします。
- アイコン用のpngファイル
  - 16x16のものをエラー用、警告用の2種類用意します

# 事前準備
SublimeText3のインストールや日本語化について
みなさんわかりやすい記事を書いてくださってますのでそちらをご参考ください

Sublime Text 3のインストールと初期設定
https://qiita.com/lunatea/items/53f4adcc6ea3f316e781

WindowsでSublimeText3日本語化は意外と分かりづらい（mac版追記）
https://qiita.com/I-201/items/0869a288eb6e4ed5a274

SublimeText3 初期設定 日本語に完全対応する
https://qiita.com/non0311/items/70686957d2e2756533d5

# SublimeLinterの導入
Sublimetext3のプラグイン、SublimeLinterをインストールします。
SublimeText3を開いた状態で
[Ctrl + Shift + P] → [PackageControl installPackage]
と入力しEnterをおします。
Packageの一覧が表示されるので
・Sublimelinter
・Sublimelinter-pep8
を選択しインストールしてください。

# エラーアイコンの変更方法
デフォルトの場合
C:\Users\[ユーザ名]\AppData\Roaming\Sublime Text 3\Packages\SublimeLinter\gutter-themes
にフォルダを作ります。ここの名前はどこにも影響ないので好きにしてください。
作成したフォルダの中には
・warning.png (警告時のアイコン)
・error.png (エラー時のアイコン)
・[テーマ名].gutter-theme
というファイルを作成してください。

[テーマ名].gutter-themeは空ファイルでも問題ありませんが

```
{
    "colorize": true or false
}
```
と入れておきましょう。
ガターテーマの色付けの有無に関係があるようなのですが調べていません…


アイコンはpngで16x16のものを用意しましょう。
32x32やもっと大きいサイズの画像をおいてみましたが一覧に表示されませんでした。
ちなみに私の書いた糞コードを教えてくれるアイコンはこちらです。
![error.PNG](https://qiita-image-store.s3.amazonaws.com/0/169001/d7a5f7a6-d683-a34d-ad77-e93356b484ce.png)

設定ファイルの準備が終わったら一旦SublimeText3を再起動しましょう。
その後、右クリック→SublimeLinter→Choose Gutter Theme...を選択
選べるテーマの一覧が出てくるので[テーマ名].gutter-themeのテーマ名を選択すれば終了です。


正しく読み込まれた場合は下記画像のようにアイコンがう〇こに変わります!
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/169001/287c7bd7-ec8b-ebd7-caa6-89736e91c8f3.png)
コードレビューのときとか誰かが後ろ通ったときとかに糞まみれだと赤っ恥を書くのですぐに直す習慣がつきそうです。

# 終わりに
職場でこんなふざけたものを使うわけにもいかないのですぐに戻しました。
deviseのauthenticate_◯◯!のリダイレクト先を変える

ドキュメントにあった。
Rails5でも問題ありませんでした。

[How To: Redirect to a specific page when the user can not be authenticated](https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated)
Project Euler 21 「友愛数」

小出しスタイルにシフトチェンジ。

## Problem 21 「友愛数」
d(n) を n の真の約数の和と定義する. (真の約数とは n 以外の約数のことである. )
もし, d(a) = b かつ d(b) = a (a ≠ b のとき) を満たすとき, a と b は友愛数(親和数)であるという.
例えば, 220 の約数は 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110 なので d(220) = 284 である.
また, 284 の約数は 1, 2, 4, 71, 142 なので d(284) = 220 である.
それでは10000未満の友愛数の和を求めよ.

```python
def hoge(num):
    ans = 0
    shinyakuwa = {}
    for n in xrange(1, num):
        shinyakuwa[n] = get_shinyakuwa(n)
    for x, y in shinyakuwa.iteritems():
        if  x != y \
        and shinyakuwa.has_key(y) \
        and x == shinyakuwa[y]:
            ans += x
    return ans

def get_shinyakuwa(n):
    shinyaku = [1]
    for m in xrange(2, (n/2)+1):
        if n % m == 0:
            shinyaku.append(m)
    return sum(shinyaku)

print hoge(10000)
```

何か閃きそうだったけどピンとこなかったのでいつもの愚直スタイル。
ボクの考えた git pull より強いコマンド

ボクは `git pull` は使いにくいと思います。なぜなら、

「ローカルとリモートに両方変更があった時、勝手に（自動的に） merge や rebase をしてしまう」
「自動的な merge や rebase は時々失敗する」
「というより、ローカルとリモートに両方変更があるのは、大抵作業ミスなので[^1]、merge も rebase もするべきではない」

[^1]: ボクのチームの開発環境においては。

からです。なので `git pull` より使いやすいコマンドを作りました。

# 代替案

ボクが本当に必要なのは以下のコマンドだと思いました。

```sh
$ git fetch && git reset --hard origin/master
```

でも、このままだとローカルブランチにリモートには無い変更があった時に、問答無用で上書きされてしまいます。「変更があります」と表示して中止してほしいです。

# git-latest

使い方:

```sh
$ git checkout master  # 更新したいブランチを checkout
$ git latest  # origin/master と同期される
```


ソースは以下の通り。このソースを `git-latest` という名前でPATHの通った場所においてください。

```
#!/bin/bash
set -euC

usage_and_abort() {
  echo 'usage: git latest [-f]' >&2
  exit 1
}

if [ "$#" -gt 1 ]; then
  usage_and_abort
fi

force=false
if [ "$#" -eq 1 ]; then
  if [ "$1" = "-f" ]; then
    force=true
  else
    usage_and_abort
  fi
fi

git fetch origin

r="$(git rev-parse --abbrev-ref --symbolic-full-name '@{upstream}')"

if [ -n "$(git log -n 1 --oneline "$r"..)" ] && [ "$force" != "true" ]; then
  echo 'There are commits which have not been pushed.' >&2
  echo 'Please run "git latest -f" when you ignore these commits.' >&2
  exit 1
fi

git reset --hard "$r"
```
Beamerの定理環境で英語が斜体にならないようにする

Beamerの定理環境を使うと、英語だけが斜体になってしまう。英語のスライドを作るならこのままでいいのだろうが、やはり日本語のスライドを作るときには気持ち悪い。
普通の文書を作るときにはamsthmを用いて `\theoremstyle{definition}` などとすればいいわけだが、Beamerの場合にはそれとは違い、

```latex
\setbeamertemplate{theorems}[normal font]
```

とプリアンブルに書けば直る。
AWS Codedeployでデプロイが遅い時の対処法

## TL;DR
ELBヘルスチェックのしきい値を最小まで下げると高速化します

![ss3.png](https://qiita-image-store.s3.amazonaws.com/0/40799/9158f7b3-7bde-45ea-1849-49ee8190ad13.png)


## 環境
CLB(Classic Load Balancer)
インプレースデプロイ
EC2インスタンス２台(AZ)

## 何が起こったのか

codedeployにてデプロイは成功するものの、`BlockTraffic` と`AllowTraffic` が５分もかかっている・・・。

![ss1.png](https://qiita-image-store.s3.amazonaws.com/0/40799/dd7e9641-8e7e-5dcc-5ab9-a81240aa4bbc.png)

そんなばかな・・・こんなもんなの？インプレースだから？と思ったが

[AWSフォーラム](https://forums.aws.amazon.com/thread.jspa?threadID=254752&tstart=0)に答えがありました。

どうやら、デプロイのライフサイクル中の `BlockTraffic` と`AllowTraffic`はELBのヘルスチェックに依存するらしく、ヘルスチェックの値を適宜変更しなければならないよう。

とりあえず、ヘルスチェック設定の最小しきい値を上から順に `2,5,2,2`に設定すると

![ss2.png](https://qiita-image-store.s3.amazonaws.com/0/40799/ae911e85-bce8-856a-10ea-7b60439fab62.png)

`5分1秒 → 16秒`まで短縮されました :relaxed:

もっと高速化できないのかな？
ひとまず解決ということで。
初心者がmongoose公式 勉強するメモ　model編

# mongoose model
## 今回のお題はこちらです。
## http://mongoosejs.com/docs/models.html
* 英語ですので、chromeの翻訳を使って下さい。
* 検証結果は、掲載しませんので、実際確認してみてください。

## default接続まで
* model.js

``` js

const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/test"); // default 接続 DB: test

// 最初のモデル
const yourSchema = new mongoose.Schema({ name: 'String', size: 'String' });
const Tank = mongoose.model('Tank', yourSchema); // default 接続  tanks

// 書類の作成
const small = new Tank({name: 'Yasu2', size: 'large2'});

small.save(err => {
  if (err) console.error(err)
  console.log('saved')
  mongoose.disconnect();
});

```
* mongoose.model使用すると、default connection(mongoose.connect)が使われるそうです。
* node model.js  でsaveが実行されます。
* mongo シェルで確認するとちゃんと出来ています。DB: test  collection: tanks

## カスタム接続
* model.js

``` js

const mongoose = require("mongoose");
const connection = mongoose.createConnection('mongodb://localhost:27017/apple'); // DB: apple

const yourSchema = new mongoose.Schema({ name: 'String', size: 'String' });
const Tank = connection.model('Tank', yourSchema); // カスタム接続

// 書類の作成
const small = new Tank({name: 'Yasu3', size: 'large3'});

small.save(err => {
  if (err) console.error(err)
  console.log('saved')
  mongoose.disconnect();
});


```
* 接続するDB,コレクションを個別にするみたいです。
* アクセスするDBをインスタンス毎に、個別に指定したい場合に必要になりますね。
* こちらもmongoシェルで確認すると出来ています。（DB名はappleです。）

## クエリ


* model.js

``` js

const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/test");

const yourSchema = new mongoose.Schema({ name: 'String', size: 'String' });
const Tank = mongoose.model('Tank', yourSchema); // tanks

Tank.find({size: 'large'}).where({name: 'Yasu'}).exec((err, docs) => {
  if (err) console.error(err);
  for (let val of docs) {
    console.log(val);
    mongoose.disconnect();
  }
})

```
* クエリで細かい指定も出来るみたいです。
* 上の条件は、size: 'large' and name: 'Yasu'

## 削除

* model.js

``` js

const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/test");

const yourSchema = new mongoose.Schema({ name: 'String', size: 'String' });
const Tank = mongoose.model('Tank', yourSchema); // tanks

Tank.remove({size: 'large'}, err => {
  if (err) console.error(err);
  console.log('removed');
  mongoose.disconnect();
})

```
* mongoシェル確認 OK

## update

* model.js

``` js

const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/test");

const yourSchema = new mongoose.Schema({ name: 'String', size: 'String' });
const Tank = mongoose.model('Tank', yourSchema); // tanks

Tank.findOneAndUpdate({size: 'small'},{ name: 'Banana'}, err=> {
  if (err) console.error(err);
    console.log('update')
    mongoose.disconnect()
})

Tank.update({size: 'middle'}, {$set: {name: 'Orange'}}, {upsert: true, multi: true}, (err) => {
  if (err) console.error(err);
  console.log('update');
  mongoose.disconnect()
} )
```
* mongoシェルにて確認 OK

* modelは、これで終了です。
* 少しづつ使い方が判ってきました。
aliasを貼って、オリジナルBashコマンドを定義する for Mac

# .bashrcファイルの作成

## ホームディレクトリに、.bashrcファイルを作成します。

```bash
vim .bashrc
```


## aliasの定義
今回は、`ls -la`コマンドを、`ll`で実行できるようにしてみます。

先程の.bashrcファイルに、以下のように定義します。

```bash
alias ll="ls -la"
```


## 変更点を読み込む

`source .bashrc`を叩く

するとllコマンドが使えます。


# 個人ブログ始めました
よかったら見てあげてください。
https://nnahito.com/

今回の設定は、ターミナルを再起動したら消えてしまいます。
[設定を持続させる方法はこちら](https://nnahito.com/articles/26)
Gremlinと戯れる

GraphDBを操作する為、`Graph Traversal Language`の [Gremlin](https://github.com/tinkerpop/gremlin) を使ってみます。

今回は、 Pythonで操作する為、 [gremlin-python](http://tinkerpop.apache.org/docs/3.3.0/reference/#gremlin-python) を導入しました。

* インストール

[pip](https://pip.pypa.io/en/stable/installing/) を使って、[gremlin-python](http://tinkerpop.apache.org/docs/3.3.0/reference/#gremlin-python)　をインストールします。

```
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py --user
pip install gremlinpython --user
```

上記ですが、pythonの環境構築が適当です。。
真っ当な環境を作る場合は、python仮想環境等を作って、パッケージ管理を行ってください。

以降、REPLでの処理を想定しています。

* GraphDBへの接続

```
from gremlin_python import statics
from gremlin_python.structure.graph import Graph
from gremlin_python.process.graph_traversal import __
from gremlin_python.process.strategies import *
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection

graph = Graph()

g = graph.traversal().withRemote(DriverRemoteConnection('websocketのURL','g'))
```

＊ 頂点(Vertex, ノード）の情報表示

```
g.V().toList()
```

全ての頂点を対象として、idが表示される。

```
g.V().valueMap().toList()
```

頂点が保持しているpropertyの情報も表示する。

* 端(Edge, リレーション）の情報表示

```
g.E().toList()
```

idが表示される。

```
g.E().valueMap().toList()
```

端が保持しているpropertyの情報も表示する。

* 頂点の追加

```
g.addV('gremlin1').property('name', 'gremlin1').toSet()
```

* 頂点のpropertyを利用した情報の取得

```
# 頂点のpropertyの値を取得.(propertyのvalueのlistを取得)
g.V().values('name').toList()

# 頂点に対し、該当するpropertyのkey/valueを持つ頂点を絞り込んで取得.(頂点のidを取得)
g.V().has('name','gremlin1').toList()

# propertyを追加して、追加されたことを確認
gremlin1 = g.V().has('name','gremlin1').toList()[0]
g.V(gremlin1).property('country','usa').toSet()
g.V(gremlin1).valueMap().toList()
# 以下のようなデータを取得.
# -> [{u'country': [u'usa'], u'name': [u'gremlin1']}] 
```


* 端の追加

```
# 頂点 gremlin2を追加し、gremlin1からgremlin2へ橋を追加.
g.addV('gremlin2').property('name', 'gremlin2').toSet()
gremlin2 = g.V().has('name','gremlin2').toList()[0]

# fromの後ろに_があることに注意.
g.addE('friend').from_(gremlin1).to(gremlin2).toSet()

# 追加した端から情報が取得できることを確認.
g.V(gremlin1).out('friend').valueMap().toList()
```

* 端のproperty操作

```
# 端にpropertyを追加する.
# labelから取得して追加.
g.E().hasLabel('friend').property('relation', 1.0).toSet()
# 頂点をから端を取得して追加.
# outではなく、outEで.
g.V(gremlin1).outE('friend').property('date', '20180206').toSet()

# 端に追加したpropertyの参照
friend = g.E().hasLabel('friend').next()
g.E(friend).valueMap().toList()
# 以下のようなデータを取得.
# -> [{u'date': u'20180206', u'relation': 1.0}]
```

一通りの追加と参照を実施してみましたが、
Gremlinには、他にも有用な取得方法が用意されていますので、一読ください。

[Gremlin traversal](http://tinkerpop.apache.org/docs/3.3.0/reference/#traversal)


東京リージョンに [Amazon Neptune](https://aws.amazon.com/jp/neptune/) がきてくれるはず！と期待しています！
ニコニコ静画の画像をオリジナルサイズで保存するRubyスクリプト

# スクリプトを書いた動機
ニコニコ静画に投稿されている画像を、コマンド一発で保存したかった。
調べてみると、APIがあるみたいなんだけど、保存できる画像サイズが小さくなってしまう。
投稿されているオリジナルサイズの画像を保存したかったので、自分でコードを書いてみました。

# スクリプトコード
```ruby:nico_seiga_dl.rb
#!/usr/bin/env ruby

require "nokogiri"
require 'mechanize'

LOGIN = 'https://secure.nicovideo.jp/secure/login?site=niconico'
agent = Mechanize.new

mail = "mailaddress" #write your mailaddress of niconico account
pass = "password" #write your password of niconico account
agent.post(LOGIN, 'mail' => mail, 'password' => pass)

id = 961724
sourceURL = "http://seiga.nicovideo.jp/image/source/"

url = sourceURL + id.to_s
data = agent.get(url)

doc = Nokogiri::HTML.parse(data.body)
illust = doc.css("div.illust_view_big")
img_src = illust.css("img").attr("src")
img_URL = "http://lohas.nicoseiga.jp" + img_src.to_s
title = doc.title.split
p title
`wget -O #{title[0]}.jpg -nc #{img_URL}`
```

# 処理の概要
大雑把に書くと、「オリジナルサイズの画像のURLを取得し、wgetで保存する」、というものです。この、オリジナルサイズの画像のURLは、
`http://lohas.nicoseiga.jp/priv/(複雑な文字列)`
となっており、画像のID（im〜、と、画像に付けられているもの。画像の青枠部分）では、このURLを取得することが出来ません。

![niko_seiga.png](https://qiita-image-store.s3.amazonaws.com/0/189330/ab9824a2-f7a7-4079-d9b4-271b0ff91496.png)

そこで、
`http://seiga.nicovideo.jp/image/source/(idの数字)`
にアクセスし、オリジナルサイズの画像のURLを取得します。ニコニコ静画の認証をパスしなければHTML文書を取得できないため、mechanizeを使用してアクセスを行い、取得したHTML文書をnokogiriでパースして、URLを取り出します。