OmniAICreator/Qiita-1.07M huggingface dataset:
Nuxt2.9.xの本当のtypescript構築手順

## 記事を書いた時点のバージョン

```console
❯ npm view nuxt

nuxt@2.9.2 | MIT | deps: 7 | versions: 228
```

## 概要
### 日本語の公式記事は古い

| | [日本語記事](https://ja.nuxtjs.org/guide/typescript) | [英語記事](https://nuxtjs.org/guide/typescript) |
| --- | --- | --- |
| スクショ | <a id="now-jp-doc-screenshot" name="now-jp-doc-screenshot"><img  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7772/ba7441ac-a197-dc9a-25d7-a3a7ea9a0ec5.png" /></a> | ![スクリーンショット 2019-09-02 1.04.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7772/99067e4d-3ff6-3e43-7e83-c8461b5ed602.png) |
| 手法 | @nuxt/typescriptつかえ | @nuxt/typescript-buildなどを使え |
| Ver | 2.8.x | 2.9.x |

違う。

- 英語のほうが対象バージョンが新しい
- 日本語より英語のドキュメントの更新が遅いとは考えにくい
- 実際にnpmで配布されているnuxtのlatestは2.9.2である

以上のことから英語記事の手順のほうが正(もしくはより好ましい）だろう。

## 公式ドキュメントは分かる人にわかるようにしか言ってくれない

https://typescript.nuxtjs.org/guide/setup.html#installation
これを読めばわかると思うが、一からtypescriptサポートされたnuxt環境を構築する方法などは書いてくれていない。これを読んでわからないやつはおとなしくボイラープレートで学んでおけという感じだろうか。

私のように最初からスクラッチで環境を作って学んでいきたい人のように現時点で(私が正解だと思う)typescript環境構築手順を書こうと思う。

## Nuxt2.9.xの本当のtypescript構築手順

以下全部やる必要はない。必要なもののみやればいい。

基本的に、公式ドキュメントのを貼った後、やること概要を書き出すようにした。これはこの記事執筆時点のときの公式ドキュメントから、内容が変わってしまったときの保険である。
もし、リンク先の記事の内容とやること概要が乖離していたら、そういうことだと思ってほしいし、この記事は寿命を終えて正を全うしたと思ってほしい。

 
### 1. スクラッチから始める
https://ja.nuxtjs.org/guide/installation#%E3%82%B9%E3%82%AF%E3%83%A9%E3%83%83%E3%83%81%E3%81%8B%E3%82%89%E5%A7%8B%E3%82%81%E3%82%8B のとおりにやる

#### やること概要

- package.jsonでscriptsの設定を追加
- npm i -S nuxt
- mkdir pages
- pages/index.vue をかく

#### 言ってること

- npm run dev で localhost:3000 で動くようになったよ


### 2. @nuxt/typescript-buildの導入
https://typescript.nuxtjs.org/guide/setup.html#installation の通りにやる

#### やること概要
- npm i -D @nuxt/typescript-build
- nuxt.configのbuildModulesを設定
- tsconfig書く

#### 言ってること
pages/やcomponents/などでtypescriptかける様になったよ

### 3. @nuxt/typescript-runtimeの導入

https://typescript.nuxtjs.org/guide/runtime.html#installation の通りにやる

#### やること概要
- npm i -S @nuxt/typescript-runtime
- package.jsonのscriptsのコマンドをnuxtじゃなくてnuxt-tsに変える

#### 言ってること
nuxt.configとかserverMiddlewaresもtypescriptでかけるようになった

### 4. class-apiの導入

- https://ja.nuxtjs.org/guide/typescript#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88 のとおりにやる。
- tsconfigに ```"experimentalDecorators": true,``` 追加


#### やること概要
- npm i -D vue-property-decorator


#### 言ってること
class-apiでコンポーネントを記述できるようになったよ
CSXSEventでobjectデータを送信する

AdobeのスクリプトでPanel間やjsx・js間でデータのやりとりをすることができるCSXSEventですが、普段stringしか送っていなかったのをデータを送りたいなーと思いやってみたという話。
思ったより簡単にできました。

# CSXSEvent基礎
基本はこう書きます

```sender.jsx
 var mylib = new ExternalObject( "lib:\PlugPlugExternalObject" );
 var eventObj = new CSXSEvent();
 eventObj.type = "event_type"; // 好きなidentifierをつける
 eventObj.data = "message";
 eventObj.dispatch();  
```
ちなみにphotoshopであれば```"lib:\PlugPlugExternalObject"```が内臓されているらしいので特にファイルをダウンロードしなきゃいけないとかはありません。

```receiver.js
 var csInterface = new CSInterface();
 csInterface.addEventListener("event_type", function (event) {
   console.log(event.data);
 });
```

event.dataにはもちろん```"message"```(string)が入っています。

# event.dataにObjectを入れる
stringだと物足りないので、Objectデータを送信したい！という気持ちでチャレンジ

```sender.jsx
 var data = {
    message : "送りたいメッセージとかを書き込んでみる",
    id : 1 // idとか取得した数値とかを追加で送ってみる
 }

 var mylib = new ExternalObject( "lib:\PlugPlugExternalObject" );
 var eventObj = new CSXSEvent();
 eventObj.type = "event_type"; // 好きなidentifierをつける
 eventObj.data = data;
 eventObj.dispatch();  
```
しかし、これで受け取り側でconsole.logを出してみると、objectがstringで送信されてしまうため、[object object]と表示されてしまいます。
<img width="216" alt="スクリーンショット 2019-09-02 1.34.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189041/e8a08190-0613-ed35-71a1-d6606b1e8cca.png">

# event.dataにJson化したデータを入れる
やはりstring以外は送れないのかなーと思ったのですが、stringならばjsondで送ってパースすれば良いのでは？という思いつき。
※ちなみにAdobeのJsxではJSON.stringify/JSON.parseのメソッドが使えないので外部からincludeする必要があります。私は[github.com/douglascrockford/JSON-js](https://github.com/douglascrockford/JSON-js)を利用させていただいています。いくつか方法があると思いますので、お好きな方法を取ってみてください。

```sender.jsx
 var data = {
    message : "送りたいメッセージとかを書き込んでみる",
    id : 1 // idとか取得した数値とかを追加で送ってみる
 }

 var mylib = new ExternalObject( "lib:\PlugPlugExternalObject" );
 var eventObj = new CSXSEvent();
 eventObj.type = "event_type"; // 好きなidentifierをつける
 eventObj.data = JSON.stringify(data); // JSON化させる
 eventObj.dispatch();  
```
こんな感じで送信すると、特に受け取り側ではparseなどしなくても受け取ることができます
<img width="396" alt="スクリーンショット 2019-09-02 1.44.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189041/2dee365a-5f61-8832-b613-f9ee4046f478.png">

CSXSEventはちょっとしたタイミングの受け渡しでしか使えていなかったのですが、色々なデータを詰めて送れるとなるととても便利に使えそうです。
キーマテリアル作成

# キーマテリアル作成

## はじめに

ITで安全な通信を行うために，「秘密鍵」と「証明書」を組み合わせた「デジタル署名」が使われています。「証明書」の中に「署名」や「公開鍵」が含まれています。大まかには，次の流れでデータ送受信を行います。

1. 送信者は秘密鍵を使ってデータを暗号化し，それに証明書を添付して，送信する。
2. 受信者は証明書の中にある署名などを検証し，正当な送信者であるかどうかを確認してから，公開鍵を使ってデータを復号化する。なお，受信者は証明書を検証する際に，証明書の正当性や失効有無を証明局（CA）のrepositoryに問い合わせる。

ここでは，CentOS7でOpenSSLを使って，Hyperledger Fabric CA 1.3.0向けのキー・マテリアル（秘密鍵，CSR，証明書）を作成する方法を紹介します。

## 証明書発行の体制

- 最上位のCAがルートCAであり，その下に多数の中間CAがある
  - ルートCAの一つとして，「Digital Signature Trust Co.」がある
- 中間CAから，Webサーバ向けや，中間CA向けのサーバ証明書を発行する


## 関連用語

- 証明局（CA = Certificate Authority）
  - 証明書を発行する機関
  - 最上位がルートCAであり，中間CAに移譲され，中間CAから証明書を発行することが多い
  - CAの他に，登録局（RA），リポジトリがあるが，ここではまとめてCAと表記
- 証明書（Certificate）
  - CAの署名，サーバの署名，公開鍵などで構成されるファイル
  - 暗号化したデータを送信する時に，証明書を添付する
  - 同じ秘密鍵からは、同じ公開鍵を含むCSRが作られるので、一度，証明書を発行してもらったら，同じ秘密鍵から再度CSRを作らないこと
- 秘密鍵（Private Key）
  - データを暗号化するために使う
- 公開鍵（Public Key）
  - データを復号化するために使う
- CSR
  - CAに証明書を発行してもらうために必要な署名要求(Certificate Signing Request)
  - CSRファイルには，公開鍵や運営者の情報（組織名や組織の所在地など）が含まれる
- キー・マテリアル
  - 秘密鍵，CSR，証明書など，デジタル証明に必要なものをまとめて，キーマテリアルと呼ぶ
- CRL
  - 証明書失効リスト
  - 秘密鍵が漏洩・失念された場合，CAに申請すれば失効リストに登録される


## 作業ディレクトリを作成

```
$ mkdir keys
$ cd keys
```

## 利用可能な曲線を確認

```
$ openssl ecparam  -list_curves
```

## ECC秘密鍵を作成

```
$ openssl ecparam -name prime256v1 -genkey -out private.pem
```

## 秘密鍵が破損していないことの確認
```
$ openssl ecparam -check -noout -in private.pem
```

## CSRを作成

```
$ openssl req -new -sha256 \
    -key private.pem \
    -out csr.pem \
    -subj "/C=JP/ST=Tokyo/L=Ota-ku/O=Example Company/OU=Example Service/CN=xxx.example.com"
```

## CSR内容確認
```
$ openssl req -text -noout -in csr.pem
```

## CA構築

ルートCAの環境を構築する。

```
$ sudo touch /etc/pki/CA/index.txt
$ sudo su
# sudo echo '1000' > /etc/pki/CA/serial
$ exit
$ openssl ecparam -name prime256v1 -genkey -out cakey.pem
$ openssl req -new -x509 -sha256 -extensions v3_ca \
    -key cakey.pem \
    -out cacert.pem \
    -days 1095 \
    -subj "/C=JP/ST=Tokyo/L=Bunkyo-ku/O=UTokyo/OU=ZTokyo CA/CN=ZTokyo CA"
$ sudo mv -f cakey.pem /etc/pki/CA/private/
$ sudo mv -f cacert.pem /etc/pki/CA/
```

## CSRに署名し、証明書を作成（オレオレ署名）

「[openssl.cnfの設定項目](https://l-w-i.net/t/openssl/conf_001.txt)」に説明があるが、/etc/pki/tls/openssl.cnfのpolicy_matchサブセクションは、デフォルトでcountryName、stateOrProvinceName、organizationNameの3つが「match」となっている。つまり、条件が厳しく、同じ国、同じ都市、同じ組織でなければ、証明書を発行できない。

policy_matchサブセクションだと証明書を発行できないので、「-policy policy_anything」オプションを指定して、緩い条件で証明書を発行する。

```
$ sudo openssl ca -extensions v3_ca -policy policy_anything \
    -in csr.pem \
    -out cert.pem
$ sudo chown $USER:$USER cert.pem
```

find /etc/pki/CA/  | sed -e "s/[^-][^\/]*\//  |/g" -e "s/|\([^ ]\)/|-\1/"

## 証明書の内容を確認

```
$ openssl x509 -text -noout -in cert.pem
```

## 公開鍵のモジュラスを確認

- ECDSAなら「Wrong Algorithm type」が出力される

```
$ openssl x509 -modulus -noout -in csr.pem
Modulus=Wrong Algorithm type
```

## あとで勉強すること

- [CA 構築のための OpenSSL の設定](http://moca.wide.ad.jp/notes/ca_doc/openssl.html)
  - openssl.confの説明あり
- [opensslによるWebサーバの証明書のチェック](http://causeless.hatenablog.jp/entry/2013/09/28/222800)
sakura editor scripts

# sakura editorのスクリプト例

実行日の日付を出力後、改行、タブを出力してスクリプト終了。
実行例：
09月02日(月)
□⏎


```sakura:date.js
var dt = new Date();
var year = dt.getFullYear();
var month = ("00" + (dt.getMonth()+1)).slice(-2);
var day = ("00" + (dt.getDate())).slice(-2);

var week = dt.getDay();
var weekString = ["日","月","火","水","木","金","土"][week];
var today = month + "月" + day + "日" + "(" + weekString + ")";

Editor.InsText(today + "\n");
Editor.InsText("	");
```

タブを出力する。

```sakuramacro:tab.mac
//キーボードマクロのファイル
S_IndentTab(0);	// TABインデント
```

改行コードを出力する。

```sakuramacro:rtn.mac
//キーボードマクロのファイル
S_Char(13);	// 文字入力
```

以上
Swift でのコマンドライン引数の解析ツール

# はじめに

macOS の Calendar を操作する CLI ツールの [iCalTool](https://github.com/moriai/iCalTool) を開発しているのだが、そろそろ手で引数の解析をするのが辛くなってきたので、何か良いライブラリがないか調べてみた。

# 見つかったライブラリ

見つけたライブラリを辞書順で。

+ [Commandant](https://github.com/Carthage/Commandant)
+ [Commander](https://github.com/kylef/Commander)
    - キーワードやエラーメッセージに色が付く
+ [Guaka](https://github.com/nsomar/Guaka)
    - 比較的コンパクト
    - 色はつかない
    - 「コマンド名 フラグ サブコマンド名 各種オプション … 」という形式が使える
+ [SPMUtility](https://github.com/apple/swift-package-manager)
    - Swift Package Manager 内部で使われている
    - ArgumentParser を SPMUtility という名前で持ち込むことができる
        - 以前は Utility という名前で利用できたが、改名された
+ [Swift Argument Parser](https://github.com/apple/swift-argument-parser)
    - 最近リリースされた
+ [SwiftCLI](https://github.com/jakeheis/SwiftCLI)
+ [Yaap](https://github.com/hartbit/Yaap)

使用感などは別途。
Automation Anywhere Community Editionをインストールしてみた & 便利なショートカット

最近RPAを始めたので無料で利用できるAutomation Anywhere Community Edition (AACE)をインストールしてみました。

インストール方法や利用条件はすでに[まとまっている記事](https://qiita.com/RPAbot/items/8d9b14a8b779d1d305e4)があるのでここでは書きません。

有料版は日本語になっているようですが、無料版はまだ英語だけのようです。
![aace.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490819/12d58049-6cef-d895-9849-e9619f169664.png)

使い始めるにあたって便利なショートカットをまとめてみることにしました。

# Automation Anywhereショートカット集

### Tasks画面

|ショートカットキー|説明|
|:--|:--|
|F1|ヘルプの表示|
|F4|(Taskを選択した状態で)WorkbenchでTaskを編集、(選択ナシなら)もしくはWorkbenchを起動。|
|F5|(Taskを選択した状態で)Taskを実行。|
|Del|(Taskを選択した状態で)Taskの削除。|
|Ctrl+Alt+R|Recording開始。|
|Ctrl+S|Repository画面を表示。|
|Ctrl+W|Workbenchを起動。|
|Ctrl+L|Schedule Managerを起動。|
|Ctrl+R|Trigger Managerを起動。|
|Ctrl+K|Workflow Designerを起動。|
|Ctrl+P|Report Designerを起動。|
|Ctrl+O|オプション画面表示。|
|Alt+F4|アプリケーション終了。|


### Workbench 画面

|ショートカットキー|説明|
|:--|:--|
|F1|ヘルプの表示|
|F2|(コマンドダイアログボックスの編集ボックスで)変数の挿入ダイアログの表示。|
|F5|(デバッグモード時)Taskを実行。|
|F9|(デバッグモード時)ブレークポイントの切り替え。|
|F10|(デバッグモード時)ステップオーバー。|
|ESC|(デバッグモード時)Taskの実行を中断。|
|Ctrl+S|タスクを保存。|
|Ctrl+D|(アクション選択時)アクションを複製。|
|Ctrl+C|(アクション選択時)アクションをクリップボードにコピー。|
|Ctrl+V|(アクション選択時)アクションをクリップボードから貼り付け。|
|Ctrl+Z|(アクション選択時)アクション編集を取り消し。|
|Ctrl+Y|(アクション選択時)アクション編集を繰り返し。|
|Del|(アクション選択時)アクションの削除。|
|Ctrl+Alt+E|エラービューの表示。|
|Ctrl+Alt+V|変数マネージャの表示。|
|Ctrl+Alt+B|Botの依存関係の表示。|
|Alt+F4|Workbench終了。|

### レコーディング時

|ショートカットキー|説明|
|:--|:--|
|Ctrl+Alt+S|停止 (Stop)。|


### 実行時

|ショートカットキー|説明|
|:--|:--|
|Pause|一時中断。|
|ESC|停止して終了。|
[Spring boot]DIによるテスタブルなコードについて考えてみた

# はじめに
Spring Framework（boot)で、DIのメリットである「テスタブルなコード」にしようと思いながら、インジェクションするクラスに全く手を加えずに実装するってどうやるんだろう？と思ったのがきっかけで、自分なりに考えてみたのでその内容について書きたいと思います。

# 前提
Springって何？DIって何？って話はしません。[こちら](https://qiita.com/suke_masa/items/9dd3300c3190d6445ff8)の説明が素敵なので参考にしてください。冒頭記載のある勉強会、私も参加しましたが良い勉強になりました。

# 疑問に思っていたこと
テスタブルなコードにするといっても、インジェクションされるクラスが未実装のためテスト用にスタブクラスを作ったとして、そのクラスが出来上がったら少なくともインジェクションしている箇所を書き換えなくてはいけないんだよなって思っていました。

例えばこんな感じ。

```java
@RestController
public class DemoController {

	@Autowired
	DemoServiceStub demoService;
	//DemoService demoService;	//テストのためにここのコメントアウトを切り替える

	@GetMapping("/echo")
	public String echo() {
		return demoService.getMessage();
	}
}

public class DemoService {
	String getMessage(){
		//まだ実装中
		return "xxx";
	}
}

public class DemoServiceStub {
	String getMessage(){
		return "foo is stub";
	}
}

```

コメントで書いたとおり、インジェクションしているところを正規のクラスとスタブクラスとで切り替えないといけない。特定のメソッドだけテストしたいなら影響ないと思いつつも、やっぱりフィールドいじっちゃってるし気持ち悪いなという感覚。

で、考えて直したのがこちら。

```java
@RestController
public class DemoController {

	@Autowired
	@Qualifier("demoservice")  //インジェクション対象を名前指定する。正規とスタブで切り替えない。
	DemoService demoService;

	@GetMapping("/echo")
	public String echo() {
		return demoService.getMessage();
	}
}

//インターフェースを１つ作る
public interface DemoService {
	String getMessage();
}


@Service(value = "demoserviceWIP")  //名前を付ける。スタブとかぶらないように。
public class DemoServiceImpl implements DemoService {
	public String getMessage() {
		//まだ実装中
		return "xxx";
	};
}

@Service(value = "demoservice")  //名前を付ける
public class DemoServiceImplStub implements DemoService {
	String getMessage(){
		return "foo is stub";
	}
}

```

こうすることで、正規のときとスタブのときでテスト対象のソース（この場合はDemoController）に手を加える必要がなくなりました。
このやり方は、インターフェースで実装したいクラスが複数あった場合にも有効な気がします。
SpringではBean登録する型（クラス）が同じものが複数あった場合はどちらを登録すればいいのか判断がつかないため、こうやって名前解決をするみたいなので。
（というか、どちらかというとこの仕組みから今回の件のヒントをもらった感じです。）

# おさらい
- 正規クラスとスタブクラスを共通的にするためにインターフェースを使って実装する
    - これはDIとしてそもそも最低限やらなきゃいけないことな気がします
- インジェクションされる側のクラスに別名を与える（`@Service`のvalue属性）
- インジェクションする側で名前解決する（`@Qualifier`）
- インジェクションする側はインジェクションされる側の実装状況に関わらずいっさい手を加えない
- インジェクションされる側でインジェクション名を切り替える

# 最後に
ググってもほぼ出てこなかったやり方です。当たり前すぎるかアンチパターンになっているかもしれません。
その場合はご指摘頂けたらと思います。
AWSのWindowsサーバに即席でFTPサーバを構築するやつ

大体[ここ](https://codeday.me/jp/qa/20190412/611354.html)のおかげ。

```powershell
# インストール
Install-WindowsFeature -Name Web-Ftp-Server -IncludeAllSubFeature -IncludeManagementTools

# FTP サイトの名前
$ftpsite = "hogehoge"

# EC2インスタンスのパブリックIP
$publicip = "10.0.0.1"

# FTP サイトの作成
# https://codeday.me/jp/qa/20190412/611354.html
New-WebFtpSite -Name $ftpsite -Port 21 -Force
cmd /c \Windows\System32\inetsrv\appcmd set SITE $ftpsite "-virtualDirectoryDefaults.physicalPath:C:\inetpub\ftproot"

# 非SSL接続の許可
Set-ItemProperty "IIS:\Sites\$ftpsite" -Name ftpServer.security.ssl.controlChannelPolicy -Value 0
Set-ItemProperty "IIS:\Sites\$ftpsite" -Name ftpServer.security.ssl.dataChannelPolicy -Value 0

# BASIC 認証を有効化
Set-ItemProperty "IIS:\Sites\$ftpsite" -Name ftpServer.security.authentication.basicAuthentication.enabled -Value $true

# ユーザの分離を有効化
# https://docs.microsoft.com/en-us/iis/configuration/system.applicationhost/sites/site/ftpserver/userisolation/
Set-ItemProperty "IIS:\Sites\$ftpsite" -Name ftpserver.userisolation.mode -Value 3

# FTPユーザの権限を付与
Add-WebConfiguration "/system.ftpServer/security/authorization" -value @{accessType="Allow";roles="";permissions="Read,Write";users="*"} -PSPath IIS:\ -location $ftpsite

# AWSでパッシブモードにすると外部から接続できないので、外部向けのIPアドレスを設定する
# https://docs.microsoft.com/en-us/iis/configuration/system.applicationhost/sites/site/ftpserver/firewallsupport
cmd /c \Windows\System32\inetsrv\appcmd.exe set config -section:system.applicationHost/sites /siteDefaults.ftpServer.firewallSupport.externalIp4Address:$publicip /commit:apphost

# パッシブポートのレンジを制限
# https://docs.microsoft.com/en-us/iis/configuration/system.ftpserver/firewallsupport
cmd /c \Windows\System32\inetsrv\appcmd.exe set config -section:system.ftpServer/firewallSupport /lowDataChannelPort:"60000" /commit:apphost
cmd /c \Windows\System32\inetsrv\appcmd.exe set config -section:system.ftpServer/firewallSupport /highDataChannelPort:"65535" /commit:apphost

# サイトを再起動
# Restart-WebItem "IIS:\Sites\$ftpsite"

# サービスの再起動
Restart-Service ftpsvc
```

続いてFTP接続に使用するユーザを作成し、ホームディレクトリを用意する。
ついでにアクセス権を制限する。

```powershell
# ユーザ名
$username = "FTPUSER"

# ランダムパスワードの生成
$number = 48..57
$upper = 65..90
$lower = 97..122
$password = (1..10 | foreach { $number + $upper + $lower | get-random } | foreach { [char]$_ }) -join ''

# パスワードの暗号化
$secure = $password | ConvertTo-SecureString -AsPlainText -Force

# ローカルユーザの追加
$user = New-LocalUser -PasswordNeverExpires -Name $username -Password $secure -Description "FTP User"

# パスワードの表示
Write-Host -ForegroundColor red $password

# グループの追加
Add-LocalGroupMember -Group "Users" -Member $user

# FTPUSERのホームディレクトリ
$dir = mkdir C:\inetpub\ftproot\LocalUser\$username

# ディレクトリのアクセスルールをすべて削除
icacls $dir /reset /q # 個別設定を破棄
icacls $dir /inheritance:r /q # 上位フォルダからの継承を破棄

# アクセス権を追加
icacls $dir /grant "administrators:(OI)(CI)F" /q
icacls $dir /grant "${username}:(OI)(CI)F" /q

# アクセス権を確認
icacls $dir
```

`Set-Acl` は割とどうしようもなく使えない子なのですが、`icacls` の構文すぐ忘れてしまうので ACL が一番思い出すのが大変です。
9/1 Tech Expert (事前学習) day 2　/　html/css終わらずヒヤヒヤ中…

【学習アウトプット】

#今日の目標(やること)
昨日勉強した分を復習がてら簡易にまとめる。
HTML/CSSを終わらせる
Ruby半分くらいまではやる！

今日はもうちょっとノウハウをみて、明日からはしっかりタイムスケジュールを組もうと思う。


##昨日のまとめ

ページの構成を全て「箱とテキスト」して捉える
HTMLで文字や画像などの骨組みコンテンツツールをかきだし（陣地取り。ブロック。箱。）
CSSで色を大きさ、配置etcを整理してその“箱”を装飾
箱ごとに役割分担がある。（見出し、段落、リスト、画像etc）


“タグ”を使って箱の種類を表す
見出しタグ→&lt;h1&gt;〇〇&lt;/h1&gt;
段落タグ→&lt;p&gt;〇〇&lt;/p&gt;
リストタグ→&lt;li&gt;〇〇&lt;/li&gt;
画像タグ→&lt;img&gt;
etc...

開始タグ< >と終了タグ</ >で囲まれるものと、
終了タグ無しで、開始タグのみのものとがある


###HTML構造
head要素とbody要素で成り立つ。
head要素:サイト全体にかかる、設定事項（言語の種類タグとか『このサイトはHTMLで構成されてるからね！』とブラウザに宣言するタグとか諸々）
body要素:目に見える部分。(見出しや文章、画像など、サイトの見た目そのまんま。)


<要素名 "属性名"=属性値>
例）
【リンク】 a href ="http://〇〇"       
【その文章に関する情報】 meta charaset ="UTF-8"
【画像】img src = "〇〇"　alt = "〇〇（画像の説明）"


####コメント
&lt;!-- 〇〇 --&gt;

####head要素
title
meta
link
script(java script)
etc...

####body要素
(CSSとHTMLのイメージ勉強の為、大幅割愛)

“箱”の中に“箱”を入れることが出来、それぞれ親要素、子要素と表す。


####HTMLの箱の種類
ブロック要素:長方形の長い箱　div要素
インライン要素:一部範囲（連続して横に並べられる）　span要素

###CSS
HTMLファイルにCSSファイルを結びつける必要がある。
→htmlのheadに
　&lt;link rel="stylesheet" href="style.css"&gt;

例)
h1{color:red;}
(htmlファイル内のh1のcolerをredに。)

####idとclass(属性)
htmlの“箱”とCSSを結ぶ役割。（htmlとcssで名を合わせる）
<ul><li>idセレクタ(同じid名、文中で一回のみ)
　　htmlでは　id="〇〇"
　　cssでは　#〇〇　　　　　　　と記載
<li>classセレクタ(同じクラス名、文中で何度でもつかえる)
　　htmlでは　class="●●"
　　cssでは　.●●　　　　　　　と記載 </ul>

####cssでの余白の指定
 border
 padding(borderより内側)
 margin(borderより外側)

余白の設定を指定しなくても、ブラウザで余白ができてしまっていることがある。
→デフォルト設定の可能性が。 nomalize.cssを使用。
&lt;link rel="stylesheet" href="normalize.css"&gt;
&lt;link rel="stylesheet" href="style.css"&gt; 
(style.cssより先に読み込ませたいから、その上に。)

##今日のまとめ
###CSS
セレクタ { プロパティ: 値; }

<ul><li>「box-sizing」プロパティ
　　「border-box」値　ボックス全体の大きさを変えず「内側」に余白を作る。（paddingだと、paddingの分だけ要素全体が大きくなった上で余白がつくられてしまう。）
<li>「*」セレクタ　全ての要素
<li>「color」プロパティ　フォントの色を指定
<li>「text-align」プロパティ　横方向での位置を指定
<li>「font-size」プロパティ　フォントサイズを指定
<li>「letter-spacing」プロパティ　文字の間隔を調整
<li>「display」プロパティ
　「inline-block」値　要素を横並びにした上で横幅と高さを指定することができます。
　「flex」値　指定した要素の子要素を横並びにします。
<li>「border-radius」プロパティ　四角形の角を丸くする
<li>「text-decoration」プロパティ
　「none」値　通常リンクには下線が引かれますが、今回は不要なためnoneを指定す
<li>「background」プロパティ　背景画像
　「url('〇〇/jpg')」値　画像の指定
　「fixed」値　スクロールしても固定される
<li>「background-size」プロパティ　背景画像の大きさ
　「auto」値  サイズは自動的に決まる
　「contain」値　縦横比を保ったまま、範囲内に全ての画像が入るように配置（縦か横に空白ができる） 
　「cover」値 　縦横比を保ったまま、対象範囲を全て埋めるように配置（画像の縦かよこが切れる）
　「px」値 縦横を長さで指定 
　「%」値 縦横を親要素に対する比率で指定 
<li>「margin」プロパティ 
<li>「line-height」プロパティ 行の高さを指定する
<li>「text-align」プロパティ　〇〇揃え

作品全体をworks-wrapperというクラスを持つ要素で囲って、その中のwork-boxで作品を表示しています。
そして、親要素であるworks-wrapperにdisplay: flexを当てています。

<li>「border」プロパティ　要素の周りに線を引く
　「none」値　なし（何も指定しないとnoneになる）
　「solid」値　１本線
　「dashed」値　破線
　「dotted」値　点線

**(下記「float」理解度５０％位。ムービー付きで説明されているから、繰り返し復習しよう。今は先にすすもう。)**
「float」プロパティ　その親要素の中で横並びに
　「left」値
 .clearfix:after
content: "";
clear: both;
display:block


##〜独り言(まとめやら感想やら)〜
html/css→もうひと押しで終わりだが、思考がついていかない為ここで打ち切ろ。
理解そのものが出来ず、進みがとても遅い…慣れて追い上げていければいいんだけど…
明日こそはhtml/css終わらせてRubyにとりかからなきゃ（汗）
Akka HTTPの Directive (path や parameter)で 独自に定義したクラスに変換する

# 願望
`Int` や `Long` などの プリミティブ型 ではなく 独自に定義した [値クラス](https://docs.scala-lang.org/ja/overviews/core/value-classes.html) などを Akka HTTP の `route` 定義で使いたい

（意図しない使用を回避するため）


# 独自に定義したクラス
```scala
final case class AccountId(value: Long) extends AnyVal
final case class Amount(value: Int) extends AnyVal
```

# 改善前
プリミティブ型なので、独自定義の型への変換を自分でやる必要がある


## Path
```scala
pathPrefix("account" / LongNumber) { rawAccountId: Long =>
  val accountId = AccountId(rawAccountId)
```

## Parameter
```scala
parameter("amount".as[Int]) { rawAmount: Int =>	
  val amount = Amount(rawAmount)
```

# 改善後
Akka HTTPが型変換をするので、プリミティブ型は登場しない。

## Path
`PathMatcher1[T]` の [def map\[R\](f: T ⇒ R): PathMatcher1\[R\]](https://github.com/akka/akka-http/blob/v10.1.9/akka-http/src/main/scala/akka/http/scaladsl/server/PathMatcher.scala#L157) を使用して型を変換

```scala
pathPrefix("account" / LongNumber.map(AccountId.apply)) { accountId: AccountId =>
```

### 各型の対応
- `T` → `Long`
- `R` → `AccountId`


## Parameter
`NameReceptacle[T]` の [def as\[B\](unmarshaller: Unmarshaller\[T, B\])](https://github.com/akka/akka-http/blob/v10.1.9/akka-http/src/main/scala/akka/http/scaladsl/common/NameReceptacle.scala#L17) を使用して型を変換

※ `Unmarshaller[T, B]` が必要なので、 `Unmarshaller.strict[A, B](f: A ⇒ B): Unmarshaller[A, B]` を使用して作成

```scala
implicit class ToNameUnmarshallerReceptacleEnhancements(name: String) {
  def asAmount: NameUnmarshallerReceptacle[Amount] =
    name.as[Int].as[Amount](Unmarshaller.strict(Amount.apply))
}
```
```scala
parameter("amount".asAmount) { amount: Amount =>
```

### 各型の対応
- `T` → `Int`
- `A` → `Int`
- `B` → `Amount`
月度、年度取得アルゴリズム

## 【目的】
年月日関連アルゴリズムの考察。

## 【前提】
大抵の環境、プログラム言語には年月日演算処理（ライブラリ、標準関数）が用意されている。
従って、例えば ``日 + 1`` は単純な足し算ではなく、その環境で用意されている標準関数を通して加算するものとする。

## 【月度の求め方】
仮に締め日を 20日とし、1月1日～20日は 1月度、1月21日～末日は 2月度とする。
月日から月度を求める方法は幾つか考えられる。
前述の仕様をそのままコードに起こせば以下になる。

```
if (月日の日 <= 20) {
    月度 = 月日の月;
} else {
    月度 = 月日の月 + 1;
}
```

しかし式で書けば以下のようにシンプル。条件分岐は不要。

```
月度 = (月日 - 20日 + 1ヶ月) の月;
```

## 【年度の求め方】
こちらはもっと簡単。

```
年度 = (年月 - 3ヶ月) の年;
```

## 【末日の求め方】
ついでに。こちらは有名か。

```
末日 = (年月日の翌月の1日) - 1日;
```

## 【アメリカ大統領選挙日のアルゴリズム】
アメリカの大統領選挙日は原則 11月の第1火曜日。
しかし、もしそれが 1日だと月初で色々とアレなので翌週の火曜日となる。
この選挙日が法律上、どのように定義されているかご存じだろうか？
それは以下。実に単純明快。


[選挙の日 (アメリカ合衆国)](https://ja.wikipedia.org/wiki/%E9%81%B8%E6%8C%99%E3%81%AE%E6%97%A5_(%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%E5%90%88%E8%A1%86%E5%9B%BD) "選挙の日 (アメリカ合衆国)")
> 11月の第1月曜日の翌日の火曜日に設置される。

素晴らしい、素晴らし過ぎる。
単に「11月の第1月曜日の翌日」でも良い。
「翌日」であるから 1日はあり得ない。
月曜日の翌日は火曜日であることは自明。
このアルゴリズムの面白いところは、火曜日の定義なのに「火曜日」が含まれない（含めなくても良い）こと。
これが 150年も前に制定されているという。昔の人は頭が良かったんだねぇ（小並感）。
年月日アルゴリズムの良いお手本として記憶に留めたい。
Scala関数型デザイン＆プログラミング  forever関数でのStackOverflowErrorについて

書籍「[Scala関数型デザイン＆プログラミング](https://book.impress.co.jp/books/1114101091)」の第13章「StackOverflowErrorの回避」の冒頭で```lazy```を利用したforever関数の実装が例として出されているのですが、この箇所(だけとは言わず書籍全体を通して）は頭の中だけで理解しようとすると難解なので、処理イメージをまとめてみました。

書籍では次のコードが記載され、以下のように述べられています。
（以下、[Scala関数型デザイン＆プログラミング](https://book.impress.co.jp/books/1114101091)の第13章「StackOverflowErrorの回避」より引用）


>
```scala
val p = IO.forever(PrintLine("Stillgoing..."))
```

>p.runを評価すると、数百行の情報が出力された後、プログラムがStackOverflowErrorでクラッシュします。スタックトレースを調べてみると、runが自身を繰り返し呼び出していることがわかります。問題はflatMapの定義にあります。

>
```scala
def flatMap[B](f:A => IO[B]): IO[B] = new IO[B] { def run = f(self.run).run }
```

ここで、上記のforever関数は以下のように定義されています。

>
```scala
def forever[A, B](a: F[A]): F[B] = {
    lazy val t: F[B] = a flatMap (_ => t)
    t
}
```

また、PrintLineは以下のように定義されています。

>
```scala
def PrintLine(msg: String): IO[Unit] = IO { println(msg) }
```


なので、上記のIO.foreverは次のように展開できます。

```scala
lazy val t = PrintLine("Stillgoing...") flatMap (_ => t) 
t 
```

=>

```scala
lazy val t = new IO[Unit] { def run = println("Stillgoing...") } flatMap (_ => t) 
t
```

以下の説明では、上記の```new IO[Unit]  { def run = println("Stillgoing...") }```を便宜上、```self```と置きます。
また、forever関数内で呼び出されるflatMapの引数```(f:A => IO[B])```に渡される実引数は　```(_ => t)```です。```(_ => t)```の```_```は、```self.run```の結果とみなせるので、```_```を```self.run```に置き換えてみます。（実際はコンパイルエラーとなりますが、```self.run```が呼び出されることをイメージするため、このように表記します）
そうすると、上記の式は以下のように置き換えられます。

```scala
lazy val t = new IO[B] { def run = ((self.run) => t).run } 
t
```

なので、IO.foreverで取得したIOモナドのrunは以下のように読み替えられます。

```scala
IO.forever(PrintLine("Stillgoing...").run
```

=>

```scala
new IO[B] { def run = ((self.run) => t).run }.run
```

ここで、```t```は```lazy```による宣言がなされています。lazy修飾子がついた変数は初回アクセス時の結果をキャッシュし、以降の参照ではそのキャッシュした値を返します。

```lazy```により、```new IO[B]```のインスタンス生成は一度しか行われないので、２回目以降の```IO[B]```は便宜上、```cachedIO```と置きます。これまた便宜上、呼び出し回数を表すためにcachedIOの後ろに数字を付け足して、```cachedIO(N)```のように表記します(Nは呼び出し回数）。(cachedIOのインスタンス自体は全て同一インスタンス）
そうすると、上記の式は以下のように置き換えられます。

```scala
new IO[B] /* ( = cachedIO(0)) */ { def run = ((self.run) => cachedIO(1) { def run = ((self.run) => cachedIO(2) { def run = ((self.run) => cachedIO(N)...)...).run }).run }).run }.run
```

```new IO[B]```のrunを実行するには、cachedIO(1)のrunを実行する必要があります。
cachedIO(1)のrunを実行するには、cachedIO(2)のrunを実行する必要があります。
以下同様に、cachedIO(N)のrunを実行するには、cachedIO(N+1)のrunを実行する必要があります。
このように```new IO[B]```のrunを実行するためには、自身のrunを内部で繰り返し呼ぶ必要があります。その結果、入れ子のrun呼び出しがスタックに積み上げられていくことになります。
これがStackOverflowErrorが発生する原因です。

これを回避するために**トランポリン化**という手法があり、それを使えばStackOverflowErrorが起こらなくなります。これについては、また別の機会で触れたいと思います。
GithubにSSH鍵登録

#はじめに
＜本記事の対象者＞
・リモートリポジトリにGithub、開発環境にCloud9を使用
・GithubにSSH鍵登録ができなくて先に進めなくて困ってる
方に向け、引っかかってしまいやすい部分について書き記したものになります。

＜前提条件＞
・Githubの登録は済んでいる
・Githubでリポジトリ（リモートリポジトリのこと）を作成している


#さっそく登録していこう！
流れとしては
①Cloud9にて公開鍵を作成
②Github上で設定から①で作成した鍵を登録
③Githubへ接続ができるか確認
となります。


###①まずはCloud9で公開鍵を作成します。
ターミナルにて

```
$ cd ~/.ssh
$ ssh-keygen
```
と入力すると以下のように聞かれますがここは入力せず全てEnterでかまいません。

```
Enter file in which to save the key(/home/ec2-user/.ssh/id_rsa):
```
```
Enter passphrase (empty for no passphrase):
```

```
Enter same passphrase again:
```


###②Github上で設定から①で作成した鍵を登録
次に、[Githubのssh設定](https://github.com/settings/ssh)からSSH鍵の登録を行います。
![SSH鍵設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404519/4acd04f4-8cb9-1d90-afff-8bdad3a77191.png)
右上の「New SSH Key」から鍵の登録を行います。

![SSH鍵登録画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404519/1fb1a306-09b0-13ea-0320-7a9d645c648c.png)
ここでのポイント
・「Title」はなんでもいい。
分かりやすく「名前_ssh_pub」なんかにしてみてもいいかと思います。
・「Key」に先ほど作成した公開鍵をコピーしてきて貼り付ける。
貼り付ける部分は「ssh-rsa」から最後の「@cloud9.amazon.com」までとなります。

そして「Add SSH Key」を押下して作成完了です！

登録が完了したら以下の画面になります。
![SSH鍵が登録された画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404519/34c5ebca-5ca6-dfdf-100a-158d92abc3ac.png)

#登録ボタンを押した後「Key is Invalid. You must supply in OpenSSH public key format」と表示された場合
![SSH鍵が無効と言われた場合](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404519/72a0945a-bee0-b971-b21a-8a5146f93881.png)

上記画像の通り警告が出た方へ。このエラーは日本語訳すると、「鍵が無効です。OpenSSH公開鍵形式で提供する必要があります。」と言う意味になります。

これはつまり”鍵の形式が正しくない”ことが原因です。

もう一度鍵の入力画面をみてみると、以下のような注意書きがありました。
![SSH鍵登録の注意点](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404519/a847a988-c395-ec4c-06f5-9c08f7a9bcea.png)

改めて登録しようとしたSSH鍵の文字を確認してみてください。登録する部分は
**「ssh-rsa」から最後の「@cloud9.amazon.com」まで**
です。この範囲が公開鍵の「内容」となりますのでただしくコピーしてから貼り付けましょう！

#最後にGithubに接続できるか確認
鍵が登録できたら、Githubに接続できるか確認をしましょう。

```
$ ssh -T git@github.com
```
を入力します。

```
Are you sure you want to continue connecting (yes/no)?
```
と聞かれるのでyesと答えましょう。

その後次のように表示されたら接続は完了です！
お疲れ様でした。

```
Hi (アカウント名) You've successfully authenticated, but Github does not provide shell access.
```
スポットライト効果をMATLABで

今年の MATLAB EXPO で、ポスターセッションの順位発表の時に以下のようなスポットライト効果を使ったプログラムを使いました。
![spotlight.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194780/2c91280e-c0d4-0754-5a6c-4f2ce7a46cea.gif)
このコードを解説してみます。
##背景画像
まず、簡単なのは１から１４の数字を書いた背景の画像です。（今年は14個のポスターが展示されていました。）

```matlab
im = imread('num_grid_large.png');
imshow(im)
```
![simple_anim_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194780/55f76f7b-4c24-735a-bbd7-d388dad733b2.png)
##軌跡座標
この14個の数字の位置を４ｘ４の行列とすると、スポットライトを移動したい位置を次のようにランダムに定義します。実際は`rand`関数を使いました。

```matlab
x = [2 4 2 1 3 1 4 2 3];
y = [4 1 2 1 2 4 3 3 1];
```
この軌跡を直接描画してみると

```matlab
% 画像の大きさに合わせてスケーリング
img_scale = [size(im,2) size(im,1)]/5;

hold on
plot(x*img_scale(1),y*img_scale(2),'o-')
hold off
```
![simple_anim_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194780/c7d740a0-308d-2f2e-1cfa-cc017163890d.png)
##スプライン補間
ただ、このままだと滑らかな動きにはなりません。

そこでスプライン補間を使って滑らかの曲線になるようにします。

```matlab
num_points = length(x);

xx = interp1(1:num_points,x,1:0.05:num_points,'spline');
yy = interp1(1:num_points,y,1:0.05:num_points,'spline');

imshow(im)
hold on
plot(xx*img_scale(1),yy*img_scale(2))
plot(x*img_scale(1),y*img_scale(2),'o')
hold off
```
![simple_anim_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194780/6b05ca76-44fd-4bb7-f8a7-7232aa202064.png)
##ROI オブジェクト
あとはスポットライト効果を作るだけです。

今回は Image Processing Toolbox の ROI 機能を使います。ROI 機能では様々な図形で関心領域を定義することができ、その領域の面積を計算したり、マスクを作成したりすることができます。ここでは```drawellipse```関数で楕円 ROI を作成します。

```matlab
hh = imshow(im);
h = drawellipse('AspectRatio',1,'Center',[xx(1), yy(1)] .* img_scale,'SemiAxes',img_scale/2);
```
![simple_anim_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194780/aa8e5197-1c83-faef-4ea7-ca04f464802e.png)
##マスク作成
ROI オブジェクトのマスク機能で楕円（円）部分を切り取るマスクを作成し、もとの画像と掛け合わせることによってスポットライト完成！

```matlab
BW = createMask(h);
new_im = im .* uint8(BW);
imshow(new_im)
```
![simple_anim_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194780/a2def7b7-a7c1-5bec-f338-8f159f78eb5e.png)
##`for`ループ
あとは、```for```ループを使ってこの作業を軌道のデータ点ごとに繰り返すだけです。参考までに全コードです。

```matlab
im = imread('num_grid_large.png');
hh = imshow(im);

x = [2 4 2 1 3 1 4 2 3];
y = [4 1 2 1 2 4 3 3 1];

num_points = length(x);

xx = interp1(1:num_points,x,1:0.05:num_points,'spline');
yy = interp1(1:num_points,y,1:0.05:num_points,'spline');

img_scale = [size(im,2) size(im,1)]/5;
h = drawellipse('AspectRatio',1,'Center',[xx(1), yy(1)] .* img_scale,...
    'SemiAxes',img_scale/2,'Visible','off');

for id = 1:length(xx)
    h.Center = [xx(id), yy(id)] .* img_scale;
    BW = createMask(h);
    hh.CData = im .* uint8(BW);
    drawnow
end
```
![spotlight.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194780/d47de536-c91c-7770-94e1-0c53808b54f3.gif)

##おまけ
もちろん色画像でもできます。
![spotlight_flower.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194780/777223c5-d309-ad98-8493-938e34cf65ed.gif)
macOS10.12でGTX1080を動かす

**公式eGPUではないので自己責任です**

環境
========
- MacBookPro 15″, 2016
  - macOS Sierra 10.12.6
- [Razer Core X](https://www2.razer.com/jp-jp/gaming-systems/razer-core-x)
  - [GeForce GTX1080](https://jp.msi.com/Graphics-card/GeForce-GTX-1080-GAMING-X-8G.html)

インストール
========
導入はインストールスクリプトを実行するだけです。

**SIP解除**
SIPを無効化します
https://qiita.com/zaburo/items/c650cda45c858fe856a9

**インストールスクリプト**
https://egpu.io/ から環境にあったものを選択
OSが10.12なので `automate-eGPU.sh` を選択
  ![egpu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20773/a6185623-4e84-905b-3d70-0a8c09d36f2d.png)

遷移先にも手順がありますが、curlでシェルスクリプトを落として実行するだけです。
このスクリプトは接続されているグラフィックボードを検出してドライバーのインストールまでをよしなに行ってくれるものです。なので実行時は外部GPU（Razer Core）をつないでおきます。

```
curl -o automate-eGPU.sh https://raw.githubusercontent.com/goalque/automate-eGPU/master/automate-eGPU.sh && chmod +x automate-eGPU.sh && sudo ./automate-eGPU.sh
```
途中の質問は yes で大丈夫です。

**外部ディスプレイをメインに指定する**
インストールが完了したら システム設定＞ディスプレイ から外部ディスプレイをメインに指定します
![display.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20773/2882177b-f2f1-ca58-f570-7e504f19e8f4.png)

再起動させます。

外部GPUを確認する
========
システム情報で認識しているか確認

![システム情報](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20773/b8e7ac66-351a-0d20-5b99-6975b9423d49.png)

以上です。SIPを戻しておきましょう。

導入自体は手軽ですが、起動後に外部GPUつないでも認識しないとか結線が抜けるとMacの電源が落ちるなどあったりはします。とはいえGTX1080のパワーが得られるのでそのへんは致し方なしですかね。
【Googleフォーム自分用メモ】GoogleフォームのCSSカスタマイズ方法

##Googleフォーム概要
- Googleフォームは、Googleが無料で提供するアンケート作成＆集計ツール。
- Googleのアカウントさえ持っていれば利用でき、ブラウザ上で簡単な操作をするだけでアンケートやコンタクトフォームを作成できる。[Googleフォーム公式](https://www.google.com/intl/ja_jp/forms/about/)

## デメリット
- ブラウザ上で作成したフォームではデザインに限界がある。

しかし、Googleフォームに自身のCSSを適応させる事で、最適なレイアウトで作成できデメリットも無くなる。

## 設定方法
1. HTMLで作成したフォームと同じ構図のフォームをGoogleフォームで作成する。
2. Googleフォーム画面でChromeの検証機能を使い、Googleフォームの「Action(formResponseで終わるURL)」と「各inputのnameの値(entry.xxxxxの箇所、リンクを展開していくとわかりやすい)」を取得し、HTMLフォームに挿入する。
3. ActionURLと各inputのnameの値をHTMLのフォーム画面に追記する。


以上で動かすことはできるが、「送信ボタン」を押すとGoogleフォームのサンクスページに遷移する為、自作のサンクスページにリンク先を変更させる。 今回はjQueryのajaxを使用した。作成したinputページに以下のjQueryを追加する。

```javascript
function postToGoogle() {
//フォームの値を取得
var field1 = $('[name="entry.xxxxxxxx"]').val();
var field2 = $('[name="entry.yyyyyyyy"]').val();

$.ajax({
url: "googleフォームのactionの値",
data: {"entry.xxxxxxxx": field1,"entry.yyyyyyyy": field2
},
          type: "POST",
          dataType: "xml",
          statusCode: {
              0: function() {
                  //Success message
location.href="サンクスページのパス";
              },
              200: function() {
                  //Success Message
location.href="サンクスページのパス";
              }
          }
      });
      }
```
送信ボタンに関数を設定する

```html
<input type="button" onClick="postToGoogle()" value="送信">
```
##あとがき
GoogleフォームのCSSカスタマイズ方法を自分用に忘れない為にまとめました。
Googleフォームはスプレッドシートと紐付けてデータの管理が容易にできるので、この方法は覚えておいて損はなさそうですね:thinking:
Node.jsからFace APIをバイナリデータで扱うメモ - axios編


requestモジュールで行う実装例は前に書いてましたが、axiosで使いたくなったのでメモっておきます。 あと、 **バイナリデータで直接アップロードが出来る**という噂を聞いて調べてみたら出来たので記録しておきます。前はFace APIはURL指定のみだと思ってました苦笑

> Face APIについてなどはこちらを参考に。
> [Node.jsでAzure Face APIを使ってみる](https://qiita.com/n0bisuke/items/67e49a574e9e7e98ac87) (request編)

## URL指定でaxiosから

```bash
$ npm i axios
```

```app.js
'use strict';

const axios = require('axios');
const qs = require('querystring');

// Face APIのキーを指定
const subscriptionKey = 'キーの指定';
// 確認したい画像を指定
const imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/3/37/Dagestani_man_and_woman.jpg';

const BASE_URL = 'https://westcentralus.api.cognitive.microsoft.com';
const params = qs.stringify({
    'returnFaceId': 'true',
    'returnFaceLandmarks': 'false',
    'returnFaceAttributes': 'age,gender,headPose,smile,facialHair,glasses,' +
    'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise'
});
const PATH = `/face/v1.0/detect?${params}`;

const config = {
    baseURL: BASE_URL,
    url: PATH,
    method: 'post',
    headers: {
        'Content-Type': 'application/json',
        'Ocp-Apim-Subscription-Key' : subscriptionKey
    },
    data: {
        url: imageUrl
    }
};

axios.request(config)
.then((res) => {
    console.log(res.status);
    console.log(res.data)
})
.catch((error) => {
    console.log(error.response.data);
});
```

## バイナリデータ指定

`app.js`と同じ階層に`text.png`が置いてある想定です。
[この辺](https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236)を参考に、Header情報を`application/octet-stream`に変更し、dataにバッファーオブジェクトをそのまま指定することで使えました。

```app.js
'use strict';

const axios = require('axios');
const qs = require('querystring');
const fs = require('fs');

// Face APIのキーを指定
const subscriptionKey = 'キーの指定';
// 確認したい画像を指定
const filePath = `./test.png`;

const BASE_URL = 'https://westcentralus.api.cognitive.microsoft.com';
const params = qs.stringify({
    'returnFaceId': 'true',
    'returnFaceLandmarks': 'false',
    'returnFaceAttributes': 'age,gender,headPose,smile,facialHair,glasses,' +
    'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise'
});
const PATH = `/face/v1.0/detect?${params}`;

const content = fs.readFileSync(filePath); //画像読み込み
const config = {
    baseURL: BASE_URL,
    url: PATH,
    method: 'post',
    headers: {
        'Content-Type': `application/octet-stream`, // URL指定の時は'application/json'
        'Ocp-Apim-Subscription-Key' : subscriptionKey
    },
    data: content
};

axios.request(config)
    .then((res) => {
        console.log(res.status);
        console.log(res.data)
    })
    .catch((error) => {
        console.log(error.response.data);
    });
```
cssのbefore, afterによる疑似要素について

#前置き

3記事目です。
日々学ぶことだらけのプログラミング初心者@mt_taiと申します。

この記事では、cssの疑似要素について少し学習したことをまとめていきます。
今回は少なめです。

#cssの疑似要素とは

cssでの疑似要素とは `::before` `::after` を用いることで、指定した要素の前後に新たな要素を挿入できるセレクタです。

まずは簡単な使い方の例を示します。

```html:sample.html
<body>
    <p>Hello World</p>
</body>
```
```css:sample.css
body p::after {
    content: "!";  /* "Hello World"の後ろに"!"を追加 */
}
```

結果は以下のようになります
![sample.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483451/d34520ff-6b41-b073-a969-52a158f25109.png)

htmlでは`Hello World`としか記述していませんが、cssで`!`を要素の後ろに追加したので
表示結果は`Hello World!`となっています。

`before`で要素の前に新たな要素を挿入、`after`で要素の後に新たな要素を挿入できます。
この疑似要素の利点として、元のhtmlコードの可読性を維持したままページの整形が行えます。
また、上記例のように、単純に文字を挿入することはもちろん、画像やurlを挿入することも可能です。

ただ、画像を挿入した場合はサイズ指定が不可能となっているので、
以下のように`background-image`で背景として挿入することでその問題点を回避できます。

```css:sample2.css
body p::after {
    content: "";  /* contentで何も入れず、疑似要素を実体化 */
    display: "inline-block";  /* blockかinline-blockに指定しないと、幅と高さの指定ができない */
    width: 100px;  /* 幅の指定 */
    height: 100px;  /* 高さの指定 */
    background-image: url("画像のurl");  /* 背景として画像を指定 */
}
```

疑似要素自体の幅と高さの変更は可能なので、この方法で画像のサイズ指定と同じ振る舞いができるわけですね。

うまく設定すれば、いろんな図形や、特定のボーダーラインなどが作れるみたいです。
htmlコードの方でごちゃごちゃしなくて済むのはありがたいですね。
（とくに私みたいな初心者は汚いコードを安易に量産してしまうので…）

ちなみに、例では`before`と`after`の手前につけるコロンは2つで統一していますが、
cssの最新規格である**CSS3**では2つ(`::`)であるのに対し、以前の**CSS2**では1つ(`:`)です。
そのため、対象にしているブラウザでコロンの数を使い分けるか、とりあえず多くのブラウザで適用させたいのであればコロンは1つにしておくのが良いのかもしれません。

#終わりに
今回はcssの疑似要素について、本当に基本的な部分をまとめました。
疑似要素の他にも疑似クラスが存在します。こちらも便利なものですが、まだ学習できていない部分も多いので、引き続き学習を進めていきたいと思っています。
cssはセレクタやプロパティの理解が深まれば、その分複雑な表現が可能となってくるので、表現の幅を広げるためにもしっかり理解を深めていきたいです。
Photoshop document.duplicate()で意図しないドキュメントが複製される

ちょっとハマったのでメモ。
ちなみに検証しているPhotoshopのバージョンはCC2019(v20.0.6)です。

# Photoshopスクリプトでのdocument.duplicate()
document.duplicate()は名前の通り、複製のためのメソッドです。

[Photoshop CC JavaScript Reference](https://www.adobe.com/content/dam/acom/en/devnet/photoshop/pdfs/photoshop-cc-javascript-ref-2019.pdf)での記述は以下の通り

> Creates a duplicate of the document object.
The optional parameter name provides the name for the duplicated document.
The optional parameter mergeLayerOnly indicates whether to only duplicate merged layers.

google先生の翻訳
> ドキュメントオブジェクトの複製を作成します。
オプションのパラメータ名は、複製されたドキュメントの名前を提供します。
オプションのパラメーターmergeLayerOnlyは、マージされたレイヤーのみを複製するかどうかを示します。

普通にドキュメント複製される、ということですね。
使い方は以下の通り。

```duplicate_sample.jsx
// 現在のアクティブドキュメントを取得
var document = app.activeDocument;

// documentが「copy.psd」として複製される
var copy_doc = document.duplicate("copy.psd");

```
ちなみにこのサンプルは正常に動きます。

# 意図しないduplicate()の挙動
遭遇したduplicateの挙動は***activeDocumentではないドキュメントを複製(duplicate)しようとすると、activeDocumentが複製される***というもの。

具体的な流れは以下の通り

1. A.psdを開く
2. A.psdにリンクされているB.psdを開く(この時点で一度activeDocumentはB.psdに移る)
3. B.psdはそのまま、一度明示的にA.psdにactiveDocumentを移す
4. B.psdを複製しようとする
5. ***A.psdが複製される***

なんでこんな面倒なことしているんだ、という話は長くなるので割愛します。
具体的なコードの例は以下の通り。

```jsx
var document = app.activeDocument;
var root_layers = document.layers;

var link_docs = [];

for(var i=0;i<root_layers.length;i++)
{
  var layer = root_layers[i];

  // SmartObjectかチェックする
  if(layer.kind!= LayerKind.SMARTOBJECT) continue;
  
  // SmartObjectを開く
  app.activeDocument.activeLayer = layer;
  var idplacedLayerEditContents = stringIDToTypeID( "placedLayerEditContents" );
  var desc3 = new ActionDescriptor();
  executeAction( idplacedLayerEditContents, desc3, DialogModes.NO );

  // 現在のactiveDocumentを取得
  var link_doc = app.activeDocument;

  // リンクしてあるpsdかチェック
  var document_path = link_doc.fullName.toString();
  if(document_path != undefined 
    && document_path.indexOf(Folder.temp) == -1)
  {
    // リンクされているドキュメントを一時的に保存しておく
    link_docs.push(link_doc);
  }
}

// 諸々な都合のため一度元のdocumentにactiveDocumentを戻す
app.activeDocument = document;

for(var i=0;i<link_docs.length;i++)
{
  var link_doc = link_docs[i];
  alert(link_doc.name); // この時点では正しい「リンクされているドキュメント名がアラートで表示される」
  link_doc.duplicate(); // document(元の親psd)が複製されてしまう
}
```

解決策は、***複製したいドキュメントをちゃんとactiveDocumentにする***ということです

```jsx
for(var i=0;i<link_docs.length;i++)
{
  var link_doc = link_docs[i];

  // ここでちゃんとactiveDocumentにする ---------------------------
  app.activeDocument = link_doc;
  // --------------------------------------------------------

  alert(link_doc.name); // この時点では正しい「リンクされているドキュメント名がアラートで表示される」
  link_doc.duplicate(); // リンクしてあるドキュメントがちゃんと複製される
}
```
 
そんなに複雑なことをしていなければなかなか遭遇しなさそうな挙動ですが、パッと発生すると何が起こったか一瞬わからないので、要注意！
私が知らないだけでこれが正しい挙動という記述がどこかにあるのかもしれないですが、私個人としてはバグのように認識しているので、どこかのバージョンアップで修正されると嬉しいです。
Facebook Log in with React

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470484/349874ab-fb16-e66b-c977-03c273184c05.png)

3時間ほどハマったけど解決。
Before 

```
await Expo.Facebook.logInWithReadPermissionsAsync('***')
```

After

```
await Facebook.logInWithReadPermissionsAsync('***')
```

importは

```
import * as Facebook from 'expo-facebook';
```

https://docs.expo.io/versions/v34.0.0/guides/using-firebase/
officialが間違ってるとは夢にも思いませんでしたよ。
【Python】Jupyter NoteBookを使った開発環境作り

# Pythonのバージョン
２系と３系では、プログラムの書き方（文法）が違う、対応するライブラリが違う。
２系は開発終了済み。

```
[root@centos7 python]# python --version
Python 3.6.8
[root@centos7 python]# pip --version
pip 9.0.1 from /usr/lib/python3.6/site-packages (python 3.6)
```

# プログラムの実行方法
```
python プログラム名
```

# Jupyter Notebookのインストール
```
[root@centos7 python]# pip install jupyter
[root@centos7 python]# jupyter --version
jupyter core     : 4.5.0
jupyter-notebook : 6.0.1
qtconsole        : 4.5.4
ipython          : 7.8.0
ipykernel        : 5.1.2
jupyter client   : 5.3.1
jupyter lab      : not installed
nbconvert        : 5.6.0
ipywidgets       : 7.5.1
nbformat         : 4.4.0
traitlets        : 4.3.2
```
# Jupyter Notebookの基本操作
### クラウドで提供される Jupyter Notebook
Jupyter Notebookは、クラウドで提供されているものもある。
クラウド環境を使えば、インストールすることなく、ブラウザでアクセスするだけで Jupyter Notebookを使って Pythonプログラミングできる

- Azure Notebooks
- Google Colaboratory
    1. ［ファイル］→［Python3］<br><img width="931" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141308/85007792-5bd7-0d37-9a68-524cf11c7775.png">
    2. 新規作成<br><img width="851" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141308/291b870c-86ec-68de-6844-eb91ef66afb8.png">
    3. ノートブックが開く<br><img width="1201" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141308/51510f8d-966f-047b-68a5-0b43b15c2552.png">
    4. プログラムを書く<br>Jupyter Notebookでは、セルと呼ばれるテキストボックスにプログラムなどを入力する。規定では1つのセルがあるが、［＋］ボタンをクリックすると増やせる。<br><img width="489" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141308/7d08a84f-eac0-8120-0248-65a232ce7033.png">
    5. 実行する<br>実行したいプログラムが書かれたセルをクリックしてアクティブな状態にしておいて［▶︎］をクリックする。プログラムが実行され、真下にその結果が表示される<br><img width="482" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141308/d098ab60-78fd-387e-b671-d70a2970caeb.png">

# Pythonのライブラリをインストールする
## pipを使ったインストール
```
pip install ライブラリ名
```

```
[root@centos7 python]# pip install scikit-learn
```
<img width="925" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141308/0b574025-1a50-0c62-11a9-7118bf91004e.png">
入ってる

ライブラリは pipコマンドでインストールするのが基本だが、ライブラリによってはエラーが表示されることがある。Pythonライブラリには、全部Pythonで書かれたもの（Pure Python）と、C言語などで書かれたものばあり、その場合はCコンパイラなどがないとインストールできない。

CentOSだとWeb設定が必要なので、Colaboratoryを使って終わった。
cmakeエラー対処`/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfig.cmake:27`

# はじめに
cmakeを使ってビルドをする際に発生したエラーについての備忘録です。
同じ問題が発生した方は参考にしていただけたらと思います。

# 問題
cmakeの全体を表示しても意味がないので、ここではエラー部を抜粋したものを記す。

```sh:part_of_error_cmake
CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfig.cmake:27 (message):
  The imported target "Qt5::Gui" references the file

     "/usr/lib/x86_64-linux-gnu/libGL.so"

  but this file does not exist.  Possible reasons include:

  * The file was deleted, renamed, or moved to another location.

  * An install or uninstall procedure did not complete successfully.

  * The installation package was faulty and contained

     "/usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfigExtras.cmake"

  but not all the files it references.

Call Stack (most recent call first):
  /usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfigExtras.cmake:50 (_qt5_Gui_check_file_exists)
  /usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfigExtras.cmake:74 (_qt5gui_find_extra_libs)
  /usr/lib/x86_64-linux-gnu/cmake/Qt5Gui/Qt5GuiConfig.cmake:184 (include)
  /usr/lib/x86_64-linux-gnu/cmake/Qt5Widgets/Qt5WidgetsConfig.cmake:101 (find_package)
  /usr/lib/cmake/vtk-6.3/Modules/vtkGUISupportQt.cmake:17 (find_package)
  /usr/lib/cmake/vtk-6.3/vtkModuleAPI.cmake:45 (include)
  /usr/lib/cmake/vtk-6.3/vtkModuleAPI.cmake:15 (vtk_module_load)
  /usr/lib/cmake/vtk-6.3/vtkModuleAPI.cmake:132 (_vtk_module_config_recurse)
  /usr/lib/cmake/vtk-6.3/VTKConfig.cmake:80 (vtk_module_config)
  /usr/lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake:501 (find_package)
  /usr/lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake:656 (find_VTK)
  /usr/lib/x86_64-linux-gnu/cmake/pcl/PCLConfig.cmake:847 (find_external_library)
  CMakeLists.txt:15 (find_package)
```

# 対処
Qtの再インストール等試したが解決しなかった。
その後いろいろ見て回ったため参考ページはすっかり忘れてしまったが、`libglvnd`に問題があるらしく、以下でインストールの確認をした。

```sh:check_libglvnd
$ apt search libglvnd
Sorting... Done
Full Text Search... Done
libglvnd-core-dev/bionic-updates,now 1.0.0-2ubuntu2.3 amd64 [installed,automatic]
  Vendor neutral GL dispatch library -- core development files

libglvnd-dev/bionic-updates,now 1.0.0-2ubuntu2.3 amd64 [installed]
  Vendor neutral GL dispatch library -- development files

libglvnd0/bionic-updates,now 1.0.0-2ubuntu2.3 amd64 [installed,automatic]
  Vendor neutral GL dispatch library
```

どうやらインストール自体はできているらしい。
そこで、再インストールすることにした。

```sh:reinstall_libglvnd
$ sudo apt install --reinstall libglvnd*
```

各パッケージの末尾に`[installed...]`とない場合は、

```sh:install_libglvnd
$ sudo apt install libglvnd*
```

とすると良いだろう。ただ、cmakeする対象のライブラリをインストールする際に自動的にインストールされるはずなので、インストールされていなかった場合は、そもそもライブラリのインストールがされているか確認した方が良いと思われる。
愛用タブレット(Fire10)を使ってMac Book air をデュアルディスプレイにしてみた話


# デュアルディスプレイを出来るだけ安価に用意したい...

デュアルディスプレイ、いいですよね。

普段の業務では23インチのディスプレイ2台を使用していることもあり、自宅の13インチMacBookAir1台での開発に正直フラストレーションが溜まっていました。
デスクトップPC買ってデュアルディスプレイにしたいなぁと思って色々調べてみたのですが、ディスプレイだけで安いものでも20,000円以上、自分の場合ディスプレイ用のデスクから買わないといけない状況...
お財布的に厳しいな~(><)、と思いながら色々と調べてみると、タブレット端末をディスプレイとして代用する手段があるとのこと!

## Fire 10 とMacBookAirをデュアルディスプレイ接続してみる。

用意したのは以下の3つ
1.MacBookAir(2015年購入)
もちろんProやMacBookでも可能です。
2.Fire タブレット
今回はFire10を使用しましたが、調べたところFire 8などでも問題なさそうです。
3. [AirReceiver](https://www.amazon.co.jp/exec/obidos/ASIN/B00L5HQRGS)
Fire タブレット側でインストールするアプリ。305円ほどかかります。

### 手順

1. Fireタブレットにてアプリストアから[AirReceiver](https://www.amazon.co.jp/exec/obidos/ASIN/B00L5HQRGS)をインストール
2. インストールが終わったらアプリを起動してみる。
3. Mac側でAirPlay出力先にタブレットを選択する。
Fireタブレット側でMacの画面が表示されているのを確認できるかと思います。

![画像1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437085/7418215f-812e-8c82-31e0-12c48fe9beec.png)
4. (Macとタブレットで同じ画面が表示される場合) "個別のディスプレイとして使用"をクリック
![スクリーンショット 2019-09-01 23.36.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437085/268dcc26-b645-7cf0-5161-fdd28e9bfa68.png)


以上で無事デュアルディスプレイ完成です!
まさかの300円でデュアルディスプレイ環境が完成してしまいましたね。

## 使ってみた感想

- 良い点
    
1.いちいち画面を左右に行ったり来たりしなくて良いからとにかく楽
2.ストレスがかからない程度の速度で動いてくれる。
3.持ち運び可能!

- 悪い点

1. 画面サイズが小さいので細かい文字などは読みづらい。
2. 気になる人は気になるっていうレベルでタブレット側の動きはラグが発生する。(Mac側の表示は問題なし)
3. タブレット側の充電の減りが早い(体感3時間くらい。Mac側は特に影響なし)

自分は開発中のアプリの画面をリアルタイムで確認しながら開発したいためにデュアルディスプレイにしたので、その程度の用途だったら十分だな~と感じました。
もともとFireタブレットを持っていない人がわざわざ買ってデュアルディスプレイにするには不便だと思いますので、Fireタブレットユーザーの方はぜひお試しくださいm(__)m
【CoreBluetooth】キャラクタリスティックの値取得について

#概要

Bluetooth接続後のキャラクタリスティック探索結果から取得した
キャラクタリスティックを使用し値の書き込みと読み込み処理についてまとめました。

#Read

キャラクタリスティックの値の取得処理
[peripheral readValueForCharacteristic:キャラクタリスティック];
で指定したキャラクタリスティックの値を取得できます。

```
[self.get_peripheral readValueForCharacteristic:service.characteristics[i]];
```

```
//Read_結果
- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (error) {
        NSLog(@"error: %@", error);
        return;
    }
    NSLog(@"read： %@", characteristic);
}
```


#Write

キャラクタリスティックの値に書込処理
Write処理を追加すれば、キャラクタリスティックに値を書き込むことがきます。
例えば、0x01を書き込みたい場合には、中身が0x01のNSData型のデータを作り、
[peripheral writeValue:データ forCharacteristic:キャラクタリスティック  type:Property];
で書き込み処理を行います。
propertyはWrite Without Response（Bluetooth機器からレスポンスなし） か　Write（Bluetooth機器からレスポンスあり） になります。


```

int value = 0x01;
NSData *data = [[NSData alloc] initWithBytes:&value length:1];

[self.get_peripheral writeValue:data forCharacteristic:service.characteristics[i]  type:CBCharacteristicWriteWithoutResponse];
```

```
//Write_結果
-(void) peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"error: %@", error);
        return;
    }
    NSLog(@"write: %@", characteristic);
}
```

#Notify
キャラクタリスティックの値の更新時の処理
[peripheral setNotifyValue:YES forCharacteristic:キャラクタリスティック];
でBluetooth機器からデータの更新があった場合に通知を送れるようになります。
更新があった場合、Readが呼び出されます。

```
//データの更新通知_開始
[self.get_peripheral setNotifyValue:YES forCharacteristic:service.characteristics[i]];

//データの更新通知_終了
[self.get_peripheral setNotifyValue:NO forCharacteristic:service.characteristics[i]];
```

```
//通知の設定を変更した場合のみ実行
- (void) peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (error) {
        NSLog(@"error: %@", error);
    } else {
        NSLog(@"Notify_成功");
    }   
}
```


参考
https://qiita.com/shu223/items/78614325ce25bf7f4379