OmniAICreator/Qiita-1.07M huggingface dataset:
[Swift] 他の言語からやってきたひと（自分）のための、拙速Swiftコードリーディング

初めてSwiftのコードを眺めたとき、なんなく想像ができるものがあれば、全くわからないものもあります。
よくわからなかったものをあげていきます。


# `let` `var`

`let`は定数です。
`var`は変数です。

JavaScriptと同時に書いていると混乱 :sweat: 
なぜconstでないのか。。。


# `_`

Swiftは関数呼び出し時に引数名を付ける必要があります。関数宣言時に`_`を付けておくと、引数名を省略できます。

```swift:
// _ がないとき
func myFunc(arg: String) {}
myFunc(arg: "arg") // 名前付きで呼び出す

// _ があるとき
func myFunc(_ arg: String) {}
myFunc("arg") // 名前を省略できる
```

また、関数からの戻り値を捨てるときに使います。

```swift:
_ = MyFunc()
```


# `?` と `!`

使われている場所によって意味が違います。

## 変数宣言

オプショナル型(Null許容型)の変数を宣言します。

```swift
let hoge: String?
let hoge: String!
```

`!` のほうは、使うときに自動的にオプショナルが外れます。

## 変数の参照

変数がnullのときはプロパティやメソッドを呼び出しません。

```swift:
let length = hoge?.length
let upper = hoge?.toUpper()
```

## 普通の型にする

`!` を付けるとオプショナル型ではなくなります。

```swift:
let hoge: String?
let fuga: String = hoge!
```

# `$0`

省略された第1引数です。

```swift:
var doubled = myArray.map { $0 * 2 }
```

# `...` `..<`

```swift:
0...10 // 0以上10以下
0..<10 // 0以上10未満
```


# 他にもわからないものいろいろ

また調べて書こうと思います。

`internal` 
`private`
`fileprivate`
`public`
`open`
`convenience`
`weak`
`extension`
Arduino サーボ制御 LXD-227 2台連携

単体制御：https://qiita.com/kudo453/items/6f4510aea4e484e0a644

