OmniAICreator/Qiita-1.07M huggingface dataset:
Firebaseの新しいUnity SDKのサンプルを一通り試してみる


2016/11/14のFirebaseのブログ記事[Announcing Firebase for Unity](https://firebase.googleblog.com/2016/11/announcing-firebase-for-unity.html)にある通り、FirebaseのUnity SDKが新しくなったので導入して確かめてみます。

サンプルコードは[firebase/quickstart-unity](https://github.com/firebase/quickstart-unity)にあるのでcloneしておきます。

# 環境

* Unity 5.4.3f1

# Firebase Analytics

まずは[Analytics](https://github.com/firebase/quickstart-unity/tree/master/analytics/testapp)から行います。Readmeの **Building the Sample** をみながらセットアップします。

UnityでOpen Projectで該当のプロジェクトを開きます。以下のようなエラーがでると思いますが、パッケージをインポートすればいいのでひとまず無視します。

![image](https://qiita-image-store.s3.amazonaws.com/0/30079/5eca7493-4441-b41f-e278-3370321b924e.png)

[Firebas Unity SDK](https://firebase.google.com/download/unity)をダウンロードして、展開します。
展開後、```FirebaseAnalytics.unitypackage```を開きます。

Firebaseの設定ファイルである```GoogleService-Info```をfirebaseからダウンロードし、Unityのプロジェクトに配置します。

Unity上でエラーがでなくなったら、MainSceneを開いて実行します。以下のような画面がでれば大丈夫です。

![image](https://qiita-image-store.s3.amazonaws.com/0/30079/c9264ec1-48ac-3507-95ce-42e747ab0f17.png)

Editor上で動きが確かめられたら、iOS上でビルドし確認してみます。iOSにプラットフォームを変更し、ビルドします。Firebaseの設定のGoogleService-InfoによってはBundle IDの変更の確認があると思いますが、変更しそのまま進みます。

Xcode上でTargetのBuild SettingsのDevelopment Teamを正しく設定して、実機にインストールされるか確かめます。
Logボタンを押したときにXcode上でログがでていれば大丈夫です。

**ほかはだいたい手順同じなので省略**


# 注意
* 実際の機能は実機にいれないと動かないものが多いです

# 参考
* [Firebase Analytics Quickstart](https://github.com/firebase/quickstart-unity/tree/master/analytics/testapp)
* [Firebase Quickstarts for iOS](https://github.com/firebase/quickstart-ios)
[メモ] LLVM

- 自分のメモも兼ねて、LLVMのAPI(C++)についてまとめていきます。
- LLVM 3.5 での話です(古い
- **順次更新中**

# コンパイル
- Ubuntu, Debian の場合は``apt-get``で以下を実行 (コンパイルするだけなら``opt``とかいらないかな)

```bash
$ apt-get install clang-3.5 clang-3.5-doc libclang-common-3.5-dev libclang-3.5-dev libclang1-3.5 libclang1-3.5-dbg libllvm3.5v5 libllvm3.5-dbg lldb-3.5 llvm-3.5 llvm-3.5-dev llvm-3.5-doc llvm-3.5-examples llvm-3.5-runtime clang-modernize-3.5 clang-format-3.5 python-clang-3.5 lldb-3.5-dev opt libedit-dev
```

- ``source.cpp`` をコンパイル (llvm-config のオプションは適当)

```bash
$ clang++-3.5 source.cpp -o source -std=c++11 `llvm-config-3.5 --system-libs --cppflags --ldflags --libs all`
```

# 関数生成

- こんな感じの、特に何もしない関数を作っていきます

```c
int func(char *s) {
  return 0;
}
```

## プロトタイプ
- 戻り値が``int``, 引数が ``char *`` の ``func``という名前の関数のプロトタイプを作る

```cpp
#include "llvm/Analysis/Passes.h"
#include "llvm/IR/Verifier.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/PassManager.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

llvm::LLVMContext &context(llvm::getGlobalContext());
llvm::IRBuilder<> builder(context);
llvm::Module *mod;


int main() {
  // Moduleを作る
  mod = new llvm::Module("sample", context);

  // 関数の名前
  std::string func_name = "func";
  // 戻り値の型
  llvm::Type *func_ret_type = builder.getInt32Ty();
  // 引数の型
  std::vector<llvm::Type *> func_args_type;
  func_args_type.push_back(builder.getInt8Ty()->getPointerTo());

  llvm::FunctionType *llvm_func_type =
    llvm::FunctionType::get(func_ret_type, func_args_type, /*可変長引数=*/false);
  llvm::Function *llvm_func = llvm::Function::Create(llvm_func_type, llvm::Function::ExternalLinkage, func_name, mod);

  llvm_func->dump(); // 作った関数を表示 (LLVM-IR)
}
```

- ちょっと補足
- ``builder.getXXX`` で型を得られますが

```cpp
builder.getInt8Ty()
builder.getInt16Ty()
builder.getIntNTy()
```
- とか、ある程度規則的に名前が付いているのでわかりやすいと思います
- あと、``getPointerTo`` はその名の通り、その型のポインタを得られるようです
- 8ビットの整数に限り、（多分よく使うから）``getInt8PtrTy()``ってのも用意されてます

```cpp
// int *
builder.getInt32Ty()->getPointerTo()
// char **
builder.getInt8Ty()->getPointerTo()->getPointerTo()
builder.getInt8PtrTy()->getPointerTo()
```


## 本体
- 次に、関数の本体を作る
- 特に何もしないで、``0``を返してみます
- ``create_func_body``という関数を作ってその中で処理させましょうか

```cpp
// 省略
void create_func_body(llvm::Function *llvm_func) {
  llvm::BasicBlock *entry = llvm::BasicBlock::Create(
      context, 
      "entry", // BasicBlockの名前 
      llvm_func);
  builder.SetInsertPoint(entry); // entryの開始
  builder.CreateRet( // return
      llvm::ConstantInt::get(builder.getInt32Ty(), 0, true) // i32 0
      );
}
```

- 一つのBasicBlockに、一つの return があります。``void``を返す？関数なら``CreateRetVoid``を使います
【UIScrollView】Autolayoutで縦スクロール【Xcode8.x】

## 1.作業領域の拡大
まずは作業しやすいように枠の縦を伸ばします。simulated sizeを「freeform」にして、heightを設定。今回はiPhone6sの枠を下地に使ってます。 
<img width="1000" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/151314/468d82e0-3138-37f5-9ebd-9683473b7967.png">

## 2.ScrollViewの設定
pinで画面いっぱいになるように制約付けします。 
<img width="1011" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/151314/6013ab7a-ed4a-2bff-0cd7-4cae83408cc1.png">

## 3.コンテンツビューの設定
ScrollViewの上にviewを置きます。このView（FormView）がcontentSizeになります。四方のマージンをpinで、「高さ」の制約を固定値で設定し、FormViewとViewの横幅を「＝」にします（③）。**スクロール方向に固定値を与える**というのがコツです。高さは後で微調整すればOK。
<img width="1192" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/151314/862513f2-ddd2-58d0-faeb-d5a6d6bb8d61.png">

## 4.コンテンツビューに部品を配置
後は普通にFormViewにに部品を配置していきます。 
<img width="1413" alt="4.png" src="https://qiita-image-store.s3.amazonaws.com/0/151314/0e8f3999-8bac-2cac-88bd-aa6858dbc69f.png">

## 5.完成！
iPhone6s simulatorで実行
![sample.gif](https://qiita-image-store.s3.amazonaws.com/0/151314/ef540ac2-3831-e01d-c6b5-b7f16426d22b.gif)

###### [横スクロールはこちら](http://qiita.com/fromage-blanc/items/0abbeb6c0d0c2ad1de29)
IEqualityComparerが面倒という話

LINQでまれに使うことのあるIEqualityComparerだが、
いちいちクラスを定義するのが面倒なので、
とりあえず、諸々の責任は放棄したこんなクラスでもあれば、概ねはどうにかなると思う。

```csharp:GenericEqualityComparer.cs
public class GenericEqualityComparer<T> : IEqualityComparer<T>
{
	private Func<T, T, bool> _predicate;
	private Func<T, int> _gethash;

	public GenericEqualityComparer(Func<T, T, bool> predicate)
		: this(predicate, obj => obj.GetHashCode())
	{
	}
	public GenericEqualityComparer(Func<T, T, bool> predicate, Func<T, int> gethash)
	{
		_predicate = predicate;
		_gethash = gethash;
	}

	public bool Equals(T x, T y)
	{
		return _predicate(x, y);
	}
	public int GetHashCode(T obj)
	{
		return _gethash(obj);
	}
}
```
Windows ServerでChef-solo実行したことその２(サービスの自動無効化)

#Chef-soloに関するなぐり書き

##前提
◆Chef-repo配下にsolo.rbというファイルがあって、
中に各レシピまでのパスが通っていること。
(例：cookbook_path ["C:/Users/Administrator/chef-repo/cookbooks"])
※Windowsの場合はここのパスは\(円マーク)ではなく/

◆私の場合は、solo.rbがchef-repo配下、
JSONファイルがchef-repo/nodes配下にあります(それにより実行文変わる)

◆Windows server環境下でchef-soloを実行するまでは[ここ](http://qiita.com/E_M/items/403e11e0c637cd28ba1d)を見てください。

###トライその2.サービスを自動無効化する
1.クックブックを作成する
(今回は**Print Spooler**というサービスでクックブック名はspooler)

```
(ディレクトリはchef-repo)
> knife cookbook create spooler -o cookbooks
```

2.spoolerの中のrecipesの中のdefault.rbに追記

```
service "Spooler" do
  action :disable
end
```

3.nodes配下にJSONファイルを作成(今回はspooler.json)→編集

```
{
    "run_list": [
      "recipe[spooler]"
    ]
}
```

4.実行

```
> chef-solo -c solo.rb -j nodes/spooler.json
```

5.確認
サーバマネージャ→ツール→サービスから「Print Spooler」を探して
[スタートアップの種類]が無効になっていることを確認。
Groovy で AST 変換 III: Tips など

## AST 変換 Tips

### `ClassNode` 生成時は `ClassHelper` を使おう

コンストラクタや static なメソッドを呼び出す式に対応する AST を作ろうとすると、クラスを表す `ClassNode` オブジェクトが必要になりますが、このときにコンストラクタを呼び出すのは推奨されていないようです。代わりに、`ClassHelper` クラスの `make` メソッドを用いましょう。

例えば、`String` クラスを表す `ClassHelper` メソッドを用いるときには以下のようにします。

```groovy
ClassNode type = ClassHelper.make(String)
```

与えられたクラス名から `ClassNode` オブジェクトを得たいときは、以下のようになります。

```groovy
String typeName = "java.lang.String"
Class clazz = Class.forName(typeName)
ClassNode type = ClassHelper.make(clazz)
```

ちなみに、`make` メソッドは `String` を受け取るものと `Class` を受け取るものがありますが、`String` を受け取る方を用いるとエラーが発生することがあったので、`Class` を受け取る方を使ったほうが無難だと思います。

### 配列を表す `ClassNode`

`ClassNode` クラスの `makeArray` メソッドを使うと、そのクラスの配列を表す `ClassNode` オブジェクトが生成できます。便利です。

逆に、配列を表す `ClassNode` からその配列の成分のクラスを取得したい場合は、`getComponentType` メソッドが使えます。例えば、`String[]` を表す `ClassNode` に `getComponentType` メソッドを呼ぶと、`String` を表す `ClassNode` が返されます。

なお、多次元配列に対して `getComponentType` を呼ぶと次元が 1 つ落ちたものが返ってきます。例えば、`String[][]` を表す `ClassNode` に対しては `String[]` を表す `ClassNode` が返ってきます。一気に配列でないクラスを取得したい場合は、以下のようにすると良いでしょう。

```groovy
ClassNode componentType = type
while (componentType.isArray()) {
  componentType = componentType.getComponentType()
}
```

### `Variable` の `accessedVariable` プロパティ

変数を表現する AST は `Variable` クラスで管理されます。ソースコード中に現れる変数は全て `Variable` オブジェクトになります。このとき、コード上の違う場所に書かれた変数は異なる `Variable` オブジェクトになります (`lineNumber` などが別々なので当然と言えば当然ですが)。一方、`Variable` クラスは `accessedVariable` というプロパティ (`VariableExpression` 型) をもっているのですが、これは同じ変数を表していれば同一のオブジェクトになります。

例えば、以下のようなコードを考えてみます。

```groovy
if (true) {
  int a = 2  // (1)
  a += 3     // (2)
  a = 7      // (3)
} else {
  int a = 9  // (4)
  a += 8     // (5)
}
```

「a」という名前の変数が 5 ヶ所現れていますが、これらは AST に変換されると `Variable` オブジェクトとしては別物です。ここで、(1), (2), (3) の `a` は同じ変数を表していますが、これとは別のスコープにある (4), (5) とは名前は同じでも別の変数です。したがって、各 `Variable` オブジェクトの `accessedVariable` プロパティを見てみると、(1), (2), (3) に対応するものは全て同一 (参照が同じ) の `VariableExpression` オブジェクトになっていて、(4), (5) に対応するものとは別の (参照が異なる) オブジェクトになっています。

変数の値を操作する AST を作る場合は、この辺にも注意する必要がありそうですね。

## このシリーズ

- [Groovy で AST 変換 I: AST 変換を作ってみよう](http://qiita.com/Ziphil/items/680b63b2d31aa952e1c2)
- [Groovy で AST 変換 II: GroovyConsole の使い方](http://qiita.com/Ziphil/items/05d6b60ae41c03206022)
- Groovy で AST 変換 III: Tips など
CloudFrontに独自のSSL証明書をアップする

#CloudFrontに独自のSSL証明書をアップする際につまずいたこと･･･

今更ながらですが、先日CroudFrontに独自のSSL証明書をアップする際につまずいたので、今後のために記録を残しておこうと思う。

今まで、ELBにしか証明書を適用したことがなかった私は、CloudFrontの場合でも
「AWSコンソールの画面からできるっしょ！」
とか思っていたのですが･･･
なんということでしょう。調べてみるとAWS-CLI経由でないとできないと記載があるではないですか。

##ではAWS-CLI経由で証明書をアップしてみよう
色々調べてみると

```
aws iam upload-server-certificate \
--server-certificate-name <任意のサーバ証明書識別名> \
--certificate-body file://<証明書> \
--private-key file://<秘密鍵> \
--certificate-chain file://<中間証明書> \
--path /cloudfront/
```

というコマンドをたたけばいいらしい。
ここでつまずいたことは、
1.「file://」は書かないといけないよ
2. CloudFrontで使うときは「--path /cloudfront/」を書かないといけないよ
3. 識別名はELBで使っているのも含めてまだ使ってない名前にしないといけないよ
4. 改行せずに一行でコマンドを書いたほうがいいよ
5. IAMの権限がいるよ
といった点でした。「Pem形式か確認しろ！」などといったエラー文に惑わされて時間を使ってしまった･･･
無事アップしたあと、コンソール画面からCloudFrontに証明書を適用することができた。

##ELBにも同じ証明書を適用しようね
無事にCloudFrontにSSL証明書を適用して、CloudFront経由でS3のimageファイルをSSLで見に行くようにできましたが、次はそのimageファイルを表示するWeb画面がおかしい。画像がリンク切れしている･･･
Web画面はELBに証明書を適用しているのですが、その証明書とCloudFrontの証明書が違ったから怒られていた。
ELBの証明証明書をCloudFrontに適用している証明書と同じものにした。無事画像が表示された。
同じ証明書を適用したほうが無難なのだろうか？それとも単純にCloudFrontがキャッシュしていたのだろうか？
このあたりに詳しい方がおられたらご教授していただけるとありがたいです･･･
また、今の証明書の期限切れが迫ってきたら同じ作業をしないといけないので、覚えているうちに書いておこうと思い、書いてみた。

##こうならないためにも
独自のSSL証明書ではなくACM（Amazon Certificate Manager）を使うべきかと思う。
ACMは無料だし、更新もいらないし、取得するの簡単だし、適用するのも簡単な証明書。
ただ、CloudFrontで証明書を使う場合は北バージニアでACMを取得しないといけないので、今回のように、ELBにも同じ証明書を使わないといけない場合は、ELBを北バージニアで立てないといけないようなので、レイテンシーの問題がある。来年の更新時には東京リージョンでもCloudFrontでACMを使えるようになっていることを願っている。
auditdで特定のsyscallとexit (errno) の組み合わせを無視する

以前auditdでLinuxのファイル改竄検知をやりたくて、こんなのを書いた。
[auditdでLinuxのファイル改竄検知を行う](http://qiita.com/minamijoyo/items/0d77959a869e458d850a)

実際に監視してみるとノイズが色々出るので、システムコールレベルで監視条件をチューニングしたくなった。
例えば以下のようなメッセージを無視したい。ちょっと見づらいので改行してるが、実際には1行です。

```
Nov 25 11:45:01 myhost audispd: 
node=myhost type=SYSCALL msg=audit(1480041901.111:5431): 
arch=c000003e syscall=83 success=no exit=-17 
a0=7ffc046bdb7a a1=1ff a2=7ffc046bc750 a3=7ffc046bc1e0 items=1 
ppid=17266 pid=17276 auid=502 uid=502 gid=501 euid=502 suid=502 fsuid=502 egid=501 sgid=501 fsgid=501 
tty=(none) ses=318 comm="mkdir" exe="/bin/mkdir" key="file_changes"
```

# 検証環境

```
# cat /etc/system-release
Amazon Linux AMI release 2016.09
# uname -a
Linux myhost 4.4.30-32.54.amzn1.x86_64 #1 SMP Thu Nov 10 15:52:05 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
```

# syscall番号を調べる
問題のsyscallが何なのか調べます。

```
# ausyscall 83
mkdir
```

mkdirのようです。

念のためアーキテクチャを指定して逆向け引いてみます。

```
# ausyscall i386 mkdir
mkdir              39
mkdirat            296

# ausyscall x86_64 mkdir
mkdir              83
mkdirat            258
```

ログに出ているarch=c000003eのアーキテクチャはx86_64を表しているよう。

# exit番号の意味を調べる
exitに出てるのはLinuxのerrnoです。
includeファイルがどこにあるかはディストリビューションによります。AmazonLinux2016.09だとこの辺にあった。

```
# grep -e '\<17\>' /usr/include/asm-generic/errno*.h
/usr/include/asm-generic/errno-base.h:#define   EEXIST          17      /* File exists */
```

これはmkdirで既に存在してますなので、実害ないので無視して良さそう。

# audit.rulesで除外指定する

/etc/audit/audit.rulesに以下の条件を追記します。
※exitの値はsuccess=noの場合はマイナス、success=yesの場合はプラスで指定することに注意。

```/etc/audit/audit.rules
-a exit,never -F arch=b64 -S mkdir -F exit=-17 -k exclude
```

反映するためにauditdを再起動

```
# service auditd restart
```

# (2016/12/12追記) ausearchによる名前解決
サーバ上にauditdのログがある状態であれば `ausearch` コマンドに `--interpret` を付けるとシステムコール名やexit番号をよしなに名前解決してくれることに気付いた。

イメージこんな感じになる。

```
# ausearch --interpret --exit -13
type=PATH msg=audit(2016年12月12日 13:31:58.507:17283877) : item=2 name=(null) inode=394973 dev=ca:01 mode=file,644 ouid=root ogid=root rdev=00:00 nametype=NORMAL
type=PATH msg=audit(2016年12月12日 13:31:58.507:17283877) : item=1 name=(null) inode=394973 dev=ca:01 mode=file,644 ouid=root ogid=root rdev=00:00 nametype=NORMAL
type=PATH msg=audit(2016年12月12日 13:31:58.507:17283877) : item=0 name=XXXXXXXXXXX inode=394972 dev=ca:01 mode=dir,755 ouid=root ogid=root rdev=00:00 nametype=PARENT
type=CWD msg=audit(2016年12月12日 13:31:58.507:17283877) :  cwd=XXXXXXXXXXXXXXXXXXXX
type=SYSCALL msg=audit(2016年12月12日 13:31:58.507:17283877) : arch=x86_64 syscall=open success=no exit=-13(許可がありません) a0=0x18e1540 a1=O_RDWR|O_CREAT|O_CLOEXEC a2=0644 a3=0x100 items=3 ppid=1776 pid=1849 ... (略)
```

ログの一番最後のところなんだけど
`syscall=open success=no exit=-13(許可がありません)` ってなってて名前解決されてる。
第6回つぶやき勉強会 ~JSと仲良くなろうの会~

### Q1

jQueryの `$` は次のうちどれですか？

- a. 関数 
- b. オブジェクト
- c. それ以外

----

### Q2

コンソールで `$.hoge` をすると undefined になります。

```js
$.hoge = "piyo";
```

上記以外の方法で、`$.hoge` が piyo となるようにせよ。

----

### Q3

```js
// 任意の要素 any に対して、（any は div, span...など)
$('any').hoge // => piyo
```

上を実現せよ。
（ヒント: `$('div').__proto__` )

----

### Q4

```rb
class Person
  def initialize(name)
    @name = name
  end
  def greet
    "My name is #{@name}"
  end
end

person = Person.new("Shiraki")
person.greet # => "My name is Shiraki"
```

上と同じようなことを JavaScript でやってみてください。
    
----
### Q5

ここにオブジェクト obj があります。
obj が、jQueryオブジェクトか否かを判別する方法を示せ。
( jQuery 自体は読み込まれているとする。 )

----

### Q6

```js
var piyo = 9;
hoge = function(){
  console.log(piyo);
  var piyo = 1;
}

hoge() // => これはなんですか？
```

----
### 答え

1. 関数, オブジェクト 
2. $.extend({hoge: "piyo"}) 
3. $.fn.extend({hoge: "piyo"})
4. 別紙
5. obj instanceof jQuery
6. undefined

- 2の別  $["hoge"] = "piyo";

----

### 4の答え

```js
function Person(name){
  this.name = name
  this.greet = function(){ 
                 return "My name is " + this.name
               }
}
person = new Person("Shiraki");
person.greet(); // => "My name is Shiraki"
```

----

# 以上。ありがとうございました。 :earth_africa:
DynamicsCRM 2016 基本プラグインの作成（Step by Step）

Dynamics CRM 2016プラグインの作成手順を説明する目的で、Microsoftのサンプルソースを使って基本プラグインを作成してみます。

##前提条件
・Dynamics CRM 2016 online版 または、On-Premises版
・Visual Studio 2012 または Visual Studio 2015
・Dynamics CRM 2016 SDK　[ダウンロード](http://https://www.microsoft.com/ja-JP/download/details.aspx?id=50032)

##詳細手順
###１．Visual Stduioで新規プロジェクト（テンプレート⇒Visual C# ⇒ クラスライブラリ）
![2016-11-28_131800.png](https://qiita-image-store.s3.amazonaws.com/0/123138/99066eda-2447-857f-90df-9a7be8e7ab78.png)

###２．必要のDLLの追加
![2016-11-28_132020.jpg](https://qiita-image-store.s3.amazonaws.com/0/123138/6eaa8f52-a907-e405-1833-ba429191b020.jpeg)
アセンブリのフレームワークから以下のDLLを追加する。
・System.ServiceModel.dll
![2016-11-28_132219.png](https://qiita-image-store.s3.amazonaws.com/0/123138/49478bbe-629f-43b2-76d0-bdd459a9734e.png)

SDK\Bin\配下から以下のDLLを参照に追加する。
・Microsoft.Xrm.Sdk.dll
・Microsoft.Crm.Sdk.Proxy.dll
![2016-11-28_141910.jpg](https://qiita-image-store.s3.amazonaws.com/0/123138/9c965194-0f42-c1ca-5f81-50f666d0263d.jpeg)

###３．ソースコードの作成
SDK\SampleCode\CS\Plug-ins配下のFollowupPlugin.csの内容をVisual Studio プロジェクトのClass1.csにコピーする。
![2016-11-28_142245.png](https://qiita-image-store.s3.amazonaws.com/0/123138/c2085824-3527-7324-9760-cf26a7855dbe.png)

###４．KeyFileの作成
プラグインを登録するために、アセンブリに署名する必要があります。プロジェクトを右クリックしてプロパティをクリックし、署名タグを選択する。
![2016-11-28_133010.jpg](https://qiita-image-store.s3.amazonaws.com/0/123138/c495b78f-9d1f-e474-eb28-7cedf560781e.jpeg)

KeyFile情報を入力し、署名タグを保存する。
![2016-11-28_132924.png](https://qiita-image-store.s3.amazonaws.com/0/123138/a37ffff8-cae9-fd55-6576-224a1b60f93e.png)

###４．プロジェクトのビルド
![2016-11-28_143301.jpg](https://qiita-image-store.s3.amazonaws.com/0/123138/ef3c08f8-df83-58b7-171c-045158930992.jpeg)
ビルド成功したことを確認する。
![2016-11-28_132608.jpg](https://qiita-image-store.s3.amazonaws.com/0/123138/4e91d19d-e899-a653-9220-ef6514788357.jpeg)

###５．プラグインの登録
SDK\Tools\PluginRegistration配下のPluginRegistration.exeを実行し、Dynamics CRM 2016サーバに接続する。
![2016-11-28_133033.png](https://qiita-image-store.s3.amazonaws.com/0/123138/104b2b79-d575-7111-ceea-1a39ff65895c.png)

アセンブリ（Projects\FollowupPlugin\FollowupPlugin\bin\Debug\FollowupPlugin.dll）を登録する。
![2016-11-28_144150.png](https://qiita-image-store.s3.amazonaws.com/0/123138/3fff8df2-a0d5-5cc4-ffed-ddb581419207.png)

手順（Step）を新規作成したら、プラグインの登録が完了です。
![2016-11-28_133640.png](https://qiita-image-store.s3.amazonaws.com/0/123138/04dfa123-d2ce-2fae-7288-e25f4966a55d.png)
※手順は、プラグインの実行方法とタイミングを構成するために使用される SDK メッセージ処理手順エンティティを示します。

###５．動作確認
取引先企業を新規作成する。
![2016-11-28_133840.png](https://qiita-image-store.s3.amazonaws.com/0/123138/be88aac8-eb37-db7d-8395-2c6d7e30c8c1.png)
[活動]をクリックして、取引先企業に関連する活動の一覧を表示する。
![2016-11-28_133955.png](https://qiita-image-store.s3.amazonaws.com/0/123138/27b868f1-66fc-31d0-7fcd-afeb4c0ae3ff.png)

参照先：
https://msdn.microsoft.com/ja-jp/library/gg594416.aspx  （サンプル: 基本プラグインの作成）
https://msdn.microsoft.com/ja-jp/library/gg309580.aspx  （チュートリアル: プラグイン登録ツールを使用したプラグインの登録）
Pythonでさくっとエクセルファイルの作成 #python

即席でメモ程度のエクセルファイルをさくっと用意したい人のために、エクセルファイルを作成するコードを書きました。

エクセルを扱うライブラリのインストール

```text:terminal
 pip install xlsxwriter
```

実装

```py:sample.py
# -*- coding: utf-8 -*- 

import xlsxwriter

workbook = xlsxwriter.Workbook('sample.xlsx')
worksheet = workbook.add_worksheet()

worksheet.set_column('A:A', 20)

worksheet.write('A1', u'メモ')
worksheet.write('A2', u'メモ)
worksheet.write('A3', u'メモメモ')

worksheet.insert_image('C1', 'image1.jpg', {'x_scale': 0.03, 'y_scale': 0.03})

workbook.close()
```

画像によっては画像が大きくなることがあるのでスケールで調整します。

```py:sample.py
{'x_scale': 0.03, 'y_scale': 0.03}
```
Android Studioで、productFlavorsを使う場合は小文字を使う

設定ファイル：build.gradle(Module:app)など。

#productFlavorsを使う場合は小文字を使う
一見、大文字でも制限が無いように見えますが・・・

##dependenciesの、xxxCompile(xxxはフレーバー名)は、(フレーバー名の先頭が)大文字だと反応しない。
ここで困ります。
(おそらく、フレーバー名の途中に大文字が混ざっていても、単語の区切り扱いされて、正しく反応しないと思います。)

##そんなの使わない？
いえ、すぐに必要になるのです。
※API14未満(実質的にAndroid 2.3.x (API9～10))を動作対象とする場合。

Google Play Services (Google開発者サービス)の動作対象
10.0.0まで：API9以上
10.2.0以降：API14以上
※ただし、ver10.0.0は、Android 2.3.xの端末ではダウンロードできない模様。
(Android 2.3.4 (API10)の実機で試した所、2016/11/28現在、ダウンロード可能なのは9.8.x。)

この対策で、API14未満を動作対象にする場合は、
dependenciesに、xxxCompileを指定する必要性が出てきます。
書き方は、参考2の「2. Build multiple APKs to support devices with an API level less than 14.」を参照で。


#参考1
http://stackoverflow.com/questions/18196974/how-to-define-different-dependencies-for-different-product-flavors
コメント欄から引用：
> Note that the xxxCompile closures Gradle generates will not work if the flavor name starts with a capital letter. – Jarett Millard Jan 21 '15 at 17:44 

訳：xxxCompileは、flavor名の先頭が大文字だと反応しないよ！

#参考2 Google Play services and Firebase for Android will support API level 14 at minimum 
https://android-developers.blogspot.jp/2016/11/google-play-services-and-firebase-for-android-will-support-api-level-14-at-minimum.html
> Version 10.0.0 of the Google Play services client libraries, as well as the Firebase client libraries for Android, will be the last version of these libraries that support Android API level 9 (Android 2.3, Gingerbread). The next scheduled release of these libraries, version 10.2.0, will increase the minimum supported API level from 9 to 14 (Android 4.0.1, Ice Cream Sandwich). This change will happen in early 2017.
Cognos監査ログの削除メンテナンスについて

Cognosの監査ログ削除メンテナンスについて、Cognos Analyticsで変わったところに気がつきましたので情報共有しておきます。

Cognos BIで監査ログを設定している環境では、監査DBの容量が永遠に増大していってしまい、製品としての自動的に消しこみの機能は提供されていないため、メンテナンスのため、各監査テーブルにSQL文でDELETEを投げる運用を手作りで実装します。

Cognos BI 10.2.2までのこの点に関する参考情報としては、以下の2つのTechnoteが参考にされていたと思います。

【監査データベースのレコード削除について】
http://www-01.ibm.com/support/docview.wss?uid=swg21452461

【IBM Cognos BI AuditDBCleanup】
http://www-01.ibm.com/support/docview.wss?uid=swg24036642

この中で、COGIPF_PARAMETER表に関しては、TIMESTAMPの列が無かったため、他の表とJOINするなど面倒くさい消しこみをしていたと思いますが、Cognos Analyticsになって、この表にTIMESTAMPの列が追加されたようです。

![image](https://qiita-image-store.s3.amazonaws.com/0/147246/ad8579fd-99b0-5d33-b99a-c4f68db4cfb0.png)


【Knowleadge Center: COGIPF_PARAMETER Table】
http://www.ibm.com/support/knowledgecenter/SSEP7J_11.0.0/com.ibm.swg.ba.cognos.ug_cra.doc/c_asg_cogipf_parameter.html

これで普通に全テーブルにCOGIPF_LOCALTIMESTAMP指定でのDELETE文を発行すれば良いだけになった様で、少し実装が楽になりましたね、という情報です。
Unity5でビルドしたアプリをAdrenoProfilerを使ってプロファイルする方法-導入編-

# はじめに
Unity5のプロファイラも十分に使うことは可能ではあるものの、もっと詳細に、特にRender周りで調べたい場合にAdrenoを使うと非常に役に立つ。ここではWindows環境+AndroidアプリでのAdrenoの導入から接続までの方法を簡単にまとめる。

# Adrenoの導入
以下のサイトから入手できます
（※アカウントの登録が必要です）
ttps://developer.qualcomm.com/download/software

Software DownloadsのページでProfilersの項目から使用するOSに合ったAdrenoを選択しダウンロードします。
その後、インストーラーを起動すれば完了です。

### Adrenoに必要な環境
WindowsであればWin7以降であればOK。
AndroidSDK(ADK)が必要です。またADKの特定のパスを環境変数に設定する必要があります。(ミスがあるとConnectionがうまくいきません)
パスは以下のように設定します。

```
C:\ADK\r24.4.1\tools;C:\ADK\r24.4.1\platform-tools
```

# アプリの設定
Adrenoの設定が完了したら、\Plugins\Android\AndroidManifest.xmlに変更を加え再度ビルドします。

```
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.qti.permission.PROFILER" />
```

#Adrenoと接続
Adrenoと接続する前に以下のコマンドを実行する(OS起動ごとに1回だけやればOK)

```
adb.exe shell setprop debug.egl.profiler 1
```

※adb.exeについての解説はここでは省略します。

アプリをAndroidにインストールした後、アプリを起動しAdrenoを立ち上げConnectを選択。
表示される接続先に起動しているAndroidが認識されていれば成功。
VPTEST(整数)とVTESTPD(実数)の動作の違い

# はじめに

AVXのビットテストは、整数版(VPTEST)と実数版(VTESTPD)があって、動作が異なる。ちょっと混乱するので覚書。ビットテストはZF、CFの双方に影響するが、以下ZFの振る舞いのみについて記述する。

# 整数版(VPTEST)

整数版のVPTESTは、全ビットに対してANDをかける。全ビットのANDがゼロならZFが立ち、そうでなければZFはクリアされる。対応する組み込み関数は`_mm256_testz_si256`。これはZFが立っていたら1を、そうでなければ0を返す。[^1]

要するに、純粋に256ビットのANDだと思えば良い。以下、いくつか例示。


* 要素ごとのANDが全て0なら1

```cpp
  __m256i v1 = _mm256_set_epi32(0,1,2,4,8,16,32,64);
  __m256i v2 = _mm256_set_epi32(1,2,4,8,16,32,64,128);
  std::cout << _mm256_testz_si256(v1,v2) << std::endl;
  // => 1
```

*  要素ごとのANDが一つでも非ゼロなら0

```cpp
  __m256i v1 = _mm256_set_epi32(0,1,2,4,8,16,32,64);
  __m256i v2 = _mm256_set_epi32(1,1,4,8,16,32,64,128);
  std::cout << _mm256_testz_si256(v1,v2) << std::endl;
  // => 0
```

* 同じ値でも0

```cpp
  __m256i v1 = _mm256_set_epi32(0,1,2,3,4,5,6,7);
  __m256i v2 = _mm256_set_epi32(0,1,2,3,4,5,6,8);
  std::cout << _mm256_testz_si256(v1,v2) << std::endl;
  // => 0
```

なので、例えば`mm256_testz_si256(v1,v1)`で、YMMレジスタが全てゼロであるかどうかを調べたり、(本質的に同じことだが)`mm256_testz_si256(v1-v2,v1-v2)`で二つのYMMレジスタが全く同じ値をもっているかどうかを調べることができる。

# 実数版(VTESTPD)

整数版が「全てのbitのAND」をとっていたのに対して、実数版は「符号ビット」にのみ作用する。図解するまでもないが、こんな感じ。

![vptest.png](https://qiita-image-store.s3.amazonaws.com/0/79744/12c8252b-30eb-ed9c-bb08-4ab8a518f090.png)

YMMレジスタを食わせた場合は、4つの要素の符号ベクトルのみを集めた4bitの値を作って、それにANDをかけて、ゼロになったらZFを立て、そうでなければZFをクリアする。対応する組み込み関数は`_mm256_testz_pd`で、ZFが立っていれば1を、そうでなければ0を返す。[^1]

要するに「対応する位置の要素が同時に負であれば1、そうでなければ0」となる。以下、いくつか例示。

* 負の要素がなければ値に関わらず1

```cpp
  __m256d v1 = _mm256_set_pd(3,2,1,0);
  __m256d v2 = _mm256_set_pd(7,6,5,4);
  std::cout << _mm256_testz_pd(v1,v2) << std::endl;
  // => 1
```

* 同じ位置に負の要素があれば、値が異なっていても0

```cpp
  __m256d v1 = _mm256_set_pd(3,2,-1,0);
  __m256d v2 = _mm256_set_pd(7,6,-5,4);
  std::cout << _mm256_testz_pd(v1,v2) << std::endl;
  // => 0
```

* 負の要素の位置が異なっていれば1

```cpp
  __m256d v1 = _mm256_set_pd(3,2,-1,0);
  __m256d v2 = _mm256_set_pd(7,-6,5,4);
  std::cout << _mm256_testz_pd(v1,v2) << std::endl;
  // => 1
```

* 対応する負の要素が複数あっても0

```cpp
  __m256d v1 = _mm256_set_pd(3,-2,-1,0);
  __m256d v2 = _mm256_set_pd(7,-6,-5,4);
  std::cout << _mm256_testz_pd(v1,v2) << std::endl;
  // => 0
```

なので、第一引数と第二引数に同じベクトルを食わせると「4つの要素のうちどれか一つでも負なら0、そうでなければ1」という判定に使える。っていうかそれ以外の有効な使い方を思いつかない・・・。

# まとめ

パックド・ビット・テストは、整数版と実数版で命令が異なり、動作も異なる。特にANDPDとかORPDがビットごとにかかるのに、VTESTPDは符号ビットにしかかからないのにしばらく気づかなかったのでまとめておいた。ちゃんと読むとマニュアルに書いてあるんだけど、その書き方が

```
 IF (TEMP[63] = TEMP[127] = TEMP[191] = TEMP[255] = 0)
   THEN ZF←1;
   ELSE ZF←0;
```

みたいにさらっと書いてあったので・・・。

[^1]: 本当はZFが立っていれば非ゼロ、そうでなければ0だが、手元の環境では1を返す実装になっていた。
CakePHP3縛りのハッカソンで新着ツイート通知バッチ作ってみた

お疲れ様です。
GMOリサーチの石黒です。

先日「CakePHP3縛りのプライベートハッカソン」に参加させていただき、
1日かけて「新着ツイート通知バッチ」を作りましたので、その様子と作ったものをご紹介します。

--------------------
#① 背景と目的

- ハッシュタグ付きツイート通知できない問題
    - 勉強会の連絡などを、ハッシュタグ付きツイートで連絡してもらっているのですが、これが通知できたら便利なのになぁと考えていました。
    - 色々調べてはみたのですが、ハッシュタグ付きツイートを通知する方法が分かりませんでした。
- 「CakePHP3縛りのハッカソンやらない？」
    - やる。

そこで、ツイートを検索した結果を通知してくれるバッチをCakePHP3縛りで作ることにしました。

--------------------
#② やったこと

+ 無料でやった。
+ CakePHP3を使った。
+ PHP7 + Docker→手順忘れて断念、いつも使っているPHP5.6+vagrant環境を使った。
+ メール、Slackへ通知。
+ Bluemix、GAE→PHP5.6のインストールにたどり着けず断念。Herokuを使った。
+ Heroku Scheduler + シェルスクリプトでcronのように常に通知してくれるようにした。
+ Twitter APIと連携（仮実装として1アカウントと連携）

--------------------
#③ 作ったもの

Githubに公開しました。
https://github.com/gr-ishiguro/tweets-notifier

全体像はこんな感じです。
![image](https://qiita-image-store.s3.amazonaws.com/0/103853/34b23af4-0672-01bd-0151-8b9e825e0ea2.png)

+ Heroku Schedulerから10分に1回シェルスクリプトを実行します。（10分、1時間、1日が選べます）
+ シェルスクリプトは1分に1回CakePHPのシェルを実行します。
    + 詳細：[Herokuで1分に1回PHPを実行する](http://qiita.com/ishizuki/items/5a072d0a59411987ce7d)
+ CakepHPのシェル内でTwitter APIを利用して特定のツイートを取得します。（1アカウント180回/15分制限）
+ Slackへの通知は、Incoming WebHooksで生成したURL宛てにcurlでPOSTします。
+ メール通知は、GmailのSmtpサーバを介してメール送信をします。（2,000通/1日制限）

検索APIでは、ハッシュタグだけでなく、感情や位置情報などを検索することも可能なので、
いろいろな使い方が可能です。
それぞれの詳細は追って記事を投稿します。

--------------------
#④ ハッカソンについて

今回、初めてハッカソンというものに参加しました。
ハッカソンと言っても、かなりカジュアルなものです。

+ 会場：知り合いの家
+ 時間：朝から夜まで、休憩を入れて11時間+発表
+ 参加者：4名（1名はSkype参加）

やることは一人で黙々とプログラミング（たまに質問）なのですが、
単に家でやるのとは違い、モチベーションが格段に上がると感じました。
Slackへの通知は、時間終了2分前に完成させることができました。

それにしても、
bakeするだけで管理画面が作れたり、
composerでインストールするだけで機能を利用できたり、
連携設定するだけでAPIが利用できたりと、
無料でこれだけ沢山のことができるという事に改めて感動し、
簡単なアプリならアイデア次第で何でもできそうだと感じた、そんなハッカソンでした。
Conohaを使ってserver構築 その1

#Conohaを使ってServer構築 sshまで
EC2と違ってコンソールからIP制限ができないのでcentos側ではじくようにしていきます。
Conohaもできるようにしてくれるとうれしいなぁ
ちなみに今回は公開目的ではなく非公開でやる人むけです。
ご了承下さい。

環境
Conoha
CentOS6.7

Conohaでは専用にconsoleがありますが、私的に使いずらいのでsshでやっていきます。
数回使ったことがあるのですが、重たいし動きが悪いのでなんとかしてもらいたいですね。

##Conoha サーバー追加
ログインまで完了してしてくださいね

サーバー追加をclick

するとプランなとが出てくるので設定していきます。
タイプ:VPS
リージョン: 東京 (近いところを選択してください)
メモリ: 2GB (自分は後々を考えてたので2GB)

イメージタイプ: OS
OS: CentOS
バージョン:  6.7 (今回の話は6.*系なので)
rootパスワード: ********
(自分の自由にsshで必要になります。ただし、アルファベット大文字、小文字、数字、記号がそれぞれいるのでめんどくさい)

自動バックアップ:無効 (ほしい人は)
ディスク容量: 50GB (SSD最高！( ﾟДﾟ))
接続許可ポート IPv4: 全て許可
接続許可ポート IPv6: 全て許可
(両方とも全て許可しておいてください。じゃないと他の接続できないので)
SSH Key: 使用しない (しようしてもかないませんが解除の仕方は記載しませんので)
ネームタグ: (そのままでも問題ないのですがわかりやすくしてもOKです。)

念のために画像添付しときます！
![Conohatan.png](https://qiita-image-store.s3.amazonaws.com/0/87883/7fd75a7e-e81e-0372-45c9-86c4014bf7b5.png)

Conohaちゃんかわいい♪

構築には数分かかります。
構築が完了したら起動します。
サーバー追加の下のサーバーをクリックしてあげると作成した、サーバーがありますのでネームタグをクリックしてあげて起動！
sshでログイン

```
#ssh root@xxx.xxx.xxx.xxx
```

これでログインができたらこれで下準備は完了です。
rootパスに関してはサーバー追加のときに設定したものになります。
Raspberry Piでアコギエフェクターを作ってみた

Raspberry Pi(B+)でアコギ用のエフェクターを作ってみました。

[![YouTubeでStudioABTC検索してください](http://img.youtube.com/vi/GAQXNj2jxSg/0.jpg)](https://www.youtube.com/watch?v=GAQXNj2jxSg)

いずれ、SileShareできちんとスライドを作ります。とりあえず、メモ書きですみませんが…

機能としては下記の機能を備えています。

- エフェクター
  - 5Bandパライコ
  - コーラス
  - リバーブ
- AD/DA変換
  - 32bit/48KHz
  - 内部32bit浮動小数点(float型)
  - Cirrus Logic WM5102([Raspberry Pi用 Cirrus Logic オーディオカード](http://ssci.to/2762))
- エフェクトコントロール
  - TouchOSC(Open Sound Controlプロトコル)使用  
    参考:[h e x l e r . n e t](http://hexler.net/software/touchosc)
  - Android(Nexus13)/iOS(iPod)で動作確認

## 目的

もともと、デジタルエフェクターには興味はありました。「Raspberry Pi」で作ることにした経緯は以下の通りです。

- Linuxが載っているボードで電子工作の実績が多いことである
- エフェクトコントロールは物理的ノブでは無く、スマホ等の操作にしたかった  
  （自分のエフェクターの使い方は、家で細かく音を作り外では絶対に触らない。
  物理ノブがあると、移動時にノブが回ってしまい、いちいちセッティングし直すのもいやだった）
- 持ち歩くことを考え、消費電力の観点からPi2,Pi3ではなくB+を選択  
  メモリ使用量を見てA+の選択も視野に入れる予定
- Raspberry Pi Zeroがリソース的や取り回ししやすさから一番であるが、入手面を考えて今回は対象から外した

## ソフトウェア構成

この投稿か別投稿で図示はするつもりですが、とりあえず箇条書きで。

- ディストリビューション  
  Raspberian(JESSIE)を使用。NOOBSではなくdebootstrapでイメージを作成  
  参考:[Raspbianをdebootstrapから作る](http://qiita.com/abtc/items/862e2999d7c136201a44)
- カーネル  
  kernekl 4.4.28(PREEMPT_RTパッチは未使用。CONFIG_PREEMPT_VOLUNTARYでconfig作成)
- サウンドサーバ  
  JACK Audio Connection Kit  
  ALSAドライバ使用
- エフェクトプラグイン  
  LV2インターフェースでC++で作成
- OSCプロトコル制御、LV2プラグイン管理、Jackクライアント機能はC++で作成
- Jack、プロトコル制御、プラグインは"-march=armv6 -mfloat-abi=hard -mfpu=vfp"オプションでコンパイル

PureDataでの事例はありましたが、

- GUIレスで設定を含めて実現した
- PureDataでOSCプロトコルでエフェクトコントロールができるか疑問だった

要は、新しくPureDataを覚えたくなかったため、全てC++で作成しました。

## 性能

- JackはFrame/Period=256,Periods/Buffer=3,リアルタイムモードで実行
- レイテンシーは5ms位で演奏での遅延は感じられない 
- 使用メモリは160～180MB位でA+でも行けそうな感じ
- CPU利用率は70%弱。98KHzにはしたかったが、難しそう。もう一つくらいエフェクトは乗せられるか？

## これから着手する機能

- 電源断耐性向上  
  /var以下をOverlayFSに持っていく予定
- WIFI  
  手持ちのWIFIトングルが標準でドライバがないため、標準でドライバがあるWIFIトングル入手中
- 設定バックアップ  
  バックアップが必要なファイルはbootパーティション(FAT)へ。ファイルコピーでバックアップできるようにする。
- ハウジング
- 使用方法を含めたドキュメンt（これが一番苦手…）
一生VR上にいたいあなたのためのカジュアルなモバイルVR

#前置き
VRモードに切り替えなんてものは2016年の産物であり、
2045年には皆さんきっと脳みそ直結プラグ生活を送っていることでしょう。
しかし、今を生きる方々がそういった未来生活に適応していくには様々な障害があり、
そういった障害を解消するためには、VRモードなどという考え方を早急に捨てる必要があります。
そう、VR上が全てであると。

#概要
スマホHMDをかぶったまま生活するために必要な構成と、WebVRを駆使したデモを紹介します。

#構成

##ハードウェア
・Nexus 6P (7.0以上) 
・魚眼レンズ(238℃ぐらいのやつ) 
 https://www.amazon.co.jp/dp/B01HCJTWLY?psc=1
・視野角120°ぐらいのスマホ向けHMD (そのままだと蓋が邪魔なので切断する) 
 https://www.amazon.co.jp/dp/B01EF53DZO?psc=1
※スマホは手持ちのもので動くなら大体5000円ぐらいで試せます。

![15156884_1116670101765577_4844345366018062099_o.jpg](https://qiita-image-store.s3.amazonaws.com/0/16981/53a59315-1d69-3332-4093-ed0e97c5b72f.jpeg)

これらをこんな感じにする。

![15196077_1116669828432271_4701729507203571186_o.jpg](https://qiita-image-store.s3.amazonaws.com/0/16981/7595b316-5e4f-fba1-c38b-c62d7ab82ac9.jpeg)


##利用技術
・A-Frame https://aframe.io/
・WebRTC https://ja.wikipedia.org/wiki/WebRTC

#作り方
1. A-Frame上に球体を設置して、カメラに固定する
2. 球体にはめるテクスチャの参照先をvideoタグにする
3. videoの映像元をWebRTCを使って背面カメラから取得する
4. 球体に表示される映像が、背面カメラで撮影された視野角に合うように調整する
5. 調整した球体映像との距離感が合わない場合は、カメラの位置を調整する(近すぎるとぐにゃってなる)

#デモ
![スクリーンショット 2016-11-29 16.20.00.png](https://qiita-image-store.s3.amazonaws.com/0/16981/5676c0ba-9fe6-5dd2-61c2-c0bcd2fc4784.png)
※画像は見えてる世界に対してGoogleMapを画像化したものを空間上に表示したもの

#ソースコード
https://github.com/sonixlabs/lifestyle-vr
※cloud9とかにアップすれば動きます•̀.̫•́✧

#最後に
現実世界にハイパーリンクつけて遊んだり、ナニカの補助用途でご利用ください。
間違っても、実際にこれを身に付けて町中に繰り出さないように。。

![スクリーンショット 2016-11-28 13.59.09.png](https://qiita-image-store.s3.amazonaws.com/0/16981/d5a79bb3-78de-01f2-420f-3d62465d8f49.png)
Android FCM(GCM) バックグラウンドでonMessageReceivedを通らない時は

AndroidでFCM(GCM)を使う場合、サーバから送られてくるpayloadの内容により、
アプリがbackground/foregroundの時で挙動が変わるようである。

受信してもGcmListenerService#onMessageReceived()を通らなかったので、いろいろと調べてみた。

詳しくは公式ドキュメントに記載されている。
https://developers.google.com/cloud-messaging/concept-options

# payloadの内容がnotificationの場合

> GCM automatically displays the message to end user devices on behalf of the client app. Notifications have a pre-defined set of user-visible keys.

システムが自動的に通知を出すらしい。

サンプルデータ
body/title/iconは予約されているキーなので、これらが必要になる。

```json
{
    "to" : "registration id.....",
    "notification" : {
      "body" : "本文",
      "title" : "タイトル",
      "icon" : "icon"
    }
}
```

# payloadの内容がdataの場合

> Client app is responsible for processing data messages. Data messages have only custom key/value pairs.

カスタムキーの受信が可能。アプリはGcmListenerServiceでonMessageReceivedの実装を刷る必要がある。

```json
{
    "to" : "registration id.....",
    "data" : {
      "message" : "本文",
      "title" : "タイトル",
      "something" : "何か"
    }
}
```

# ハイブリッド版

こうすると、background時にはnotificationにより自動的に通知が出て、foreground時には受け取った処理を実装することが出来る。

```json
{
    "to" : "registration id.....",
    "notification" : {
      "body" : "本文",
      "title" : "タイトル",
      "icon" : "icon"
    },
    "data" : {
      "message" : "本文",
      "title" : "タイトル",
      "something" : "何か"
    }
}
```

どんな時もonMessageReceivedで処理が必要な場合は、notification含めずにdataのみで送信した方が良いかもしれない。
VMwareセキュリティアドバイザリVMSA-2016-0021

VMware Identity Manager 2.xとvRealize Automation 7.xについて、セキュリティアドバイザリが出ていました。

* [VMSA-2016-0021: VMware product updates address partial information disclosure vulnerability](http://www.vmware.com/security/advisories/VMSA-2016-0021.html)

使用してないので、簡単にメモだけ。

* CVE-2016-5334の脆弱性。
* VMware Identity Manager 2.7.1版とvRealize Automation 7.2.0版が出ているので、それに更新すればOK。

このアドバイザリに関してVMware Blogsに「[VMSA-2016-0021 and VMSA-2016-0022 - VMware Security & Compliance Blog - VMware Blogs](http://blogs.vmware.com/security/2016/11/vmsa-2016-0021-vmsa-2016-0022.html)」が投稿されています。
DNSBL(CBL)にIPアドレスがブロックされてメールが受信されなくなった場合の対応

# DNSBL(CBL)にIPアドレスがブロックされてメールが受信されなくなった場合の対応

## DNSBL(CBL)とは

- スパムメール配信サーバーのブラックリストを作っている団体
  - 拠点はイギリスにあるらしい
  - [公式サイト : http://www.abuseat.org/](http://www.abuseat.org/) 
    - ドメインは違うけれども [https://www.spamhaus.org/](https://www.spamhaus.org/) からも行ける

## まず初めにすること

- CBLの[Lookupページ](http://www.abuseat.org/lookup.cgi)でSMTPサーバーのIPアドレスがリストアップされていないか確認する
  - CAPTCHA認証(画像2枚の文字or数字をテキストボックスに入力してLOOK UPボタンを押す)を実行すると、検索結果の画面に遷移する
  - 検索結果の画面で、「(IPアドレス) is listed in the CBL.」と出てきたらブロック対象になっているので、画面一番下のリンクを開く
    - リンク先を開くと自動的にREMOVEリクエストが飛ぶ

## REMOVEリクエストでの注意事項

- REMOVEリクエストが飛んでから24時間は「仮REMOVE」
  - 問題が解決していれば次回チェックでリストアップされないので自然にリストから消える
  - 仮REMOVE中でもDNSBL(CBL)でのチェックには引っかからなくなるのでメールは受信される(はず、たぶん)

## それでもダメな場合

そもそもうちのSMTPサーバーはSPAMメールを送信してないのになんでブロックされるんだ！という場合は、直接DNSBL(CBL)の担当にメールで問い合わせができる。

  - メールアドレスは cbl@abuseat.org
    - 原文 : Our email address is cbl@abuseat.org.
  - メールの件名(subject)には「必ず」問い合わせをしたい(ブロックされている)IPアドレスを入れること
    - 原文 : Include the IP address you're asking about in the subject line.

詳細は[DNSBL(CBL)の公式FAQ](http://www.abuseat.org/faq.html)を読んでね！


## メールでやり取りする際の注意事項

- とても無愛想なメールが来るけれど腹を立てずに気長に行きましょう
- 定型文を返してくることが多いけれどそれにも腹を立てないように
- 英語のメールしか受け付けてくれないのでやり取りは英語で
  - 日本にも活動拠点がある様な書き方なのだけれど。。。
- 過去にKDDIと揉めた経緯があるので日本からのメールだと多少警戒されるかもしれない
  - [INTERNET Watch - 迷惑メール対策ブラックリストの功罪について「Spamhaus」と国内ISPが議論](http://internet.watch.impress.co.jp/cda/event/2006/11/30/14094.html)

- 海外なので時差があるのと、もともと海外はメールの返信が遅い傾向があるので、返信が遅くても数日は待つこと
  - 同じ件で複数のメールを送ってこないでほしいとFAQに記載されている
  - 原文 : Send multiple emails about the same issue without waiting for a response. It's annoying and may delay resolution.

## 筆者の経験から

- やりとりの途中でDNSBL(CBL)から3週間ほど返信が無かったので「メール送ったけど読んでもらえてますか？」と問い合わせたところちゃんと返信は来た
- 基本的に2～3日中に回答が来る
  - 早いときは数時間で返ってくることもあるけれどこれは運次第
- やり取りしているうちに自然と半解除状態になってうやむやのうちにブラックリストから解除されることがある
  - 根気強く対話を続けることが重要なのかもしれない
  - 「(対等な立場として)協力してスパムメール根絶しようね！」ってスタンスで行けば割と理解してくれている感じ
  - 「こっち(日本)は冬だけどそっち(イギリス)はどう？寒くない？」などといった感じでちょっと緩めに対話していくとほんの少しだけ先方の態度が柔らかくなるのでお勧め
  - ある日突然ブラックリストから解除されてても特に連絡などは来ない
    - たぶん「ブラックリスト作成を自動化しているため先方も気が付いていない」とかなのではないだろうか？

Best Regards,
Elastic Stack導入

Ubuntu14.04.5にElastic Stack 5.0.1シリーズを入れます。

```
sudo apt-get update
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
sudo apt-get install oracle-java8-set-default
curl -L -O https://artifacts.elastic.co/downloads/logstash/logstash-5.0.1.deb
curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.0.1.deb
curl -L -O https://artifacts.elastic.co/downloads/kibana/kibana-5.0.1-amd64.deb
sudo dpkg -i *
sudo apt-get -y install sysv-rc-conf
sudo sysv-rc-conf logstash on
sudo sysv-rc-conf elasticsearch on
sudo sysv-rc-conf kibana on
```

自動起動設定まで完了。
起動するにはホストで`vagrant reload`するか、以下。
```
sudo service logstash start
sudo service elasticsearch start
sudo service kibana start
```

でもこのままじゃ動かないので…

```
sudo apt-get install emacs24-nox
sudo emacs /etc/logstash/conf.d/logstash.conf
```
```/etc/logstash/conf.d/logstash.conf
input {
    file {
        path => "/home/vagrant/log/something.log"
        type => "something"
    }
    http {
        host => "localhost"
        port => "9600"
        type => "http"
    }
}
filter {
    date {
        match => [ "date", "YYYY/MM/dd", "YYYY/MM/dd HH:mm:ss", "YYYY/MM", "EEE, YYYY/MM/dd HH:mm:ss 'GMT'"]
        target => "date"
    }
}
output {
    elasticsearch {
        hosts => ["localhost:9200"]
        index => "%{type}-%{+YYYY.MM.dd}"
    }
}
```

設定ファイルの中身は、入れたいデータと相談です。細かい設定は公式を見るとよいでしょう。

ちなみにElastic Stackはメモリが足りないとServiceは走ってるように見えても動作してくれません。

ホスト側のVagrantfileのここを編集します。

```Vagrantfile
  config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
    vb.memory = "4096"
  end
```

2GBでは動きません。4GBでは動きます。

Vagrantfile関連で。
proxyに囲まれて生活している方は以下の設定も必要です。

```Vagrantfile
  config.proxy.http     = "http://proxy.jp:99999"
  config.proxy.https    = "http://proxy.jp:99999"
  config.proxy.no_proxy = "localhost,127.0.0.1,(他のVBのIP)"
```

ポートフォワーディング・Private_IPの設定は、ファイル内にひな形があるのでそれを見ましょう。

`http://localhost:5601`
(localhost or Privagte_IP)

見れたらめでたしめでたし。
Google API Client for pythonでアナリティクス APIからデータ取得

リファレンス
https://developers.google.com/analytics/devguides/reporting/core/v4/quickstart/installed-py

サンプルclass

```
class GoogleAnalyticsUtility(object):
    SCOPES = ['https://www.googleapis.com/auth/analytics.readonly']
    DISCOVERY_URI = ('https://analyticsreporting.googleapis.com/$discovery/rest')
    VIEW_ID = 'xxxx'

    def __init__(self, target_date):
        self.target_date = target_date

    def get_report(self):
        parser = argparse.ArgumentParser(
                formatter_class=argparse.RawDescriptionHelpFormatter,
                parents=[tools.argparser])
        flags = parser.parse_args(['--noauth_local_webserver'])
        CLIENT_SECRETS_PATH = os.path.join(settings.BASE_DIR, '../etc/googleapi/client_id.json')
        flow = client.flow_from_clientsecrets(
                CLIENT_SECRETS_PATH, scope=self.SCOPES,
                message=tools.message_if_missing(CLIENT_SECRETS_PATH))

        storage = file.Storage(os.path.join(settings.BASE_DIR, '../etc/googleapi/analyticsreporting.dat'))
        credentials = storage.get()
        if credentials is None or credentials.invalid:
            credentials = tools.run_flow(flow, storage, flags)
        http = credentials.authorize(http=httplib2.Http())
        analytics = build('analytics', 'v4', http=http, discoveryServiceUrl=self.DISCOVERY_URI)
        reports = analytics.reports()
        return reports.batchGet(
                body={
                    'reportRequests': [
                        {
                            'viewId': self.VIEW_ID,
                            'dateRanges': [{'startDate': self.target_date, 'endDate': 'today'}],
                            "dimensions": [
                                {
                                    "name": "ga:productSku",  # 販売した品目の商品コードです。
                                }],
                            'metrics': [
                                {'expression': 'ga:itemQuantity'}  # e コマース トランザクションで売れた商品の数です。
                            ],
                            'pageSize': 50000,
                            'pageToken': "nextpage",
                            "orderBys":
                                [
                                    {"fieldName": "ga:itemQuantity", "sortOrder": "DESCENDING"},
                                ]
                        }]
                }
        ).execute()

target_date = date.today() - timedelta(days=7)
ga = GoogleAnalyticsUtility(target_date.strftime('%Y-%m-%d'))
ga.get_report()
```

コマンドラインで叩いた場合,リンクが表示されるのでこれをコピペしてブラウザに貼り付ければ認証完了

`https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fanalytics.readonly&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=xxxxx-gd5j31ge4jdobhlg9a3jqnveae34cag1.apps.googleusercontent.com&access_type=offline`
raspberry pi 1 model bで、node-red　その１６

#概要
raspberry pi 1 model bの、node-redで、音を出してみた。

#開発環境
raspberry pi 1 model b
raspbian 2016_09_23 jessie lite

#写真
![MVC-011S.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/381384b9-8e32-2fde-eb9b-3b50e3b9ae32.jpeg)

#準備
speaker-test -t sine -f 440
aplay ohi.wav

#サンプルコード
![wav.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/5e6167d7-65be-b37f-af34-9aae172f8b76.jpeg)

```
[{"id":"4a63f144.d85e9","type":"inject","z":"4f4f703e.a2a9d","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":135,"y":841,"wires":[["bf940258.66bb4"]]},{"id":"bf940258.66bb4","type":"exec","z":"4f4f703e.a2a9d","command":"sudo aplay /home/pi/oha.wav","addpay":true,"append":"","useSpawn":"","timer":"","name":"aplay","x":320,"y":841.5,"wires":[[],[],[]]}]

```
MongoDBのObjectIdだけで、日付で範囲指定して取得する方法

たまには、MongoDBネタで。

### MongoDBのObjectIdの生成規則
---

[mongodbのObjectIdの生成規則](http://toshitanian.hatenablog.com/entry/2014/02/14/015314)

こちらの記事が参考になります。

> 4バイトの，Unixエポックからの経過秒数(Unix時間)
> 3バイトのマシンID
> 2バイトのプロセスID
> 3バイトのカウンタ(開始番号はランダム)

先頭がUnix時間なので、先頭以外のバイトを0で指定すれば、時間で範囲指定ができます。

```js

var startTime = 1480518000;
var endTime = startTime + 86400;

var start = new ObjectId(startTime.toString(16) + '00000000000000');
var end = new ObjectId(endTime.toString(16) + '00000000000000');

db.Hoge.find({_id: {$gte: start, $lt: end}});

// こちらでも可
var start = ObjectID.createFromTime(startTime);

```

ちなみに、\$gteは「Greater Than Equal」。\$lt「Less Than」。という意味らしいです。

### 昔書いたスライド
---
[Node.js×mongo dbで3年間サービス運用してみた話](http://www.slideshare.net/leverages_event/nodejsmongo-db3)

実は、こちらに書いてあるのですが、なんと画像になっており引っ張るのが面倒だったので、Qiita化してみました。（シンタックスハイライト付けたくて、画像なら行けるじゃんと思って当時書いたのですが、今になってコピペ出来ないということに気づくというね。。。今なら、[「Marp」](https://yhatt.github.io/marp/)使うかなぁ。）

あ、ちなみに、このスライドの中の

> mongod単位で見ると、_idが複数ある状態に。。。

というのは、バグフィックスされているそうです。本当に解決したのか？知りたいのですが、転職しちゃったので調査出来ないんですよねー。dumpしてrestoreするだけで、重複_idがあれば標準出力されるので、ピグチームの誰かやってほしいです。。。

理由は、「Mongosに不要になったコネクションが残ってしまって、そちらに書き込んでしまうことがあったため」みたいです。BlueGreanデプロイメントしていたので、Mongosを定期的に再起動しておけばよかったかなぁと。今だと、Dockerとか使って普通に全部再起動になるとかなのかなぁとか。技術は進歩してますね。
svn の update をバッチで処理する

投稿日：2016-11-28

# やりたいこと
svn の update 時に大量の更新があった場合に
以下のエラーで `update` が止まってしまうことがある
`The server sent a truncated HTTP response body.`
その都度、`cleanup` を実行して、再度 `update` するのだがこれを自動化したい
windows 環境なので バッチでの実行を検討する
TortoiseSVN を使用しているのでコマンドラインツールのインストールが必要

# 環境
- Windows7 Home Premium
- Subversion 1.8.13
- TortoiseSVN 1.8.11

# 処理の概要
`update`を実行、エラーになったら`cleanup`して再度`update`を実行
`update`中に`conflict`したらその部分はスキップ（後まわし）

# ヘルプを見てやり方を調べる
`svn help update` で `update` コマンドで使えるオプションを確認する

# バッチ処理
＜SVNのローカルリポジトリパス＞を設定
TortoiseSVN のパス `C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe` も異なる場合は修正する

```
@ECHO OFF

set SVN_DIR=＜SVNのローカルリポジトリパス＞
set TOR_DIR="C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe"
set /A CNT=0

:LOOP

REM (p) postpone 競合を後で解決
call svn update --accept p %SVN_DIR%
IF "%ERRORLEVEL%"=="0" GOTO END

call svn cleanup %SVN_DIR%

REM 無限ループを避ける為に繰り返しは10回を上限とする
IF CNT==10 GOTO END
SET /A CNT+=1
GOTO LOOP
:END

REM 最後に TortoiseSVN を表示する（ここで競合に関しては解決してもらう） 
call %TOR_DIR% /command:update /path:%SVN_DIR%
```

# 最後に
お昼休みで作ったので動作的に怪しい部分が無いとはいえないです。
ご利用は計画的に。


# 参考リンク
[TortoiseSVNのコマンド](https://tortoisesvn.net/docs/release/TortoiseSVN_ja/tsvn-cli-main.html)

[【svn】基本コマンド](http://qiita.com/konweb/items/6effd36aab551b2d6b8f)

[個人的によく使う svn コマンドの使い方まとめ](http://bashalog.c-brains.jp/10/09/08-112628.php)

[バッチファイルでTortoiseSVNのupdateを行う](http://progmemo.wp.xdomain.jp/archives/34)

[Windowsバッチファイル制御構文](http://capm-network.com/?tag=Windows%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%88%B6%E5%BE%A1%E6%A7%8B%E6%96%87)
UUID(v4) がぶつかる可能性を考えなくていい理由

お手軽にランダムなIDを取得したい時にUUIDはとても重宝します。
でもたまに、
**「このID(UUID)ってぶつかることない？対策しなくて大丈夫？」**
と聞かれることがあります。
それに対して、
**「ウィキペディア先生がぶつからねえって言ってたから大丈夫だよ！（＃ﾟДﾟ）」**
で切り抜けるのもそろそろ限界のような気がするのでちゃんと調べました。
(もちろんウィキペディア先生を頼りました！)

## 2つの理論
UUIDの衝突確率について考える上で次の2つの理論が重要になります。

- 鳩の巣原理
- 誕生日のパラドクス

### 鳩の巣原理
鳩の巣原理とは、
**m個の入れ物にn個のものを入れるとき、n > m ならば少なくとも1個の箱には2個以上のものが入る**

9個の巣箱に10羽の鳩が入る場合、必ずどれかの巣箱には2羽以上入ることになるということです！(ウィキペディア先生)
考えれば当たり前のことですが同様にして考えれば、
「1..100の乱数生成を101回した場合必ず1回以上同じ値が出る」
ということなのでハッシュやUUIDの衝突確率にも応用できます。

衝突する確率は数式で一般化できますが割愛。
「箱の数が十分でなければぶつかりうる」ということだけ覚えておいてください。

### 誕生日のパラドクス
続けて誕生日のパラドクスです。これは、
**1クラスに23人いるとき同じ誕生日のペア(以上)が存在する確率は50%以上**
になるという理論です。
「365日もあるのに思ったより確率が高い」
と思ったでしょうか？このことからパラドクスと呼ばれています。

この確率が正しいかは先ほどの鳩の巣原理の応用になります。
鳩の巣原理より1クラスに366人いる場合(多い!)、同じ誕生日のペア以上が存在する確率は100%です。(うるう年でない場合)

確率を数式化してみます。
まず、n人全員の誕生日が異なる確率を求めます。

最初に、2人のとき、誕生日が同じになる確率は 1/365 なので誕生日が異なる確率は

```math
1-(1/365) = 364/365 ・・・②
```

同様に、3人目の誕生日が異なる確率は

```math
1 - ((1/365)+(1/365)) = 363/365 ・・・②
```

つまり、3人の誕生日が全て異なる確率は① * ②より

```math
(364/365) * (363/365) = (364*363)/365^2≒0.991795834..
```
これを一般化すると

```math
(364/365) * (363/365) * (362/365) * ... * ((365-n+1)/365) = 365!/(365^n-(365-n)!)
```
この確率を1から引けば少なくとも2人以上が同じ誕生日である確率になります。

```math
1 - 365!/(365^n-(365-n)!)
```
n=23のときに確率は0.507となり50%を超えます。

せっかくなのでコード化

```birthday_conflict.py
memo = {}  # 計算量削減のためのメモ化
def _birthday_conflict(n):
  """
  n人目の誕生日が異なる確率
  """
  if n in memo:
    return memo[n]
  else:
    rate = (365.0-n)/365.0
    memo[n] = rate
    return rate


def birthday_conflict(n):
  """
  n人の誕生日が全て異なる確率
  """
  rate = 1.0
  for i in range(1, n):
    rate *= _birthday_conflict(i)
  return rate


def not_birthday_conflict(n):
  """
  n人の少なくとも2人が同じ誕生日になる確率
  """
  return 1.0 - birthday_conflict(n)

# 実際に計算
[(n, not_birthday_conflict(n)) for n in range(2, 365)]
```
Excelで結果をグラフ化すると、
![スクリーンショット 2016-11-28 12.01.52.png](https://qiita-image-store.s3.amazonaws.com/0/3147/25916f54-c91e-fbd5-1165-f4e8a78b6c7b.png)

23人で0.507...と50%を超え、119人で100%に収束します。

ついでに、n人いる教室に入室した場合、自分と同じ誕生日の人がいる確率を求めてみます。
まず、ある人が自分と同じ誕生日でない確率は 364/365
これがn人に対し同時に起こりうる確率は

```math
(364/365)^n
```

つまり同じ誕生日の人が少なくとも1人いる確率は

```math
1-(364/365)^n
```
となります。

コードは

```
def not_same_birthday(n):
  return 1.0 - (364.0/365.0)**n
```
と単純です。結果は、
![スクリーンショット 2016-11-28 12.24.36.png](https://qiita-image-store.s3.amazonaws.com/0/3147/a3f02855-faa4-7314-ee6b-dcd335d9ca8e.png)
と先ほどと打って変わって253人でようやく50%を超えます。

## 誕生日攻撃
長々とやってきましたが、誕生日のパラドクスは誕生日攻撃と呼ばれる攻撃手法の基になっている理論です。(ここから難しいのでウィキ先生頼り)
乱数をひたすら作って同じものが出るまで繰り返すという単純な方法ですが、誕生日のパラドクスの通り、意外と回数は少なくて済んでしまいます。
H個の異なる出力をそれぞれ同じ確率で生成した場合、同じ結果が出るまでの回数は平均

```math
1.25*√(H)
```
回だそうです。
(誕生日の場合のH=365で23.88回と出るので妥当性がわかります)

これを数式で近似やら色々やって最終的にN-ビットの乱数生成がぶつかるまでの回数の期待値を求めると、

```math
2^{N/2}
```
回だそうです。
この式がほしかったものです。

##結論
UUID(ver.4) は122ビットの乱数なので生成したUUIDが既存のものにぶつかるまでの回数の期待値は

```math
2^{122/2} = 2305843009213693952回 = 2.3*10^{18}
```
230京回となります。
これはぶつからない！
Swift で OGP 情報の取得

## 目的
Swift で任意のWebページの[OGP](http://ogp.me/)情報を取得する

## 方法
任意のパッケージマネージャで https://github.com/satoshi-takano/OpenGraph をインストールする。
OpenGraph を利用するファイルの冒頭で import して

```swift
import OpenGraph
```
fetch メソッドに任意の URL を渡す

```swift
OpenGraph.fetch(url) { og, error in
    print(og?[.title]) // => og:title of the web site
    print(og?[.type])  // => og:type of the web site
    print(og?[.image]) // => og:image of the web site
    print(og?[.url])   // => og:url of the web site
}
```

コールバックで OGP 情報が受け取れる。

___

以上

_※半分自分のライブラリの宣伝でした_
MacのCPU温度、ファンスピードなどをターミナルでチェックする方法

MacBook Airの内蔵SSDやバッテリーなどを交換してから、ファンクションキー辺りの温度の高さが気になりだした。iStatsというソフトを使うとMacのいろんな部分の温度（CPUの温度、バッテリーの温度、メモリ周辺の温度、CPU/GPU ヒートパイプ周辺の温度など）が分かっていい。

```bash:terminal
# iStatsのインストール
sudo gem install iStats -n /usr/local/bin

# 実行は
istats

# iStatsの使い方をチェック
istats -h

# 全てのセンサーをスキャンしてターミナルに表示
istats scan

# 全てのセンサーの情報をistats実行時に表示させる
istats enable all
```

istatsの実行結果の画像
![Screen Shot 2016-11-28 at 12.31.36.png](https://qiita-image-store.s3.amazonaws.com/0/134160/9d373ce1-a929-72be-f8e5-c55d514cc4bc.png)


# 参考
https://rubygems.org/gems/iStats/
https://discussions.apple.com/thread/2676820?tstart=0
https://qiita.com/metaforce_/items/71cf3b064fe00cf1608e
https://stackoverflow.com/questions/2893889/how-do-i-fix-the-you-dont-have-write-permissions-into-the-usr-bin-directory