#サーボを２台連携する。(LXD-227)
サーボを向かい合わせて配置した場合の制御方法。
![DSC_6153.jpg](https://qiita-image-store.s3.amazonaws.com/0/301284/b7aca135-e645-2eea-065c-0fcd56b5581c.jpeg)

#固定する前にサーボの基準角度を決めておく。
`ANGLE_N`でサーボを固定する。これは制御用の基準角度になるので実際の制御範囲の中心である必要は無い。

#シリアルモニターから数値を入力して作動テスト
```
if (Serial.available()) {
		pulse = Serial.parseInt();
		if (pulse < ANGLE_MIN)pulse = ANGLE_MIN;
		if (pulse > ANGLE_MAX)pulse = ANGLE_MAX;
	}
```
IDEのシリアルモニターから数値を入力して動かせるようなっている。
干渉しないように最小値、最大値を設定する。
パソコンから制御したいならこのままシリアル通信をすればいい。


#制御例
```

#define SERVO_PIN1 8
#define SERVO_PIN2 9

#define CYCLE 22000
#define MIN_PULSE 1
#define ANGLE_MIN 900
#define ANGLE_MAX 1800
#define ANGLE_90 1360
#define ANGLE_0 1025
#define ANGLE_180 1695

#define ANGLE_N 1300


int pulse = ANGLE_MIN;//500-2100 (500-2500)
int _pulse = ANGLE_MAX;



void ServoWrite(int min_pulse) {
	if (_pulse - pulse > min_pulse) {
		_pulse -= min_pulse;
	}
	else if (_pulse - pulse < -min_pulse) {
		_pulse += min_pulse;
	}
	else {
		_pulse = pulse;
	}
	int _pulse2 = ANGLE_N * 2 - _pulse;
	digitalWrite(SERVO_PIN1, HIGH);
	delayMicroseconds(_pulse);
	digitalWrite(SERVO_PIN1, LOW);
	delayMicroseconds(CYCLE - _pulse);

	digitalWrite(SERVO_PIN2, HIGH);
	delayMicroseconds(_pulse2);
	digitalWrite(SERVO_PIN2, LOW);
	delayMicroseconds(CYCLE - _pulse2);
	
	
}

void ServoTest(int speed) {
	for (int i = 0; i < 150; i++) {
		ServoWrite(speed);
	}

}

void ServoSetup() {
	pinMode(SERVO_PIN1, OUTPUT);
	pinMode(SERVO_PIN2, OUTPUT);

	int speed = 20;
	
	pulse = ANGLE_MIN;
	ServoTest(speed);
	pulse = ANGLE_MAX;
	ServoTest(speed);
	pulse = ANGLE_0;
	ServoTest(speed);
	pulse = ANGLE_180;
	ServoTest(speed);
	
	pulse = ANGLE_90;
	
}

void setup() {
	Serial.begin(115200);
	ServoSetup();
	Serial.println("START");
}


void loop() {
	if (Serial.available()) {
		pulse = Serial.parseInt();
		if (pulse < ANGLE_MIN)pulse = ANGLE_MIN;
		if (pulse > ANGLE_MAX)pulse = ANGLE_MAX;
	}

	ServoWrite(MIN_PULSE);


}
```
Clojure+GraalVM

ClojureのAdvent Calndarの方で既に投稿した内容なのですが、Lambdaカスタムランタイムの話なのでこちらにも掲載させていただきます。

本文は[ClojureをGraalVMでネイティブバイナリにしてAWS Lambdaカスタムランタイムで動かす](https://qiita.com/k2nakamura/items/9475deff5ea417469ccf)をご参照ください。
Dockerでイメージダウンロードができなくなる解決法

```
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
```

といった感じでダウンロードができないときは

![2018-12-13_12h35_41.png](https://qiita-image-store.s3.amazonaws.com/0/19661/867a0a80-b452-ccf0-1fc7-7861823b4ba3.png)

dockerの設定のこれを試してみましょう
React-NativeでNews一覧（レイアウト編）

前回書いた[React-NativeでNews一覧ページを作る](https://qiita.com/kana-t/items/05d7d110ec04311574d6)のレイアウトのバリエーション。
※expo 31.0.2利用


## 完成イメージ
<img width="300" alt="スクリーンショット 2018-12-13 12.21.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/252667/0680c224-07ea-cdec-30a9-e010028806e0.png">

## Native Baseをインポート
今回は[Native Base](https://nativebase.io/)を使ってレイアウトしていきます。

```terminal:terminal
npm install --save native-base
npm install
```


## Aritcle.js
```diff:Article.js
import React from 'react';
import { View, Linking, TouchableHighlight } from 'react-native';
+import { Text, Button, Divider } from 'react-native-elements';
+import { Container, Header, Content, Spinner, Thumbnail, Left, Body, Card, CardItem } from 'native-base';

import moment from 'moment';

export default class Article extends React.Component {
  render() {
    const {
      description,
      publishedAt,
      source,
      urlToImage,
      url
    } = this.props.article;
    const { noteStyle } = styles;
    const time = moment(publishedAt || moment.now()).fromNow();
    const defaultImg =
      'https://wallpaper.wiki/wp-content/uploads/2017/04/wallpaper.wiki-Images-HD-Diamond-Pattern-PIC-WPB009691.jpg';

    return (
            <TouchableHighlight
                useForeground
                onPress={() => Linking.openURL(url)}
            >

+                <Card style={{flex: 0}}>
+                    <CardItem>
+                        <Left>
+                        <Thumbnail square large source={{uri: urlToImage || defaultImg}} />
+                        <Body>
+                            <Text style={{ marginBottom: 10 }}>
+                                {description || 'Read More..'}
+                            </Text>
+                            <View
+                                style={{ flexDirection: 'row', justifyContent: 'space-between' }}
+                            >
+                            <Text style={noteStyle}>{source.name.toUpperCase()}</Text>
+                            <Text style={noteStyle}>{time}</Text>
+                        </View>
+                        </Body>
+                        </Left>
+                    </CardItem>
+                </Card>
+            </TouchableHighlight>
    );
  }
}

const styles = {
  noteStyle: {
    margin: 5,
    fontStyle: 'italic',
    color: '#b2bec3',
    fontSize: 10
  },
};

```

## 動作確認
```terminal:terminal
expo start
```
イメージ画像のようになっていれば成功です。
Oracle Databaseで東京の地方時を表示

# はじめに
[「18分59秒をめぐって日本標準時の歴史をひもとくことに」](https://www.m3tech.blog/entry/timezone-091859)を読みまして、Oracle Databaseで東京の地方時(LMT)が表示できるかどうかを試しました。ついでに日本の夏時間対応も試しています。

# Oracle Databaseとタイムゾーン
Oracle Databaseは9i R1以降タイムゾーンのハンドリングが可能になっています。
利用可能なタイムゾーンは[IANAのTime Zone Database](https://www.iana.org/time-zones)を元にしており、ここに記載されているLMTにも対応しています。
ただし、Oracle Databaseが対応している時差の精度は分までです(マニュアルに明記されていない模様ですが、時差の時間部分、分部分を表す書式があるのに、秒部分を表す書式がない点からの推測となります)。東京の地方時はTime Zone Database上は+9:18:59ですが、+9:18がOracle Databaseとしての精度になります。

# 実際に試してみる
検証環境はOracle Database 12.1.0.2 Enterprise Edition(検証に関係ないけどExadata)です。
まず、今年の日付を表示させます。下記例のように、AT TIME ZONE句にてリージョン名もしくは時差の絶対値(+9:00など)を指定することで、指定したタイムゾーンに変換することが可能です。

```
SQL> select to_char(to_timestamp_tz('20180801 UTC', 'yyyymmdd tzr') at time zone 'Asia/Tokyo', 'yyyy/mm/dd hh24:mi:ss tzr tzd') from dual;

TO_CHAR(TO_TIMESTAMP_TZ('20180801UTC','YYYYMMDDTZR')ATTIMEZ
-----------------------------------------------------------
2018/08/01 09:00:00 Asia/Tokyo JST
```

UTC時間を日本時間に変換しました。9時間プラスされています。

では東京の地方時が採用されている期間となる、1887年8月1日だとどうなるかを試してみます。

```
SQL> select to_char(to_timestamp_tz('18870801 UTC', 'yyyymmdd tzr') at time zone 'Asia/Tokyo', 'yyyy/mm/dd hh24:mi:ss tzr tzd') from dual;

TO_CHAR(TO_TIMESTAMP_TZ('18870801UTC','YYYYMMDDTZR')ATTIMEZ
-----------------------------------------------------------
1887/08/01 09:18:00 Asia/Tokyo LMT
```

きちんと+9:18となっています。
JSTではなくLMTとなっていることも確認できます。

# おまけ：日本の夏時間への対応
[Wikipedia](https://ja.wikipedia.org/wiki/%E5%A4%8F%E6%99%82%E9%96%93#%E6%97%A5%E6%9C%AC%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E5%A4%8F%E6%99%82%E9%96%93)にあるように、過去日本でも夏時間が採用されていた時期があります。ここまでの説明で、これにも対応できることは想像がつくかと思いますが、実際に試してみます。

```
SQL> select to_char(to_timestamp_tz('19500801 UTC', 'yyyymmdd tzr') at time zone 'Asia/Tokyo', 'yyyy/mm/dd hh24:mi:ss tzr tzd') from dual;

TO_CHAR(TO_TIMESTAMP_TZ('19500801UTC','YYYYMMDDTZR')ATTIMEZ
-----------------------------------------------------------
1950/08/01 10:00:00 Asia/Tokyo JDT
```

夏時間の1時間が更に加算されていることが確認できます。
JSTではなくJDTとなっていることも確認できます。
VuePressでFontAwesomeアイコンを表示してみた

備忘録です。

# 結果
こんな感じで[FontAwesomeアイコン](http://fontawesome.io/icons/)を任意の位置に挿入できます。
<img width="256" alt="スクリーンショット 2018-12-13 12.19.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/172185/5fa22818-f8c2-0027-81ab-313a5d24d3bc.png">

# やりかた

## Step1
`.vuepress/config.js`に下記のコードを追加し、VuePressテンプレートへ`link`タグを追加します。

```config.js
module.exports = {
    // ~~~~~~
    head: [
        ['link', {
            href: 'https://use.fontawesome.com/releases/v5.6.1/css/all.css',
            rel: 'stylesheet'
        }]
    ],
    // ~~~~~~
}
```

###【補足】 ローカル等のオフライン環境で実装したい場合
● あらかじめ[公式サイトから一式をダウンロード](https://fontawesome.com/how-to-use/on-the-web/setup/hosting-font-awesome-yourself)
● `.vuepress/public/`に任意の名前でディレクトリごと配置（例えばfontawesome）
● 上のコードの代わりに、`.vuepress/config.js`には下記のコードを追加

```config.js
module.exports = {
    // ~~~~~~
    head: [
        ['link', {
            href: '/fontawesome/css/all.css',
            rel: 'stylesheet'
        }]
    ],
    // ~~~~~~
}
```



## Step2
配置したいアイコンのタグを`.md`ファイルにそのまま記述します。

```hoge.md
:::tip <i class="fas fa-info-circle"></i> Note
場合によっては順序があるので、複数導入する場合は上から順に作業することをおすすめします。
:::
```

# まとめ
超簡単に導入できました。
SimGAN: 機械学習の学習データが無いときに生成データをリアルっぽく加工して見せると精度が上がる話

機械学習の学習データが無いときに生成データをリアルっぽく加工して見せると精度が上がる話です。
Appleから出された論文で、CVPR2017でべストペーパーを受賞しています。

### Reference
- [Learning from Simulated and Unsupervised Images through Adversarial Training](https://arxiv.org/abs/1612.07828)

文中の図表は論文より引用しています。

この記事は、Wantedlyの勉強会で取り上げられた論文・技術をまとめたものです。
[2018年に読んだ機械学習系論文・技術まとめ at Wantedly Advent Calendar 2018 - Qiita](https://qiita.com/advent-calendar/2018/wantedly_ml)

### 雑なまとめ
- 機械学習でデータ作るのはマジで大変
- →人工データを作ってそれから学習すればいいじゃん？
- →作ってやってみたけど偽物っぽいデータに過学習して精度上がらん
- →偽物っぽいのをベースに、GANで本物と見分けつかないの作ったらいいじゃん？
- →精度上がった　🎉

### モチベーション
機械学習・人工知能では**「データは石油」**という言葉があります。「使うためには精製が必要」、「加工して様々に使える」、「あるところには大量にあるけど無いところには無い」ところが似ていると言われています。

巨大企業でもないと大量に独自のデータは持っていません。そんな状況でも先人たちはデータが無い状況からなんとか学習する方法を見出してきました。
その一つが、**生成データによる機械学習**です。文字通り、学習データを生成してそれを学習データとして使うというアイディアです。

このアイディア自体は前からあるものですが、生成データはリアルさに欠けるという欠点があります。
この論文のモチベーションは、「大量の正解データがなくても、生成データからGANを使ってリアルと見分けつかないリアルっぽいデータを作って精度を上げたい。」というものです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/64964/87e62ce0-eef1-d603-d8c5-be4a2712bb01.png)

### Eye gaze estimation
実際生成データが使えるタスクは限られています。正解データからデータが作れる必要があるのでシミュレータや何かしらの生成モデルが必要です。
この論文では、「眼球の画像」から視線の方向をあてるタスクに生成データを使っています。

眼球の画像と視線の方向の対応データはEye Trackerが必要なので大量の人にやってもらうのは機器と時間がかかりコストがかかります。
そのため3Dシミュレーション上であるポイントを見ている人間の顔モデルを作り、それを2Dにレンダリングしたら無限にデータが作れそうです。
しかし、シミュレーション画像では様々な人間の目の形状やノイズなどの「本物っぽさ」が失われてしまいます（沢山の人間の目のシミュレーション画像を作るのも大変そうです）。

#### Proposed Method
- GANと同じように、RefinerとDescriminatorがいる
- Refinerは人工的に生成された画像を受け取って、リアルっぽい画像を生成する
- Descriminatorは、本物かどうかを判定する。（普通のGANのdescriminatorと同じ）
- Generatorのロス関数に、「入力のピクセルをあまり変えない」項が追加されている
- Descriminatorに入力するバッチにGenerator のHistoryを入れる工夫がある
    - 過去のGeneratorから生成された画像をシャッフルして入れることで、ロバストになったと報告されている
![image.png](https://qiita-image-store.s3.amazonaws.com/0/64964/3da7014d-cd43-1d67-d406-cf492465c331.png)

### Result
2017年の精度でState-of-the-art（そのときの一番良い精度）を達成しました（表の一番下）。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/64964/a7f3891d-28bc-1ca6-9d50-9bd6a1069561.png)

### 感想
大量の正解データを作らなくても教師あり機械学習を実現するという論文の目指すところが好きなところです。
この枠組自体は他でも使えそうですね。
docker-composeのコンテナ名がランダム化になって困った時の対応

https://github.com/docker/compose/releases/tag/1.23.2
**1.23.2のバージョンでコンテナ名のランダム文字列の付与が無くなりました。
1.23.1だけの幻の機能だったようです・・・・。**

**以下、docker-compose v1.23.1をお使いの方だけ対象の記事になります。**

Macのdocker-composeを使って開発していたのですがバージョンアップしたらdocker-composeで立ち上がるコンテナ名が

`docker-dev_web-service_1`

という名前が

`docker-dev_web-service_1_7871912c2b4d`

のようなハッシュが付くようになってしまいました。

```
docker-compose down && docker-compose up -d
```

で作り直すことが多いので名前が変わると面倒になってしまいました。

いちいちdocker-compose psやらなくても良いように以下のコマンドを叩くようにしました。

```
docker exec -it $(docker ps -f name=web-service -q) sh
```

さらに[dockerコマンド](https://github.com/akarzim/zsh-docker-aliases)のエイリアスが設定されていれば

```
dkE $(dkps -f name=web-service -q) sh
```

というコマンドで済みます。
【超初級編】DialogFlowを使って簡単なチャットボットを作ってみる

# はじめに
この記事は [GameWith Advent Calendar 2018](https://qiita.com/advent-calendar/2018/gamewith) の13日目です。
Google Home Mini を購入してはや半年近く経ちますが、
天気も教えてくれる音楽プレイヤーくらいの扱いしかされていないことを不憫に感じ、
自分でActionsを作成してみることにしました。
今回はその超初級編です。

# ゴール
Actions を作成し、Google Home実機で動作させる。

# 本題
まず、[DialogFlowのコンソール]()にアクセスします。
Welcomeページが表示されるので、`CREATE AGENT`をクリックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/528a323f-81f1-3e5b-7082-98cd6f4a1304.png" />

## Agentの作成
`Agent Name`(日本語不可)を入力します。
ここでは、`Greeting`とします。
また、今回は日本でやり取りを行っていくので、`DEFAULT LAUNAGE`は`Japanese - ja`を選択します。
設定したら、`CREATE`をクリックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/64a37043-fde4-57e6-45a4-14e843c06df0.png" />

## Intentsの作成
Agentの作成が完了したら`Intents`を作成します。
左メニューの`Intents`をクリックし、`INTENT NAME`を入力します。
ここでは、`morning`とします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/bfe80cd7-3263-49c2-2264-bd23eb68445f.png" />


次に、`Training phrases`に反応させたい言葉を入力します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/fbced9d1-c0bc-ccb3-f03e-bc0d2d2bc5d1.png" />


そして、アシスタント側が応答する言葉を`Responses`に入力します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/fd2d1a95-5c20-68dc-39cc-2824dea04ec0.png" />

ここまで設定したら`SAVE`をクリックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/db387e19-fcef-1614-eb74-3248778b78d7.png" />

## Actions on Googleの設定とSimulatorでのテスト
続いて、上記で設定したIntentをGoogle Assistantで利用するための設定をします。
左メニューの`Integrations`をクリックします。
一番上の`Google Assistant`を選択します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/1a0a3cec-f23c-d40d-b817-a61cbe961a30.png" />


`Explicit invocation`に、上記で作成したGreetingを指定します。
その後、`TEST`をクリックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/be38d928-65cc-f598-3998-0f9ee086ee8c.png" />


`Actions on Google`が起動します。
まずはSimulatorを使って検証します。
「テスト用アプリににつないで」と伝えます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/26781f2f-8508-7237-7d3f-f14bf126c6ed.png" />

するとSimulatorが起動し、応答してくれます。
`Intents`作成時に`Training phrases`に設定したキーワードを、話しかけると
`Responses`に設定したキーワードで返事をしてくれます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/133075/9f0486a2-2f9e-910f-79ef-010d671b5984.png" />

## Google Home実機で動作させる
まず、今回Actionsを作成したアカウントとGoogle Homeをリンクさせます。
方法は @doki_k さんの[こちら](https://qiita.com/doki_k/items/5caff84c03946150aef7)の記事を参考にさせていただきました。
アカウントのリンクが完了したら、Google Homeに「OK Google、"Agent名"につないで」と話しかけます。
正しくリンクできていれば、「わかりました、"Agent名"のテストバージョンです」と答えてくれます。

# 最後に
次は AWS Lambdaで関数を作って連携させていきたいと思います。
自分用：OpenCV3.4.3 カメラキャリブレーション

# 概要
OpenCV 3.4.3 で C++用に書いたカメラキャリブレーションコード

# 説明
calib_imgフォルダ内の10枚の画像を読み込み，カメラ内部パラメータ行列と，歪み係数をXMLファイルで出力する

# コード

```cpp
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <opencv2/opencv.hpp>
#include <opencv/highgui.h>
#include <opencv2/imgcodecs.hpp>
#include <vector>

using namespace std;

#define IMAGE_NUM  (10)         /* 画像数 */
#define PAT_ROW    (7)          /* パターンの行数 */
#define PAT_COL    (10)         /* パターンの列数 */
#define PAT_SIZE   (PAT_ROW*PAT_COL)
#define ALL_POINTS (IMAGE_NUM*PAT_SIZE)
#define CHESS_SIZE (23.0)       /* パターン1マスの1辺サイズ[mm] */

int main(int argc, char *argv[])
{
	int i, j, k;
	int corner_count, found;
	int p_count[IMAGE_NUM];
	// cv::Mat src_img[IMAGE_NUM];
	vector<cv::Mat> srcImages;
	cv::Size pattern_size = cv::Size2i(PAT_COL, PAT_ROW);
	vector<cv::Point2f> corners;
	vector<vector<cv::Point2f>> img_points;

	// (1)キャリブレーション画像の読み込み
	for (i = 0; i < IMAGE_NUM; i++)
	{
		ostringstream ostr;
		ostr << "calib_img\\" << setfill('0') << setw(2) << i << ".png";
		cv::Mat src = cv::imread(ostr.str());
		if (src.empty())
		{
			cerr << "cannot load image file : " << ostr.str() << endl;
		}
		else
		{
			srcImages.push_back(src);
		}
	}

	// (2)3次元空間座標の設定

	vector<cv::Point3f> object;
	for (j = 0; j < PAT_ROW; j++)
	{
		for (k = 0; k < PAT_COL; k++)
		{
			cv::Point3f p(
				j * CHESS_SIZE,
				k * CHESS_SIZE,
				0.0);
			object.push_back(p);
		}
	}

	vector<vector<cv::Point3f>> obj_points;
	for (i = 0; i < IMAGE_NUM; i++)
	{
		obj_points.push_back(object);
	}

	// ３次元の点を ALL_POINTS * 3 の行列(32Bit浮動小数点数:１チャンネル)に変換する 


	// (3)チェスボード（キャリブレーションパターン）のコーナー検出
	int found_num = 0;
	cv::namedWindow("Calibration", cv::WINDOW_AUTOSIZE);
	for (i = 0; i < IMAGE_NUM; i++)
	{
		auto found = cv::findChessboardCorners(srcImages[i], pattern_size, corners);
		if (found)
		{
			cout << setfill('0') << setw(2) << i << "... ok" << endl;
			found_num++;
		}
		else
		{
			cerr << setfill('0') << setw(2) << i << "... fail" << endl;
		}

		// (4)コーナー位置をサブピクセル精度に修正，描画
		cv::Mat src_gray = cv::Mat(srcImages[i].size(), CV_8UC1);
		cv::cvtColor(srcImages[i], src_gray, cv::COLOR_BGR2GRAY);
		cv::find4QuadCornerSubpix(src_gray, corners, cv::Size(3,3));
		cv::drawChessboardCorners(srcImages[i], pattern_size, corners, found);
		img_points.push_back(corners);

		cv::imshow("Calibration", srcImages[i]);
		cv::waitKey(0);
	}
	cv::destroyWindow("Calibration");

	if (found_num != IMAGE_NUM)
	{
		cerr << "Calibration Images are insufficient." << endl;
		return -1;
	}

	// (5)内部パラメータ，歪み係数の推定
	cv::Mat cam_mat; // カメラ内部パラメータ行列
	cv::Mat dist_coefs; // 歪み係数
	vector<cv::Mat> rvecs, tvecs; // 各ビューの回転ベクトルと並進ベクトル
	cv::calibrateCamera(
		obj_points,
		img_points,
		srcImages[0].size(),
		cam_mat,
		dist_coefs,
		rvecs,
		tvecs
	);

	// (6)XMLファイルへの書き出し
	cv::FileStorage fs("camera.xml", cv::FileStorage::WRITE);
	if(!fs.isOpened())
	{
		cerr << "File can not be opened." << endl;
		return -1;
	}

	fs << "intrinsic" << cam_mat;
	fs << "distortion" << dist_coefs;
	fs.release();

	return 0;
}
```
LaravelのtransactionでrollBack時処理をハンドリング出来るようにする

* 初版：2018.12.12
* laravel-5.7, php-7.2

開発中や特別なトランザクションで、rollback時の処理を追加したくなるときがある。laravelの`DB::transaction()　`はrollback時処理を拡張できないし、`DB::beginTransaction/commit/rollBack`三兄弟をベタに使うとテストしづらいので、ヘルパー的なものを用意する。

単純に、rollback時共通でロギングするだけなら、Laravelのイベント機能を使ってrollbackイベントをListenして実行する方が良いでしょう。

```php:ラッパークラス的な
<?php
/**
 * transaction wrapper
 */
namespace App\ORM\Helpers;

use Illuminate\Support\Facades\DB;

class Transaction
{
    /**
     * DB::transactionはrollbackをハンドリングできないので、処理足す
     * @param \Closure $process () no args
     * @param \Closure $rollbacker ($rollback, $e) invoke $rollback() means DB::rollBack();
     */
    public static function do(\Closure $process, \Closure $rollbacker = null)
    {
        $result = null;

        if (is_callable($rollbacker)) {
            // rollback指定あり
            DB::beginTransaction();
            try {
                $result = $process();
                DB::commit();
            } catch (\Exception $e) {
                $rollbacker(function () {
                    DB::rollBack();
                }, $e);
            }

        } else {
            // 指定なし
            $result = DB::transaction(function () use ($process) {
                return $process();
            });
        }
        return $result;
    }
}
```

```php:呼び出し側

$eloquentInstance = Transaction::do(function () {
    // DB::insert とか Eloquent::create とか

    // ここのreturnの値がそのまま上での返り値となる
    return $createdEloquentInstance;

}, function ($rollback, $e) {
    // file_put_contents();でログするとかなにか特別な処理
    $rollback();
    // throw new \Exception(); とかなにか特別な処理
});

```


---
`DB::transaction()`　をtry-catchで囲めばrollback後の処理は対応できるけど、ネストが深くなるのがいや。

```php:ネストが深い
try {
    DB::transaction(function () {
        // nest fukai
    });
} catch (\Exception $e) {
   // after rollback
}

```
flaskでIP制限をかける

# 動機
APIサーバーからのアクセスのみ反応するようにしたい
直接叩かれた時は403を返したい

（もっと下のレイヤーで制限をかけるのが正解なのかもしれないけれど、メモ代わりに残しておきます）

# ソース
下記は例です

```python
from flask import Flask, request

app = Flask(__name__, static_folder=None)

#許可するIP一覧
ACCEPTED_IP = ["127.0.0.1", "192.168.11.2"]

def ip_check(func):
    def wrapper(*args, **kwargs):
        if request.remote_addr in ACCEPTED_IP:
            print('IP Check : OK')
            return func(*args, **kwargs)
        else:
            print("403")
            return abort(403)
    return wrapper


@app.route('/', methods=['GET'])
@ip_check
def index():
    return "hi"

# main
if __name__ == "__main__":
    print(app.url_map)
    app.run(host='localhost', port=5001)
```
SalesforceのUnitTestで出た謎の [Internal Salesforce Error] の解消


## 追えないエラー

テスト流したらこんな結果がとれた。
（ant migrationツールで実施した場合のログ）

```sh
Test Failures:
 1.  Callout_Test.httpRequest -- Internal Salesforce Error: 182815349-17184 (-1472235887) (-1472235887)
     Stack trace: null
```

情報がどのテスト流したらエラーが起きた、くらいしかない　:innocent:


## 結論から

コールアウトのクライアント証明書にスペースが入ってると出る。


## 解説

クライアント証明書（参照: [HTTP 要求での証明書の使用](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_callouts_client_certs_http.htm) ）を使ってコールアウトを実施しているコードがあったとする。

setClientCertificateNameに渡す文字列にスペースが含まれていると出た。（2018/12/13 現在）

```java
	final HttpRequest request = new HttpRequest();
	request.setMethod('GET');

	request.setEndPoint(endpoint);
	request.setHeader('Content-Type', 'application/json; charset=UTF-8');

	String clientCertificateName;
	
	if(Test.isRunningTest()) {
		// clientCertificateName = 'test dummy certificate name'; // NG
		clientCertificateName = 'dummyClientCertName'; // OK 
	} else {
		// 何かしら設定から取ってきた方が良い
		clientCertificateName = 'productionClientCertName';
	}
	request.setClientCertificateName(clientCertificateName);

	final Http h = new Http();
	final HttpResponse response = h.send(request);

```

どうしてもカバレッジ通したい時などに使う。
Test側では証明書設定が無いことで起きる例外をtry-catchすることになるけど、それでカバレッジは通る。

※実際は Test.isRunningTest じゃなくて、他の方法でTest側から注入出来るような機構があったほうがよい
カスタム django-admin コマンドに、独自引数を追加する

前回の記事「[カスタム django-admin コマンドを実装して、外部からアプリ内のモデルを使う](https://qiita.com/jansnap/items/d50f59dabc5da7c1d0dd)」の続きです。

# 背景
前回は、カスタムコマンドとして、「crawler」を追加し、```$ python manage.py crawler```で、実行できるようにしました。
今回は、そのコマンドに引数を渡して、処理を切り替えられるようにします。


# サンプルのコード

- ```add_arguments```という関数を実装し、引数の扱い方を指定します。

```python

from django.core.management.base import BaseCommand, CommandError
from app1.models import Topic

class Command(BaseCommand):
  help = 'crawler for test.'

  def add_arguments(self, parser):
    parser.add_argument('-c', '--check-alive', action='store_true', dest='check-alive', help='Check topic alive.')

  def handle(self, *args, **options):
    #self.myprint("options=%s" % options)
    if not options['check-alive']:
      self.crawl_new()
    else:
      self.check_alive()

  def crawl_new(self):
    self.myprint('this is function crawl_new.')
  
  def check_alive(self):
    self.myprint('this is function check_alive.')

```


# 要点

- 引数は、```--version```のように後続の引数が無いものと、```--verbosity 3```のように後続の引数が有るものの2種類に分けられます。


 - 後続の引数が無い場合は、```action='store_true'```を指定します。(これの詳しい解説記事が見つからなかった)。引数が指定されたか否かは、True/Falseで格納されます。

 - 後続の引数が有る場合は、```nargs='*'```を指定します。後続の引数は辞書型で格納されます。後続の引数が省略された場合は、空の辞書が格納されます。


- さらに、```dest='check-alive'```で、引数がどのように指定されたかを```options```にどんなキーで格納するかを指定します。

 - この指定が無いと、引数名の長い方の名前で、```-```を```_```に変換したキーで格納されます。(上記の例では```options['check_alive']```)。

 - 引数に長い名前の場合はハイフンを使う場合が多いので、destを指定した方が無難かと思います。

# 気になる点

- 上記の場合、```-c```の代わりに```-cc```や```-cccccccc```のように同じ文字を重ねて指定しても同じ結果になりますが、```-c1```のように異なる文字を指定すると```error: argument -c/--check-alive: ignored explicit argument '1'```とエラーになります。長い引数の場合は```--check-alivee```のように末尾の同じ文字を重ねるとエラーになります。


# 参考サイト

- 公式ページの[カスタム django-admin コマンドの実装](https://docs.djangoproject.com/ja/2.1/howto/custom-management-commands/#accepting-optional-arguments)

- 公式ページの[16.4.3. add_argument() メソッド](https://docs.python.org/ja/3.6/library/argparse.html#the-add-argument-method)

- [Djangoのカスタムコマンドを作成してコマンドラインから実行する](https://qiita.com/checkpoint/items/b6947501774b4008e077)
[macOS][Swift4.2] Distributed Notifications でアプリ間通信

Macアプリでコマンドラインツールやアプリを内包してサブタスクとして起動している時などに本体アプリと通信を行いたい時がある。
 `DistributedNotificationCenter` を使用すればアプリ間通信が可能になる。

![スクリーンショット 2018-12-12 18.45.38.png](https://qiita-image-store.s3.amazonaws.com/0/156085/d6945ddc-274d-6d4f-2caa-2d02b7ebf823.png)

サンプルコードは以下に配置。
https://github.com/atsushijike/DistributedNotifications

* Xcode10.1
* Swift4.2

# 送信側

`NotificationCenter` と同じようにpostするのだが、 `post(name:,object:)` や `post(name:,object:,userInfo:)` を使うと受信側アプリを前面にしないとobserveされなかったりするので、 `postNotificationName(_ name:,object:,userInfo:,deliverImmediately:)` を使用する。

`userInfo` には `field.stringValue` を"Message"キーで入れている。

```Swift:PostApp/AppDelegate.swift
    @IBAction func post(_ sender: NSButton) {
        let userInfo: [AnyHashable : Any]? = field.stringValue.isEmpty ? nil : ["Message" : field.stringValue]
        DistributedNotificationCenter.default().postNotificationName(NSNotification.Name("DistributedNotifications.Post"), object: nil, userInfo: userInfo, deliverImmediately: true)
    }
```

 **但し、Sandbox対応アプリで userInfo を含むとエラーになるので注意** 
https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/DesigningYourSandbox/DesigningYourSandbox.html

```
With App Sandbox, you cannot include a userInfo dictionary when posting to an NSDistributedNotificationCenter object for messaging other tasks. 
```

# 受信側

`NotificationCenter` でobserveするときと同様に `addObserver(_ observer:,selector:,name:,object:)` する。

```Swift:ObserverApp/AppDelegate.swift
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        DistributedNotificationCenter.default().addObserver(self, selector: #selector(distributedNotificationsPost), name: NSNotification.Name("DistributedNotifications.Post"), object: nil)
    }
```

`userInfo` に含まれる"Message"を `label` に表示。

```Swift:ObserverApp/AppDelegate.swift
    @objc private func distributedNotificationsPost(notification: Notification) {
        if let message = notification.userInfo?["Message"] as? String {
            label.stringValue = message
        }
    }
```
Go Panic でパニック

streampack の Tana です。

streampack ではライブの一機能の一つで Websocket を使ってユーザーとインタラクティブなやり取り機能を提供してます。

Websocket はコネクションを貼り続けるため、 Maximum接続数の閾値テストしているとたまに落ちることがありました。

```
goroutine 5774 [running]:
runtime.throw(0xe2c371, 0x15)
/usr/lib/golang/src/runtime/panic.go:605 +0x95 fp=0xc4234a76f0 sp=0xc4234a76d0 pc=0x42c0d5
runtime.mapassign_fast64ptr(0xcfcc20, 0xc420320180, 0xc423490280, 0xc42334dc00)
/usr/lib/golang/src/runtime/hashmap_fast.go:695 +0x3d2 fp=0xc4234a7750 sp=0xc4234a76f0 pc=0x40e452
main.websocketHandler(0x7fd1be198e18, 0xc42325d3f0, 0xc42334dc00)
... 
```

急に負荷をかけすぎたため、たまたまかなと思いつつも、また再現。

エラーも大量にエラーが出て追いにくく、うーんと悩んでたところ、

```
fatal error: concurrent map writes
```

と出てました。

どうも、**同時に map を書き込みに関するエラー** のようです

よくよく調べてみると、

> Maps are not safe for concurrent use: it's not defined what happens when you read and > write to them simultaneously. If you need to read from and write to a map from concurrently executing goroutines, the accesses must be mediated by some kind of synchronization mechanism. One common way to protect maps is with sync.RWMutex.

ソース: source: https://blog.golang.org/go-maps-in-action

他にも同様な経験されたケースが多々ありました。

つまり、map を操作する場合は sync.RWMutex などのライブラリを使って、
Read/Write する際は排他的に Lock/Unlock する必要がありました。

```
var clients = make(map[*websocket.Conn]bool)
var ClientMutex struct {
  sync.Mutex
}

ClientMutex.Lock()  // ロック
clients[ws] = true
ClientMutex.Unlock() // アンロック
```

また、下記のように -race オプションをつけると Warning でアドバイスしてくれます。

> $ go run -race main.go 

goroutine 内でごにょごにょ map を Read/Write している場合は注意しましょう。
AndroidアプリでFCM（Firebase Cloud Messaging）のPush通知を実装・送信するときのメモ

## 概要

自分用のメモ（下書きが10件までだったので仕方なく公開した）

随時更新予定

## 知ったこと一覧

- 調査・実装・テスト・リリース込みで2〜5営業日でくらいで対応可能なボリューム（個人差あり）
- serviceはcontextである
- GCM（Google Cloud Messaging）は使わない、FCM（Firebase Cloud Messaging）を使う
- FirebaseInstanceIdServiceは使わない、FirebaseMessagingServiceを使う
- onNewToken()はFCMトークン（deviceToken）が生成されたときに呼ばれるコールバックである。FCMトークン（deviceToken）は以下のタイミングで生成される
    - アプリによってインスタンス ID が削除される場合
    - アプリが新しい端末で復元される場合
    - ユーザーがアプリをアンインストール / 再インストールする場合
    - ユーザーがアプリのデータを消去する場合
- Push通知の送信はGUI（ブラウザにてFirebase Console）とAPIで行える
- Push通知は一つの端末が対象の場合、FCMトークン（deviceToken）を指定すれば送信できる
- Push通知は複数の端末が対象の場合、TOPIC（端末をグルーピングしたもの）を指定すれば送信できる
- TOPICは最初に作成されてから1〜2日程度待たないと送信できない(Firebaseのサーバーに反映されない？)
- TOPICの作成はFirebase Consoleから行うとかではなく、Androidアプリから行う

## 参考にした記事一覧

以下の記事、記事の執筆者の方に感謝しています。

- [Firebase Cloud Messaging  |  Firebase](https://firebase.google.com/docs/cloud-messaging/?hl=ja)
- [Firebase(FCM)を用いたAndroid(Kotlin)でのプッシュ通知 - Goalist Developers Blog](http://developers.goalist.co.jp/entry/2018/10/12/174351)
- [FirebaseInstanceIdServiceがDeprecatedになった件 - Qiita](https://qiita.com/keijumt/items/d45ea0da3dfa6284ad90)
Jestyをただの静的HTTPサーバーして動かす＋muslでシングルバイナリにもしてみる

# 概要

Jestyの無駄遣い。

## きっかけはVue.js

Webpackに依存しないVue.jsを使ったフロントアプリって作れないのかを調べていたところ、以下の記事を発見。

https://markus.oberlehner.net/blog/goodbye-webpack-building-vue-applications-without-webpack/

Vue.jsのコンポーネントを*.vueではなくJavaScriptで記述して、```type="module"``` や import を利用して、Vueコンポーネントを動的にロードできますよという記事でした。

```
<script type="module" src="xxx.js"></script>
```

記事内においては、npmのbrowser-syncパッケージを用いて、nodeでサーバーを立てて説明をしています。
ここで思ったのが、**Webpack使わないっていう記事なのに、Node.jsは使うの？**という疑問。
Node.jsは嫌いってわけでもないのですが、「Httpサーバー立てるだけだろ。Pythonのワンライナーでいんじゃね？」
と思い、以下のような感じでHTTPサーバー立ててみたところ、

```
# for python 2.x
python -m SimpleHTTPServer 9000

# for python 3.x
python -m http.server 9000
```
 
type="module" のファイル読み込みがブロッキングされる現象が発生。
ただし、Chromeのシークレットモードだとブロッキングされないという謎現象も発生。
Python側のシングルスレッドとかの動作？でうまく行かないんだろうなーと原因追求は特にせず、なんかちゃんとした軽いHTTPサーバー無いかなと探したところ、あるじゃんNimに。[Jester](https://github.com/dom96/jester)が。

## Jesterを見てみると

Jesterを見てみるとpublicフォルダというのを用意すれば、その配下のファイルを静的ファイルとして提供できると。
またstaticDir()関数で設定をオーバライドできるよともあったので、アプリケーション実行時のフォルダをstaticDirで設定してしまえば、Pythonでのワンライナーと同じ動作させられそう。

```
# publicフォルダの中を公開
$ ls public
hogehoge.html

$ curl http://localhost:xxxx/hogehoge.html
```

という感じで、作ってみたのはこちら。

https://github.com/6in/simple-http

```
# インストール
$ git clone https://github.com/6in/simple-http.git
$ cd simple-http
$ nimble install

# httpコマンドが~/.nimble/binに作成
$ http --help
Usage:
  http --port=<port> [--root=<root>]
  http (-h | --help)
  http --version
```

結局のところ、jester起動時のオプションに、静的フォルダのパスを渡せば良いみたいだったので、こんな感じに。

```nim
  let settings = newSettings(
    Port(port), root
  )
  var myJester = initJester(settings)
```


httpコマンドは、ポートとルートディレクトリ(デフォルトはカレント)を指定して実行します。

最初の記事に戻って、サンプルをcloneし作成したhttpコマンド(笑)で動かしてみる

```
$ git clone https://github.com/maoberlehner/goodbye-webpack-building-vue-applications-without-webpack.git nowebpack
$ cd nowebpack
$ http --port=8181 --root=src
```

### 出た！
![Screenshot from 2018-12-13 10-51-36.png](https://qiita-image-store.s3.amazonaws.com/0/58872/2f73100e-fb8e-b820-3744-7d274789f332.png)

## Muslでシングルバイナリにもしてみる

linux限定ですが、nimbleにmuslタスクを追加しています。[Muslの記事](https://qiita.com/6in/items/3544cec69dd53960c2df)で構築済みの前提です。
simple-httpをcloneしたフォルダで、muslタスクを実行するとbinフォルダにhttpコマンドが作成されます。

```
$ nimble musl
...
Created binary: bin/http

# lddコマンドで確認
ldd bin/http                                                                                                                                                            [master]
        動的実行ファイルではありません

$ bin/http --port=8182 --root=src

# nowebpackフォルダに移動
$ cd ../nowebpack

# 作成したシングルバイナリを指定して、別ポートで実行
$ simple-http/bin/http --port=8182 --root=src 
```

### 出た！！

![Screenshot from 2018-12-13 11-04-07.png](https://qiita-image-store.s3.amazonaws.com/0/58872/be790587-0b3f-f44e-3676-27828ae186ef.png)

## まとめ

まったく**俺得でしかないhttpコマンド**をjesterを利用して作ることができました。
どのLinuxディストリビューションでも動きそう？なシングルバイナリも作ることができました。
Webpackを使わないVue.jsのアプリの作りを調べていたら、**なぜかhttpサーバーを作っていた**という『[ヤクの毛刈り](https://blogos.com/article/65001/)』のような話でした。 

Vue.jsはどうしたかっていうと、**WebPackで開発する**ことにしました。
iOS Read and write typed data arrays to/from bundle/local accessible storage (Swift 4.0+)


# Read from bundle or local storage

### Get url of Bundle

```swift
let url = Bundle.main.url(forResource: filename, withExtension: "")
```

### Get path of local accessible storage

```swift
let path = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path) as URL
```

### Get data from url

```swift
do {
    let data = try Data(contentsOf: url)
}
catch {
    print("failed to read", url)
}
```

### Get string stored as Data

```swift
let str = String(data: data, encoding: String.Encoding.utf8)
```

### Get typed array from data with a generic

```swift
static func dataToType<T>(data: Data) -> [T] {
    return data.withUnsafeBytes({ (pointer: UnsafePointer<T>) -> [T] in
        let buffer = UnsafeBufferPointer(start: pointer, count: data.count / MemoryLayout<T>.size)            
        return Array<T>(buffer)
    })
}
```

### Get string array from data 

```swift
do {
    let arrays = try JSONSerialization.jsonObject(with: data, options: []) as? [String]
} catch {
    print("failed to parse string array")
}
```

# Write to local storage

### Get data from typed value array

```swift
static func typeToData<T>(array: [T]) -> Data {
    return array.withUnsafeBufferPointer({ (pointer: UnsafeBufferPointer<T>) -> Data in
       return Data(buffer: pointer)
    })
}
```

### Write data to url

```swift
do {
    try data.write(to: url, options: .atomic)
}
catch {
    print("failed to write")
}
```

### Write array of strings as Data
```swift
do {
    let data = try JSONSerialization.data(withJSONObject: strings, options: [])
    try data.write(to: url, options: .atomic)
}
catch {
    print("failed to write string array")
}
```
配列の最初or最後のキーを取り出す(PHP7.3)


## 追記 
空いていたので、[PHP Advent Calendar 2018](https://qiita.com/advent-calendar/2018/php)の13日目の記事として参加させてもらいました。

---

先日、PHP7.3がリリースされましたね。
今まで地味に面倒だった表題の件が簡単になったので紹介します。

## TL;DR
PHP7.3以降は`array_key_first()`と`array_key_last()`を使いましょう。副作用もありません。
http://php.net/manual/ja/function.array-key-first.php
http://php.net/manual/ja/function.array-key-last.php



## PHP7.2以前の場合
地味に面倒でした。

```php:php72.php

$arr = ['a' => 'Alice', 'b' => 'Bob'];

# わざわざポインタを動かしてから取得しないといけない
reset($arr);
key($arr);
# => "a"

end($arr);
key($arr);
# => "b"

# わざわざキーだけの配列を生成してから取得。しかも作った配列$keysを破壊する
$keys = array_keys($arr);
array_shift($keys);
# => "a"

$keys = array_keys($arr);
array_pop($keys);
# => "b"

# 呼ぶたびに変わっていく...
array_pop($keys);
# => "a"
array_pop($keys);
# => null

# 強引に一行でやろうとするとE_NOTICEをだす
reset(array_keys($arr));
# => PHP Notice:  Only variables should be passed by reference...
```

## PHP7.3の場合
追加された`array_key_first()`と`array_key_last()`を使いましょう。

```php:php73.php

$arr = ['a' => 'Alice', 'b' => 'Bob'];

array_key_first($arr);
# => "a"

array_key_last($arr);
# => "b"

# 何回呼んでもOK
array_key_last($arr);
# => "b"

# ちなみに空配列の場合はNULLです
array_key_last([]);
# => null
```

## ちなみに
RFCをみるとarray_key_first/lastは賛成18/反対14で採用、array_value_first/lastは賛成15/反対18で不採用なので、最初/最後の値を取り出す関数はありません。賛否分かれる機能のようですね。keyを採用したのならvalueも採用して欲しかったですが。。
https://wiki.php.net/rfc/array_key_first_last

最後の値を取るのは依然として面倒と言えば面倒ですね

```php
$arr = ['a' => 'Alice', 'b' => 'Bob'];

# 今まで（ポインタが移動しちゃう）
end($arr);
# => "Bob"

# 存在チェックが必要なのでこれはこれで長い。いい方法あるかな？
$lastkey = array_key_last($arr);
array_key_exists($lastkey, $arr) ? $arr[$lastkey] : null
# => "Bob"
```
【かわいいイラストで分かる！】フォールトトレランス、フェールソフト、フェールセーフ等の違い

#この記事の主旨
システム設計に関する用語は、基本情報技術者試験（FE）などの資格でも頻出ですが、名前が似通っていてとても覚えづらいです。そこで、イラストにしてキャラの技名っぽくすれば覚えやすいんじゃない？というのが当記事の要旨です。

出てくるキャラクターはシステム設計のアルソックくん（仮）と名付けました。

##用語

###フォールトトレランス
<img src="https://qiita-image-store.s3.amazonaws.com/0/227791/590b36be-5270-2ccf-4b86-101aba404edd.jpeg" width=40% alt="UNADJUSTEDNONRAW_thumb_165b.jpg">
>障害が発生しても機能を継続させる設計手法。
広義の意味で「対障害性」と使用される場合もあるが、「フェールソフト」と比較して「障害発生時に機能を縮小せずに継続する」対障害性を意味する場合もある。

>例）電源の二重化　ハードディスクのRAID

###フェールソフト
<img src="https://qiita-image-store.s3.amazonaws.com/0/227791/7e6b9668-1c45-7016-7066-a1893c7314c8.jpeg" width=40% alt="UNADJUSTEDNONRAW_thumb_165b.jpg">
>・障害発生時に機能を縮小してでも継続
・稼動継続を優先

>例）エンジン式の飛行機。エンジンが一機停止しても、稼動を継続する必要がある。

###フェールセーフ
<img src="https://qiita-image-store.s3.amazonaws.com/0/227791/a9f1a83c-4d2c-0c60-d76a-6d33b5359c56.jpeg" width=40% alt="UNADJUSTEDNONRAW_thumb_165b.jpg">
>・障害発生時にシステムを安全な状態に移行
・安全を優先

>例）鉄道列車における緊急時の急ブレーキ。列車の運用より乗客の安全を優先する。

###フールプルーフ
<img src="https://qiita-image-store.s3.amazonaws.com/0/227791/1087a6c5-7c12-caf2-9f74-d13d9fcd1cce.jpeg" width=40% alt="UNADJUSTEDNONRAW_thumb_165b.jpg">
>ユーザが誤った操作を行っても安全に稼動させる設計。

>例）OSにおける電源ボタン。電源ボタンを押した場合、コンピュータがいきなり電源オフされるのでは無く、OSのシャットダウン処理が実行されてから電源がオフされる。

###フォールトアボイダンス
<img src="https://qiita-image-store.s3.amazonaws.com/0/227791/f63e25e0-62e9-66c3-0e41-263e0ebf03be.jpeg" width=40% alt="UNADJUSTEDNONRAW_thumb_165b.jpg">
>事前対策により障害を回避する

>例）
・高品質の部品を採用
・十分なテスト
・品質管理の徹底
・教育

###フォールトマスキング
<img src="https://qiita-image-store.s3.amazonaws.com/0/227791/4d7c9c4c-0dfd-089e-5c99-b2c88431e839.jpeg" width=40% alt="UNADJUSTEDNONRAW_thumb_165b.jpg">
>障害時に障害の影響を他に与えないこと。

>例）・機器を完全に冗長化し、障害時でも他の冗長化された機器には影響を与えず動作を継続すること。

###一覧
<img src="https://qiita-image-store.s3.amazonaws.com/0/227791/f499721f-5ff7-b402-ebc8-01a569014b10.jpeg" width=60% alt="UNADJUSTEDNONRAW_thumb_165b.jpg">



参考・引用元サイト↓
[フォールトトレランス、フェールソフト、フェールセーフの違い](http://tooljp.com/jyosho/docs/faulttolerance/faulttolerance.html)
便利だけど忘れがちなGitコマンド集

## 概要

気が向いたら随時更新予定

## コマンド

### マージされたローカルブランチをローカルから削除する

```
git branch --merged | egrep -v '\*|develop|master' | xargs git branch -d
```

※この例ではdevelop, masterというブランチにマージされた場合を示している

### マージされたリモートブランチをローカルから削除する

```
git remote prune origin
```

※この例ではリモートリポジトリをoriginという名前にしている場合を示している

### git fetchする際にリモートで削除されたブランチをローカルのリモートブランチから削除する

```
git fetch --prune
```


### stashをすべて削除する

```
git stash clear
```

### リモートブランチを追跡（トラッキング）する

```
git branch -u origin/develop develop
```

ローカルの `develop` ブランチがリモート（ `origin` ）の `develop` ブランチをトラッキングする。
（以降、ローカルの `develop` ブランチで `git pull` する際にリモートブランチを指定しなかった場合、トラッキングブランチが対象となる）
MTGのやり方(進捗MTG用?)

# MTGのやり方(仮)

※これは社内勉強会用資料です。

---

# 諸注意
* 言われてみれば当然の事ばかり話します。
* 入退室自由です。
* 質問があったらいつでも挙手してください。
* 資料は後ほど公開するので、メモする必要ないよ。
* メモするなら自分の気付きや質問、疑問をメモするといいよ。

---

# 諸注意2
+ MTGのやり方は千差万別なので網羅しきれていない。（前、言い訳）
+ 無駄の無いMTGをしてもらいたいとは思っている。

---

# アジェンダ

+ 前提
+ 対象者
+ 目的
+ MTGで達成しなければいけないこと
+ MTGの形式
+ MTGで準備する
+ MTGを実施する
+ MTG後

---

# 前提
基礎の基礎を押さえられたらなと。

___

# 対象者

+ ファシリテーター
+ MTG参加者

---

## 補足

MTGの質はファシリテーター次第だとは思う…。  
けれど、ファシリテーターの人ばかりじゃなく、  
MTGに参加する側も含めてMTGだと思うので、  
両方に意味のある話を話せたらと思う。  

---

## MTGは、みんなで達成していくもの。

(ファシリテーターも重要だけれどね。)

---

### たったひとつの命を捨てて　生まれ変わった不死身の体　鉄の悪魔を叩いて砕く　キャシャーンがやらねば誰がやる。

___

# 目的

無駄の無い、無駄にならない意味のあるMTGを行えるようにしよう。

---

## 質問、疑問ありますか?

___

# MTGで達成しなければいけないこと

---

## MTGってなんの為やってます?

---

## MTGとは(今日の一番重要なところ)

プロジェクトを実現する為の一手段。  
**次に、メンバーがプロジェクトに対して何をするのか**  
を明らかにする方法。

---

## NG

+ 共有して終わり
+ 決めて終わり

---

## OK

+ 共有した結果、**誰が何をするのか**
+ 決めた結果、**誰が何をするのか** 

---

## 注意、GAT

GOALには **次のアクション** が含まれていないといけない。  
けれどその言及がされていないので、ちょっとどうかと思う。
余談だけれどKPTもそう。
目的が統一されていないのに｢KPT、KPT｣と実施して意見が発散し、
次につながらない無駄な時間を過ごしているチームが多い。

---

## 質問、疑問ありますか?

___

# MTGの形式

---

## 参考

（１）意思決定型会議    
（２）指示命令会議  
（３）ブレイン・ストーミング型会議  
（４）コーチング型会議  
（５）連絡型会議  
（６）本質問題発見・解決会議  

引用元:http://www.insightnow.jp/article/1924

---

## このように捉えてみた。

---

## MTGの進め方2種類
+ 引き出す  
ブレスト、課題洗い出し
+ 押し込む、伝え合う  
スケジュール共有、指示だし

---

## MTGのゴール2種類+両方

+ 共通認識を持つこと
+ 決めること

---

## 質問、疑問ありますか?
網羅されている感がちょっと薄い。  
漠然としすぎちゃってるかな…。

___

# MTGで準備する

---

## やりたい事はなんですか?

+ 共有したいのは何ですか?
+ 決めたいことは何ですか?
+ 決めた結果何したい?


---

## MTGを想像する

---

## 想像 = 準備

+ 段取り
+ 参加者の行動
+ 必要になる情報
+ 決まることまたは共通認識にしたいこと
+ 次のアクション
+ 時間

---

## バリエーションをもって想像しておく。

---

## 段取り

+ ゴールを目指す為の計画。
+ 持ち込むべき情報精査する指標。
+ **ゴールに対しての前提を考える**
+ MTGの内容を考えることではない。

---

### 例:スケジュールMTGの場合
+ 予定の確認（全体）
+ タスク進捗の確認（それぞれ）
+ 抜け漏れ確認(それに対して)  
そして、それぞれの作業へ

---

### 例:オリエン?の場合
+ 仕様共有する（全体）
+ 疑問点解消する（それぞれ）
+ スケジュールを決める(仕様に対して)  
そして、それぞれの作業へ

---

### 例:振り返りの場合
+ 課題や要望を出す（対象）
+ ゴールを決める（進む所）
+ 手段を決める（進め方）
そして、それぞれの作業へ

---

### 例:プロジェクト方針決め
+ 情報収集
+ 分析
+ アイディア決める
+ 手段を決める
そして、それぞれの作業へ

---


## 参加者の行動

+ 想像できればする。
+ 癖を知っておくこと。
+ 段取りを押さえれば大丈夫!!

---

## 必要になる情報

+ 共有すべき情報
+ 決めるに対しての判断材料
+ 参加者が欲しがるであろう情報
+ 次の作業に移れる情報
+ 反論おさえ
など

---

## 決まることまたは共通認識にしたいこと
+ MTGのゴールとか目的とかいわれる奴。
+ 情報が受け入れられるだろうか想像する。

---

## 次のアクション
+ 誰がいつまでに何をするのか

---

## 時間
+ 一つのテーマは5分から15分。
だと思っていいかも、あとは習うより慣れろ。
+ max 90分 それ以上は休憩を挟む事。

---

## 質問、疑問ありますか?

___

# MTGを実施する

---

## 後は準備通り進めてもらえれば…。

---

## テクニック
+ 議論が進みそうなら、ファシリテーターは喋らない。
+ 段取りを実行することに専念。
+ 段取りが進みそうにない時に喋る。

## テクニック
+ **納得(感)**を確認しながら進める。
+ 納得感が足りないなら、足りるようにする。

---

## テクニック
+ 議論の良し悪しの判断して本筋に戻す。
+ 常にゴールを目指す。

---

## テクニック
+ 共通認識を確認する。
+ 互いの認識を伝え合う。

---


## 質問、疑問ありますか?

---

# MTG後

+ 議事録の展開
+ 実行されるか互いに確認

## テクニック

+ MTGの準備したメモが議事録になったりする。

___

# しっかり準備、段取りを決めて無駄のないMTGをやろう。

---

## 質問、疑問ありますか?
Nextcloud 15を入れてみました。

#はじめに
先日（2018/12/10）、Nextcloud15がリリースされ、[Changelogの翻訳](https://qiita.com/mmisu/items/38c9e2c29d7b9a995d5c)をしてみましたが、早速、社内環境にインストールしてみましたので、いくつかの新しい機能を紹介したいと思います。

#アイコンの表示１
まずは、ブラウザー画面上部の機能のアイコンです。今まではアイコンだけ表示されていましたが、Nextcloud15ではマウスのカーソルを合わせると機能名が表示されるようになりました。

カーソルを合わせていない状態（今までと同じ）
![画像145.png](https://qiita-image-store.s3.amazonaws.com/0/308127/9b1a0ae0-00e9-a73c-135e-535385a0ecf3.png)

カーソルを合わせた状態（アイコンの下に機能名が表示される）
![画像146.png](https://qiita-image-store.s3.amazonaws.com/0/308127/1484e983-667c-f7ee-f758-a705aa405047.png)


使い慣れていない人でもわかりやすいですね。

#アイコンの表示２
次に、ファイルやフォルダのアイコンの表示の変更です。今まではリスト表示だけでしたが、画面右上にグリッド表示切替ボタンが追加されました。
![画像149.png](https://qiita-image-store.s3.amazonaws.com/0/308127/23d5dacc-e67e-a4ff-65b0-a6216113c115.png)

グリッド表示に切り替えると、大きいアイコンで表示されます。
![画像150.png](https://qiita-image-store.s3.amazonaws.com/0/308127/3c415fd1-2253-a571-8e8f-9e69a3c97f6a.png)

#ダウンロードをさせない
ダウンロードをさせなくする機能が追加されました。[URLリンク共有時](https://qiita.com/mmisu/items/2b646b39f97ebb74a8f8)にダウンロードをさせない設定にする事が可能です。
![画像147.png](https://qiita-image-store.s3.amazonaws.com/0/308127/e1ccff8a-8daf-f70a-c4f3-58112e22acb2.png)

共有したURLにアクセスすると、ダウンロードボタンがありません。また、ファイルをクリックしても、ダウンロードはされません。
![画像148.png](https://qiita-image-store.s3.amazonaws.com/0/308127/8bb3716d-22eb-ddb2-70d7-f7532fb02c7b.png)
ダウンロード出来ないのでは意味がないと思いますが、[ONLYOFFICE](https://qiita.com/mmisu/items/ed91c2b8ed9e2f586d1f)やCollabora Onlineと併せて利用すれば、ブラウザー上で閲覧・編集はできるが、ダウンロードはさせないなど、といった事ができるのではないかと考えております（今後、要検証です。）

#複数URLリンク共有
今までのURLリンク共有は、一つしか共有する事ができませんでしたが、Nextcloud15から複数のURLリンク共有ができるようになりました。URLリンク共有の設定画面の一番下に、「別のリンクを追加」という項目が追加されています。
![画像151.png](https://qiita-image-store.s3.amazonaws.com/0/308127/e4eee285-4afc-a634-f90b-494ca2069e7d.png)

複数のURLリンク共有を設定してみました。
![画像152.png](https://qiita-image-store.s3.amazonaws.com/0/308127/d7a22bba-ff39-7d36-c776-372cf23a53a1.png)

#まとめ
今回、Changelogの項目が非常に多かったのですが、機能や表示の部分での大きな変更点を紹介しました。個人的にはダウンロードさせない機能とONLYOFFICEの組み合わせがうまくできれば、民間企業でも利用されるケースが増えてくると思います。また、今後、URLリンク共有時だけでなく、[ユーザ・グループ間の共有](https://qiita.com/mmisu/items/1a7f66c94ca4d8a66b49)でもこの設定ができるようになると良いかと考えております。

この記事は、[スタイルズ社のNextcloudサイト](https://nextcloud.stylez.co.jp/nextcloudblog)にも公開しております。
Botkit を入れたDockerfileを書いてみる

みんな大好き？[Botkit](https://github.com/howdyai/botkit)を入れた Dockerfile を書いてみたのでハマりポイントと共にメモします。

## 確認バージョン
* botkit 0.6.21
* Node.js 10.14.2

## Dockefile の内容
ほぼ最低限の記述のみですが・・・

```dockerfile
FROM amazonlinux:latest

LABEL maintainer "xxx <xxx@xxxxxxxx>"

RUN yum -y update && \
    yum -y install sudo && \
    yum -y install git && \
    curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo bash - && \
    yum -y install nodejs && \
    rm -rf /var/cache/yum/* && \
    yum clean all

RUN npm install -g botkit

# パスはお好みで
WORKDIR /usr/local
RUN botkit new --name botkit --platform slack --studio_token dummy

# 自作のBOTや環境変数ファイルがあればコピーする
COPY bot.js /usr/local/botkit/
COPY .env /usr/local/botkit/

EXPOSE 3000
ENTRYPOINT node /usr/local/botkit/bot.js

```

## Dockerfileの内容について
* AWS上に立ててたのもあるので amazonlinux から構築していますが、Node.jsのコンテナを使って Node.js 自体のインストールを省いてもOKです:+1:
* `botkit new` の処理の中で git をコマンドを呼び出す部分があるので git は必須になります(エラーがわかりづらすぎてハマった・・・)
* `botkit new` で async/await を使っているので Node.js 7.6 以上必須です
* `botkit new` するときの `--studio_token` は Optional ですが、なぜか省力できない（対話形式で入力を聞かれる）ので ダミーの文字列を入れています ([次期バージョンでこのパラメータは廃止されるようです](https://github.com/howdyai/botkit/pull/1537))
意思決定者から上手にデザインレビューを受けるための4つのポイント

この記事は株式会社グロービスの[Advent Calendar 2018の13日目 ](https://qiita.com/advent-calendar/2018/globis)の記事です。

みなさんこんにちは。デザイナーの渡邉です。
渡邉多すぎる問題があり「リョウジさん」と呼ばれているますが、実は生粋のポケモンマニアで「サトシ」という裏ニックネームを持っています。

![qiita_img_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/309303/8cb599bc-0515-7a9e-6f81-b00b58e84174.jpeg)


さて突然ですがデザイナーの皆さん！意思決定者のデザインレビューで腹落ちしないことはありませんか？

- もっと無骨な感じで力強く
- Appleぽくカッコ良くして
- ボタンは赤の方が良いな
- いい感じのグラデにして…etc

上記のようなことを言われれば、デザインレビューではなく個人の感想では？と考えてしまい、コミュニケーションを諦めて腹落ちしないまま修正作業をすることもあると思います。

しかし、なぜデザインレビューが意思決定者の感想になってしまったのでしょうか？
その理由は**デザインの前提条件が不足してしまっている**からです。

僕個人の感覚値ですが、プロダクト開発のスクラムメンバー間では前提条件が共有できているので、事前情報がなくても精度の高いデザインレビューが行われることが多いです。
反対に普段プロジェクトに関係していない意思決定者や、受託開発をしている場合の発注者（意思決定者）など、日頃から密に連携していない場合は前提条件が不足してしまいデザインレビュー が個人の感想に終始してしまうことが多いです。

前提条件をしっかりと理解してもらい、意味のあるレビューをもらうために下記4点を気をつけましょう。

# 1, ターゲットユーザーを明確にする
「男性 or 女性」または「新規購入 or 継続利用」などターゲットユーザーによってデザインのアプローチ方法や情報の優先順にが大きく異なります。

わかりやすい例として弊社で運営している「グロービス学び放題」と「グロービス学び放題フレッシャーズ」の訴求画像を比較してみました。ターゲットユーザーの違いがデザインに大きく反映されています。

![qiita_img_02.jpg](https://qiita-image-store.s3.amazonaws.com/0/309303/19bc154f-83a5-9a9d-a335-54d95c8327d2.jpeg)

| |グロービス学び放題  |フレッシャーズ  |
|---|---|---|
|ターゲットユーザー  |若手〜中堅社員 |新入社員〜若手社員  |

このようにターゲットユーザーが違えば、写真選定やデザインのトンマナ、キャッチコピーなど様々な要素が変わってきますので、デザインレビュー前に明確にしましょう。

また、マーケティングという文脈で語られることが多いですが、最近では明治「THE Chocolate」のブランドリニューアルがターゲットユーザーやデザインの目的を明確にして成功した例だと思います。

[「あなたの年代がターゲットではない」上司へ放った“あのひと言”の真相｜明治のチョコレート革命 ](https://next.rikunabi.com/journal/20180221_c/)

# 2, デザインの目的を明確にする
当たり前の話かもしれませんが目的が違えば手段も大きく変わってきます。
下記はグロービス学び放題のカテゴリーのコース一覧ページです。

![qiita_img_03.jpg](https://qiita-image-store.s3.amazonaws.com/0/309303/bee93bc1-30be-21f6-d300-71617f1a9247.jpeg)

現状はじっくりとコース内容を吟味して次に学習するコースを探すためにデザインされたページです。なのでコースの説明が詳細に書かれていて、難易度順に縦に並べられています。

しかし、もし目的が「学びたいコースが決まっていてそれを探すページ」だったらどうでしょうか？
まず検索窓は必要になりますし、もしかしたら今までの学習履歴からリコメンドされた動画があればすぐに目的のコースを見つけることができるかもしれません。

# 3, 制約について明確にする
デザインするうえでほとんどの場合制約が存在します。

- 技術的制約（レスポンシブデザインだからレイアウトが制限されるなど）
- 期日的制約（納品までに期日がなく妥協しなかればならないなど）
- 予算的制約（予算がないから実装が難しいなど）…etc

制約によって理想的なデザインから妥協しなければならないこともあると思います。なので制約がある場合は事前に明確にしておきましょう。


# 4, 事前にメールやslackなどでデザインを共有しておく
個人的にはこれすごく重要なことだと思います。
なぜならば、考える時間がないとレビューの観点が抜け漏れしてしまう可能性があるからです。
また考える時間がないと反射的に個人の好みでレビューをする人も増えてしまうので、僕はレビューの1日前には1〜3の情報とともにデザインを共有するようにしています。

# まとめに変えて
いかがでしたか？本来であれば密に連携すべきですが「意思決定者が忙しすぎて難しい！！」と悩めるデザイナーの力になれたら嬉しいです！
今回初めてのqiiita投稿で至らない点も多々あった思いますがサトシの次回投稿に期待してもらえればと思います。

お疲れ様でした！
MySQLコマンドの整理

#MySQL

## DB作成
```
CREATE DATABASE DB_NAME;
```

## ユーザ覧取得
```
SELECT * FROM mysql.user
```

## 全権ユーザ作成
```
GRANT ALL PRIVILEGES ON DB_NAME.* TO "NEW_USER"@"localhost" IDENTIFIED BY "PASSWORD";
```



## ひとこと
随時更新します。