OmniAICreator/Qiita-1.07M huggingface dataset:
[Swift] map, flatMapの一般化された説明

# はじめに

　Swiftにおける`map`や`flatMap`についての記事は[Qiitaにもたくさんあります](https://qiita.com/search?q=Swift+map+flatMap)が、`Array`と`Optional`に限定されていて且つそれぞれ別々に説明されている記事が多いような印象を受けました(主観)。
　そこで、(自分が新しく作成した型について`map`で実装すべきか`flatMap`で実装すべきか迷った時に参照するためにも)この記事では`map`と`flatMap`の特性について*簡潔に* **一般化された説明**をしてみようという次第です。すごく詳細に一般化しようとすると「モナド」というものを理解しないといけないようですが、それは別の記事にお任せしましょう[^monad]。
　既に同様の記事があったらごめんなさい。あと、この記事ではSwiftに限った話をしていますので悪しからず…。

[^monad]: たとえば、「[モナドについてSwiftで説明してみた](https://qiita.com/koher/items/12f72f2fc2db7fa709cf)」。


# 総論

　`map`も`flatMap`も関数(クロージャ)を引数に取るいわゆる高階関数と呼ばれるものですが、元の型・引数となる関数(クロージャ)における返り値の型・高階関数の返り値の型に一定の関係性があり、その関係性によって区別がなされます。「二重が一重になるのがflat」みたいなのは一旦忘れてください。


# 各論

## `map`とは

### 動作

- `Hoge<T>`の場合: `(T) -> U`という関数(クロージャ)を引数にとって、`Hoge<U>`を返す。
- `Fuga<T1, T2>`の場合: `(T1) -> U`という関数(クロージャ)を引数にとって、`Fuga<U, T2>`を返す

即ち、**`map`は「引数となる関数(クロージャ)の返り値を同じ型で包み直す」**ということです。

### 例

- `Array<Element>`: `func map<T>(_ transform: (Element) throws -> T) rethrows -> Array<T>`
- `Optional<Wrapped>`: `func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> Optional<U>`
- `Result<Success, Failure>`: `func map<NewSuccess>(_ transform: (Success) -> NewSuccess) -> Result<NewSuccess, Failure>`


### 反例…？

- `String`: `func map<T>(_ transform: (Character) throws -> T) rethrows -> Array<T>`
- `Dictionary`: `func map<T>(_ transform: ((key: Key, value: Value)) throws -> T) rethrows -> Array<T>`

➡️これらは`Sequence`由来なので、**`Sequecne<Element>`において`(Element) -> T`という関数(クロージャ)を引数にとって`Sequence<T>`を返す**と考えれば矛盾はありません。



## `flatMap`とは

### 動作

- `Hoge<T>`の場合: `(T) -> Hoge<U>`という関数(クロージャ)を引数にとって、`Hoge<U>`を返す。
- `Fuga<T1, T2>`の場合: `(T1) -> Fuga<U, T2>`という関数(クロージャ)を引数にとって、`Fuga<U, T2>`を返す

即ち、**「引数となる関数(クロージャ)の返り値と`flatMap`自身の返り値は型が同じ」**ということです。


### 例

- `Optional<Wrapped>`: `func flatMap<U>(_ transform: (Wrapped) throws -> Optional<U>) rethrows -> Optional<U>`
- `Result<Success, Failure>`: `func flatMap<NewSuccess>(_ transform: (Success) -> Result<NewSuccess, Failure>) -> Result<NewSuccess, Failure>`


### あれ？Arrayは…？

`Array<Element>`で`flatMap`は`func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult: Sequence`となっています。なので、これは`Array`に対する`flatMap`ではなく、前述したような`String`と同様、**`Sequence<Element>`に対する`flatMap`**と捉えなければなりません。つまり、`flatMap`の引数となる関数(クロージャ)は`(Element) -> Sequence<U>`と考えることができ、そして`flatMap`の返り値も`Sequence<U>`と解釈できます。


# 注意

　昔のSwiftでは`flatMap`という名前で現在の`compactMap`と同じ動作が実装されていました。昔のドキュメントなどを参照して混乱なきよう…。
　ちなみに`compactMap`は`Sequence<Element>`において`.map(_:(Element) -> T?).filter({ $0 != nil })`というような動作をします(正しいコードではなくあくまでイメージ)。


# エピローグ

　`Result`を実装するPR内で[Appleの中の人](https://github.com/rjmccall)が`flatMap`について[コメント](https://github.com/apple/swift/pull/20958/files#r240047509)していた内容にインスパイアされた記事でした。`flatMap`を「二重になったものを一重にするんだ」と思っていると、`Result`における`flatMap`が「？？」となりそうだなと。
(OutSystems)実行時にRoleを付与/剥奪する

OutSystemsで作成したアプリケーション内で権限判定する際には、Roleを使うことが多いと思います。
Screen等の他の要素と同様に、モジュール内に作成するのですが、現 (2020/6/23)時点ではTraditional WebとReactive Web Appでは権限付与の動作に違いがあるようです。

簡単にいうと、
- Traditional Webでは、Grant/Revoke<Role名> Actionの結果はRoleのIs Persistent=Yesのときは永続的に残る。Noのときは、そのセッション中のみ有効
- Reactive Web Appでは選択の余地なく永続的に残る

# 権限付与/剥奪Action
共に、Roleを作成すると、自動的にRoleの下に作成されるActionを利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/9e3ff541-b53e-2ab6-c246-cc6c6490e3d9.png)
Grant<Role名>：UserIdで指定したユーザに対して<Role名>のRoleを付与します。Roleを持っている状態で重ねてGrantしても例外は発生しません。
Revoke<Role名>：UserIdで指定したユーザから<Role名>のRoleを剥奪します。同様にRoleを持っていない状態でRevokeしても例外は発生しません。

# 利用例
## 権限付与
ProductsOwnerというRoleを作成した場合の例。以下の例では、パラメータ（権限を付与するユーザー）をログインユーザー（GetUserId()）にしています（ログイン中のユーザーに、ProductsOwerというRoleを与えている）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/cae178ad-0f5a-c1c7-3535-2a43548cc6fd.png)

## 権限剥奪
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/1fe0460b-996b-91aa-5a59-ef83301c4c24.png)


## 結果確認
Personal Environmentでの手順を紹介します。
1. Usersアプリケーションにログインする（Personal Environmentを作成したOutSystemsアカウントを使用）
2. Usersタブで確認するユーザーを開く（Name列がリンクになっている）
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/d3513a76-fd1f-774a-d3dc-eec0646a5ebd.png)
3. ユーザーごとの一覧ページにRolesという欄があり、その下に確認したいRoleが表示されていれば、そのユーザーにRoleが付与されています

# Traditional Webの場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/094891b5-3eb1-8797-8a8c-b7ccfcd3854c.png)

## Is Persistent = Yesのとき
Grant/Revoke Actionの結果はUsersアプリケーションで確認できる。
Grant/Revoke操作の結果は、次回ログイン時にもそのまま残っています。

## Is Persistent = Noのとき
RoleのIs Persistent設定を変えたら、Publishしてからテストしてください。
Grant/Revokeした結果はそのセッション中のみ有効です。
Grant/RevokeしたあとにUsersアプリケーションを開いてみると、反映されていない事がわかると思います。
ログアウトして入り直してみると、アプリケーション上でも反映されていない。

この設定は、権限判定が別基盤にある場合（既存のたシステムの権限判定ロジックを流用したい場合）に、ログインごとに適切な権限を与えて動作させるときに使えますね。

# Reactive Web Appの場合
Reactive Web Appのモジュール内で作成したRoleのIs Persistentは作成した時点でYesです。
それだけでなく、プロパティ名の文字色が灰色になっていて変更できません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/9e3ff541-b53e-2ab6-c246-cc6c6490e3d9.png)

Is Persistent = Yesに固定です。
そのため、Reactive Web Appでは、Grant/Revokeすると、その結果は永続的（変更されるまで）に残ります。

## Reactive Web Appでの一般的なRoleの使い方
以前Qiitaに書いた記事があります。
[OutSystemsのReactive Web AppにおけるRoleのチェック](https://qiita.com/jyunji_watanabe/items/e5a4483bbc9924ab15fe)
【javascript】DSL構築

こちらの記事は以下の書籍を参考に執筆しました

- [入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)




#DLSとは
言語の機能や構文をうまく使って、その言語に最初からサポートされていたかのように特定のタスクを解決することです。
以降では文字列を処理するためのヘルパー関数を作成していきます。

#ヘルパー関数を作成する
前回のテンプレートの[記事](https://qiita.com/yktk435/items/8dd2c725ecab0250422e)ではこのようなコードを持つ関数を定義しました。

```javascript
function stringWS() {
  let stringParts = arguments[0];
  let values = [].slice.call(arguments, 1)
}
```

>出典： [PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


`let values = [].slice.call(arguments, 1)`で文字列部分と補間部分を取得しています。
しかし上記コードでは少しわかりにくいです。
さしあたり、この部分をレイヤ化して、ロジックの他の部分から隠してしまいます。
そのための関数を作成し、取得した値をタグ関数に渡すようにすれば良いでしょう。

```javascript
function createTag(func) {
  return function() {
    const strs = arguments[0];
    const vals = [].slice.call(arguments, 1);
    return func(strs, vals);
  }
}
```
>出典： [PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)



後は、タグ関数を次のように作成します。
```javascript
const stringW = createTag(function(strs, vals) {
  /* strsとvalsを使った処理 */
})
```
また渡された文字列strsと補間値valsをつなぎ合わせるためにreduceを使用する必要があります。これも抽象化してしまいます。

```javascript
function interlace(strs, vals) {
  vals = vals.slice(0); //配列のコピーを作成
  return strs.reduce(function(all, str) {
    return all + String(vals.shift()) + str;
  });
}
```
>出典： [PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


`vals = vals.slice(0);`で配列をコピーしています。
shiftのように配列をその場で変更してしまうときにはこのようにします。
あとはcreateTagとinterlaceを組み合わせれば標準的な実装でテンプレートリテラルを処理できます。

```javascript

const processNormally = createTag(interlace);

const text = 'Click Me';
const link = processNormally `<a>${text}</a>`; // <a>Click Me</a>
```
>出典： [PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)
水平、垂直な線を取り除く

```c#
var src = new Mat(@".\data.png", ImreadModes.Grayscale);

float[,] filterX = { { 0,  0, 0 },
                     { 0, -1, 1 },
                     { 0,  0, 0 },
};

float[,] filterY =  { { 0,  0, 0 },
                      { 0, -1, 0 },
                      { 0,  1, 0 },
};

var filter2D = new Mat();

Cv2.Filter2D(src, filter2D, MatType.CV_32FC1, InputArray.Create(filterX));
Cv2.Filter2D(filter2D, filter2D, MatType.CV_32FC1, InputArray.Create(filterY));

filter2D = Cv2.Abs(filter2D);

Cv2.Normalize(filter2D, filter2D, 0, 255, NormTypes.MinMax, MatType.CV_8UC1);

Cv2.Threshold(filter2D, filter2D, 1, 255, ThresholdTypes.Binary);

Cv2.ImShow("filter2D", filter2D);
Cv2.WaitKey();

byte[,] element1 = { { 0, 0, 1 },
                     { 0, 1, 0 },
                     { 1, 0, 0 },
};

Cv2.MorphologyEx(filter2D, filter2D, MorphTypes.Close, InputArray.Create(element1));

byte[,] element2 = { { 1, 0 },
                     { 0, 1 },
};

Cv2.MorphologyEx(filter2D, filter2D, MorphTypes.Close, InputArray.Create(element2));

var label = new Mat();
var stats = new Mat();
var centroids = new Mat();
var count = Cv2.ConnectedComponentsWithStats(filter2D, label, stats, centroids, PixelConnectivity.Connectivity8, MatType.CV_32SC1);

var indexes = stats.Col((int)ConnectedComponentsTypes.Area).SortIdx(SortFlags.EveryColumn);

var indexer = stats.GetGenericIndexer<int>();

var output = filter2D.CvtColor(ColorConversionCodes.GRAY2BGR);

for (int i = 0; i < indexes.Rows - 1; i++)
{
    var index = indexes.Get<int>(i);

    var area = indexer[index, (int)ConnectedComponentsTypes.Area];

    var rect = new Rect
    {
        X = indexer[index, (int)ConnectedComponentsTypes.Left],
        Y = indexer[index, (int)ConnectedComponentsTypes.Top],
        Width = indexer[index, (int)ConnectedComponentsTypes.Width],
        Height = indexer[index, (int)ConnectedComponentsTypes.Height]
    };

    if (area < 8)
    {
        output.Rectangle(rect, Scalar.Black, -1);
    }
    else
    {
        output.Rectangle(rect, Scalar.Red);
    }
}

Cv2.ImShow("output", output);

/*
// ConnectedComponentsWithStatsを使用せず、MorphologyExで白点を除去する場合
byte[,] element3 = { { 0, 1 },
                     { 1, 0 },
};

Cv2.MorphologyEx(filter2D, filter2D, MorphTypes.Open, InputArray.Create(element3));

byte[,] element4 = { { 1, 0 },
                     { 0, 1 },
};

Cv2.MorphologyEx(filter2D, filter2D, MorphTypes.Open, InputArray.Create(element4));

byte[,] element5 = { { 1, 1 },
};

Cv2.MorphologyEx(filter2D, filter2D, MorphTypes.Close, InputArray.Create(element5));

Cv2.ImShow("filter2D", filter2D);
*/
```
![f2f5fe992130d988852bf16f8401d8ec.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/214ec8d3-c985-edae-8685-f96297a90919.png)

![7fecdad7852049fdbebf477058ab934f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/3af87e70-a670-417d-79a5-3e548dfeab6f.png)

![3ac7d1778644f3549fa3543cf8b71a35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/e27455a7-bf61-4af4-8064-7046425e9e8a.png)
Cloud9インストールに困ったら

# このエラーが出て困ったら

`installation failed one or more errors....`

環境：Win10

## このコマンドをSSH接続のターミナルで試せ！
`curl -L https://raw.githubusercontent.com/c9/install/master/install.sh | bash`

# 参照
[AWS Cloud9 インストーラの使用](https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/installer.html)
ElasticBeanstalkのWorkerサーバーでLaravelのスケジューラを実行する

ElasticBeankTalk及び、Workerサーバー、またLaravelについての説明はしないので知らない人は対象外です。

まず、Laravelのタスクスケジューラですが、一般的にはcronを以下のように設定して利用します。

```
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```

ElasrticBeanstalkで利用する場合にどの様にcronを設定するのが良いでしょうか。
また、オートスケールなどでインスタンスが増えても1台だけが実行されることを守るにはどうしたら良いでしょう。

そんなときはElasticBeanstalkの機能を利用すると実現できます。
まずは`cron.yaml`というファイルをアプリケーションのルートディレクトリに作成します。
※このとき、`cron.yml`というファイル拡張子だと何故かEBで認識されませんでした

```yaml:cron.yaml
version: 1
cron:
 - name: "backup-job"
   url: "/backup"
   schedule: "0 */12 * * *"
 - name: "audit"
   url: "/audit"
   schedule: "0 23 * * *"
```
こちらは公式開発者ガイドの例です。
scheduleにcronの時間設定、urlにその際に実行してほしいHTTPエンドポイントが設定できることが見てわかります。

これだけではHTTPエンドポイントが利用されるのでLaravelのタスクスケジューラは利用できません。
なので、以下のライブラリを導入しましょう。

https://github.com/dusterio/laravel-aws-worker
導入方法はリポジトリを参照してください。

先程のcron.yamlは以下のように設定しましょう。

```yaml:cron.yaml
version: 1
cron:
 - name: "schedule"
   url: "/worker/schedule"
   schedule: "* * * * *"
```

これだけです。
これでEBでは毎分`/worker/schedule`を実行するQueueを発行します。

オートスケール時などは、EBはDynamoDBを利用してcronを実行するインスタンスのリーダーを選出しているそうです。
リーダーのインスタンスが利用できない状態になると、別のインスタンスがリーダーに再選出される仕組みになっています。

これで安心してタスクスケジューラを利用できますね。
古の書き方を卒業してちょいと今どきよりなJSを書こう

# はじめに

基本的にはワタクシ様はPHPを書いて日々過ごしているのですが、たまにjsを書いたりすることもあります。
さて業界では未だに `js = jQuery` みたいな方も少なくなく、jQueryでjsを覚えてそのままAngularとかに手を出さずCoffeeScriptとか通らなかった方はなんでか知りませんが、古文のようなES5以前のjsを書くことが多い印象があります。
ES6(ES2015)が世に爆誕してから5年も経つと便利さ、書きやすさが桁違いにUPします。
ES5があまりにも書きづらくてCoffeeScriptやTypeScriptやDartや **Reactに関係ない方のJSX** などといったaltJSと呼ばれるものが2010年頃からポコポコ生まれていったわけですが、それらの影響を受け、格段に書きやすくなった今どきなjsの書き方をふたつばかり紹介していきたいと思います。

# varからの卒業

```javascript
// ES5以前
var hoge = ''; // よくない

// ES6以後
const hoge = ''; // 中身が変わらない予定ならこっち（そのうち書き換えが効かなくなると思う）
let hoge = ''; // 書き換わるならこっち
```

`var` で変数宣言をする時代は終わりです。今は `const` と `let` です。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/const

varがダメなわけではないのですが、varは関数全体だったりとかグローバル全体に影響を及ぼしてしまい大変危険だったわけです。
「お前は今まで食べたパンの数を数えてるのか」ばりに宣言した変数名を全部記憶してるならvarでもいいのですが、そんな自身がないなら `const` か `let` を使いましょう。
使い分けとしてはずっと中身が変わらないなら `const` 、変わるなら `let` です。

# functionからの卒業

```javascript
// ES5以前
var hoge = function(fuga){return '';};
var obj = {
    onClick: function(e){
        return e.target;
    }
};

// ES6以後
const hoge = fuga => {return '';};
const org = {
    // 旧来のメソッド定義と同じ
    onClick(e){
        return e.target;
    },
    // こちらはthisがうごかなくなる
    onClick: e => {
        return e.target;
    },
};
```

ES5の頃はfunction宣言地獄だったわけですが、ES6以降はそんな心配はありません。
というか、functionというキーワードを書く機会もあんまりなくなると思います。
普通の無名関数ならかっこいいアローファンクションが使えますし、アローファンクション使うと「呼び出し元によってthisが変わっちまう問題」から開放されます。違う問題には直面しますが……
オブジェクトのメンバーに関数を定義する「メソッド定義」はちょっとJavaっぽい書き方ができるようになりました。
もちろんアローファンクション使ってメソッド定義もできるのですが、thisの意味合いが変わってしまうので、全く同じようには動作しないので注意が必要です。


# 参考記事

* [ES5とES6の違いをまとめてみた(メモ)](https://qiita.com/rifutan/items/a55f132d4dae7e2f1941)
* [今更聞けない最近のJavaScript（ES6とか）](https://qiita.com/kyuu1999/items/04ad1a087718cee73b20)
macでスクリーンショットのファイルフォーマットをjpgに変える方法

pngで保存されるとinstagramでアップロードができない。
そこでjpgで保存されるようにすると便利だ。
その為にはterminalのコマンドラインで以下のコマンドを実行すればよい。

```.sh
$ defaults write com.apple.screencapture type jpg
$ killall SystemUIServer
```
【Vue】google-maps-api-loaderで郵便番号から住所を補完させる

## 概要
入力された郵便番号を元に、Google Maps API([google-maps-api-loader](https://www.npmjs.com/package/google-maps-api-loader))を利用して「都道府県／市区町村／番地」を取得してオートコンプリートでフォームを補完させる方法

## 事前準備
- ライブラリの導入

```bash
yarn add google-maps-api-loader
yarn add axios
```

## 実装

```vue
<template>
  <div>
    <label>郵便番号</label>
    <input
      @input="onChangePostalCodeFirst($event)"
    />
    -
    <input @input="onChangePostalCode($event)" />
    <select v-model="prefectureId">
      <option :value="null" disabled>選択してください</option>
      <option
        v-for="prefecture in prefectures"
        :key="`prefecture-${prefecture.value}`"
        :value="prefecture.value"
      >
        {{ prefecture.label }}
      </option>
    <input ref="address" v-model="address" />
  </div>
</template>

<script>
import GoogleMapsApiLoader from 'google-maps-api-loader'
import axios from 'axios'

export default {
  data() {
    return {
      address: '',
      prefectures: [
        { label: '北海道', value: 1 },
        { label: '青森県', value: 2 },
        ...省略...
      ]
    }
  },
  methods: {
    onChangePostalCodeFirst(event) {
      if (event.target.value.length === 3) {
        this.$refs.postalCodeSecond.focus()
      }
    },
    async onChangePostalCodeSecond(event) {
      if (event.target.value.length === 4) {
        const google = await GoogleMapsApiLoader({
          apiKey: *************,  // APIキーを入力
          libraries: ['places']
        })

        const address = new google.maps.Geocoder()
        address.geocode(
          {
            address: this.postalCode,
            region: 'jp'
          },
          (results, status) => {
            if (status === google.maps.GeocoderStatus.OK) {
              let address = results[0].address_components
              address.shift() // '日本'を削除
              address = address.reverse() // 住所を逆ソート
              address.shift()  // 郵便番号を削除
              address = address.map(data => {
                return data.long_name  // 住所のテキストを抜き出し
              })
              const prefecture = address.shift()  // 都道府県を抜き出し

              this.prefectureId = this.prefectures.find(p => {
                return p.label === prefecture
              }).value
              this.cityAddress = address.join('')
            }
          }
        )
      }
    }
  }
}
```

## 動作
[![Image from Gyazo](https://i.gyazo.com/36aba524d6af62aeb181fc2e12855218.gif)](https://gyazo.com/36aba524d6af62aeb181fc2e12855218)

## 参考
- [Geocoding Service  |  Maps JavaScript API  |  Google Developers](https://developers.google.com/maps/documentation/javascript/geocoding)
- [便利すぎる！Google Maps APIで郵便番号から住所を取得する！サンプルそのまま使えます - Qiita](https://qiita.com/kenzooooo/items/e612671e592dc1d55f24)
Vue.js(CLI)

#Vue CLIインストール方法

**ターミナル**

`npm install -g @vue/cli`

`vue create udemy-vue.js`  　udemy-vue.jsは自分の好きな名前

`default (babel, eslint)`　　選択

`cd udemy-vue.js`　　　　　　　ディレクりに移動

`npm run serve`


[![Image from Gyazo](https://i.gyazo.com/08e8af9bb9c4e58a9c65176f50a99159.png)](https://gyazo.com/08e8af9bb9c4e58a9c65176f50a99159)


`http://localhost:8080/`　　ローカル環境で作業開始
Ruby Minitestを試す

# 目的
Railsのデフォルトのテスティングフレームについてアウトプットする。
# テストコードのひな形
Minitestを使ったテストコードのひな形は下記の通り。

```ruby:sample_test.rb
require 'minitest/autorun'

class SampleTest < Minitest::Test
  def test_sample
    assert_equal 5, 'こんにちは'.length
  end
end
```

・1行目でMinitestに必要なライブラリを呼び出す。
・SampleTestクラスにMinitest::Testクラスを継承させる。
・SampleTestクラス内に、実行対象となるテストメソッドを定義する(test_sample)
という流れで作成できる。

assert_equalは検証メソッドで、第1引数には予想される値、第2引数は検証する値を入れる。
したがって、test_sampleメソッドは、「'こんにちは'という文字列の文字数」が「5文字」であるかをテストしている。
結果として等しくなるので、テストはパスする。
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496707/e9f06c3f-13b7-a0b4-d6f9-35dd47187d01.png)
・runs: 実行したテストメソッドの件数(test_sampleのみなので1件)
・assertions: 実行した検証メソッドの件数(assert_equalを1回使用)
・failures: 検証に失敗したテストメソッドの件数
・errors: 検証中にエラーが出たテストメソッドの件数
・skips: skipメソッドにより実行をスキップされたテストメソッドの件数
を表している。

# 検証メソッドの例
http://docs.seattlerb.org/minitest/Minitest/Assertions.html
MinitestのAPIドキュメントを参考にいくつか検証メソッドを使ってみる。

```ruby:hello_test.rb
require 'minitest/autorun'

def hello(name)
  puts "#{name}さん、こんにちは！"
end

class HelloTest < Minitest::Test
  def test_hello
    assert_output("Bobさん、こんにちは！\n") { hello("Bob") }
  end
end
```

assert_outputを使うと、標準出力した内容をテストできる。

```ruby:multiple_of_eleven_test.rb
require 'minitest/autorun'

def multiple_of_eleven?(number)
  number % 11 == 0
end

class MultipleOfElevenTest < Minitest::Test
  def test_true
    assert multiple_of_eleven? 121
  end
  def test_false
    refute multiple_of_eleven? 13
  end
end
```

assert,refuteメソッドを使うと、真偽をテストできる。
# 後書き
Minitestを使うと簡単にテストを実装できるので、活用してみる。
今度はRspecについてもアウトプットしたい。
# 参考文献
プロを目指す人のためのRuby入門
伊藤 淳一［著］
Mac PC で画面領域をはみ出すページ全体のスクショを撮る方法

Mac PC で画面領域をはみ出すページ全体のスクショを撮る方法。

そもそも画面一部のスクリーンショットだけじゃなくて、 **画面領域をはみ出すページ全体のスクショを撮ることができる** ことを知らない人もいるかも、と思ってこの記事を書いています。

例えばこういう画像としてダウンロードできます。

![FireShot Capture 004 - 並行モデルとイベントループ - JavaScript - MDN - developer.mozilla.org.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/2118c0c4-5e3a-a783-305e-5200ba371158.png)


やり方を二つ紹介します

### Chrome Developer Tool を使う方法

1. developer tool を開く
2. ちょっと左にある3点ポチのところクリック  ![貼り付けた画像_2020_06_25_16_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/dc1c1e33-3da8-0f61-565d-2799d8900a92.png)
3. capture full size screenshot  ![貼り付けた画像_2020_06_25_16_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/e0c9aa16-2895-75ea-5e76-41ac71e98256.png)



### Chrome 拡張を使う方法

色々あるかと思いますが、使ってみて便利そうだったものを紹介します。非エンジニアに紹介するなら上記の方法よりいいかもしれません。

> ウェブページ全体をスクリーンショット - FireShot

https://chrome.google.com/webstore/detail/take-webpage-screenshots/mcbpblocgmgfnpjjppndjkmgjaogfceg/related?hl=ja

### 蛇足
Widonwsだと以下のショートカットでできるらしいです。未検証。

同僚曰く 「Windows＋SHIFT＋S が最強に便利」

Mac PCでショートカットを調べてみてすぐに出てこなかったのですが、もし知っている方いれば教えていただけるとありがたいです。
hostsの設定が効かない時に試したこと

### PCのDNSキャッシュをクリア 
```sh
sudo dscacheutil -flushcache
```

### chromeのDNSキャッシュをクリア

chrome://net-internals/#dns へアクセス
Clear host cacheをポチってchrome再起動

### hostsファイルのパーミッションを変更
結局これで解決した

```sh
chmod 644 /private/etc/hosts
```
なんでパーミッション変わってんの...
composerの調子が悪かったがなんとか解決

Debugbarをインストールしようとしたんですがプロンプトが途中で止まって返ってこなくなりました。

```
$ composer require barryvdh/laravel-debugbar --dev
```

## 問題
調子が悪い時は以下のコマンドでどこが悪いかを調べるそうです。

```
$ composer diagnose
```

しかし、私の場合以下の場所でフリーズしました。

```
$ composer diagnose
composer diagnoseChecking composer.json: OK
Checking platform settings: OK
Checking git settings: OK
Checking http connectivity to packagist:
```

## 対策

```
$ composer self-update --preview
$ composer update -v
$ composer diagnose
```

## Debugbarの設定の続き
やっとインストールできたので設定を追記して動作確認

```php:config/app.php
    'providers' => [
+       Barryvdh\Debugbar\ServiceProvider::class,
    ],

    'aliases' => [
+       'Debugbar' => Barryvdh\Debugbar\Facade::class,
    ]
```

### 参考
- [[PHP]Composer使用時にエラーが発生したとき、最初に確認すること](https://akamist.com/blog/archives/163)
- [Laravel5.7: Laravel Debugbarを使う](https://qiita.com/sutara79/items/9fd442a81001842aeba1)
Bashでリリースツールを実装しての備忘録

# 背景
Bashでリリースツールを実装した際に少し詰まった部分について記述する。
とくに`rsync`は単純なようで動かしてみると全然思った挙動をしてくれなかった。
単体テストは念入りに行うこと。

# rsync
移送対象をファイルから読み込む際は`exclude-from`オプションを使用する。
`include-from`や`files-from`を利用するより直感的に操作できる。
ファイルの書式は次の通り。

```
+ */
+ path/to/file1.extension
+ path/to/file2.extension
+ path/to/file3.extension
- *
```

`+`は移送対象、`-`は除外対象になる。
`+`で指定するパスは`rsync`コマンドを実行するディレクトリからの相対パスになるので注意する。
`+ */`がないとコマンド実行ディレクトリからサブディレクトリ以下に配置されたファイルが認識されない。
これは本来、ディレクトリごとに`+`で指定する必要があるため。

```
rsync --exclude-from=/path/to/transfer.list /path/to/source /path/to/target
```

# 配列
資源のパスと所有者のような対応関係を記述する際は連想配列を使用する。

```
declare -A RESOURCE_PATH=(
  ["source1"]="/path/to/source1"
  ["source2"]="/path/to/source2"
  ["source3"]="/path/to/source3"
)

declare -A RESOURCE_OWNER=(
  ["source1"]="owner1:group1"
  ["source2"]="owner2:group2"
  ["source3"]="owner3:group3"
)

for resource in ${!RESOURCE_PATH[@]};
do
  # 処理内容
  <command> ${RESOURCE_PATH[${resource}]}
  <command> ${RESOURCE_OWNER[${resource}]}
done
```

ただし、これは連想配列であって配列のような順序関係はない。
宣言通り、`source1 -> source2 -> source3`の順に処理するにはさらに配列を使用する。

```
declare -A RESOURCE_PATH=(
  # 省略
)

declare -A RESOURCE_OWNER=(
  # 省略
)
declare -a RESOURCE=(
  "source1"
  "source2"
  "source3"
)

for resource in ${RESOURCE[@]};
do
  # 処理内容
  <command> ${RESOURCE_PATH[${resource}]}
  <command> ${RESOURCE_OWNER[${resource}]}
done
```

# trap
シェルが異常終了する場合などの終了処理を組み込む際は`trap`を使用する。
`trap`はシェルが受け取るシグナルをトリガーとするので`kill`コマンドで強制終了される際にも有効。

```
trap "
  rm -rf ${temp_directory}
  rm -f ${temp_file}
  exit ${return_code}
" 0 1 2 3 9 15                  # trapを発火させるシグナル
```

# 後記
実際には上に書いたことより、シェルのオプションに何を用意するか、ヘルプをどう記述するかを考えたり、
また、リリースツールを第三者に動かしてもらっての手順書のレビュー指摘箇所修正などに時間を取られた。
GUIがない分、Bashに明るくない人間が読むと挙動や操作方法が理解できないものになりやすい。
実行ログは多すぎるくらい出してちょうどいい。各種コマンドの`verbose`オプションを積極的に利用すること。
Nuxt の redirect では vue-router の name が変わらない件

## この記事について
Nuxt の middleware や plugin でリダイレクトするのに
`redirect('hogehoge');`
のような書き方をしていたら、動作が想定外で困った＆解決した話です。


## 困ったこと
### `router.push()` では route.name が変わる

こんなコードがあったとして

```javascript:pages/mypage.vue
export default Vue.extend({
    created() {
        this.$router.push('/login');
    }
});
```

```javascript:pages/login.vue
export default Vue.extend({
    created() {
        console.log(this.$route.name);
        // "login"
    }
});
```

ブラウザから `mypage` を呼び出してリダイレクトされた場合でも、 `route.name` は `login` になっています。

### Nuxt の `redirect` を使うと route.name が変わらない

```javascript:middleware/redirectLogin.vue
export default function({ redirect }) {
    // 〜ログイン済チェクとか〜
    redirect('/login');
}
```

```javascript:login.vue
export default Vue.extend({
    created() {
        console.log(this.$route.name);
        // "mypage"
    }
});
```

ブラウザで見る限りは `login` にリダイレクトされているけれど、 `route.name` は最初にアクセスしようとした `mypage` のまま・・・

## 解決方法
### `redirect` を使って route.name を変える方法
これだと、 middleware や plugin で `route.name` を参照している場合、リダイレクト後に想定しない挙動が起きてしまうことがあります。

```javascript:middleware/redirectLogin.vue
export default function({ route, redirect }) {
    // login ページに来ていたらチェックしない
    if (route.name === 'login') {
        return;
    }
    // ブラウザから見たら login に来ているけど、 route.name が mypage のままなので通過してしまう

    // 〜ログイン済チェクとか〜
    redirect({ name: 'login' });
}
```

困ったな〜と思っていたら、ちゃんと解決方法がありました🎉
https://github.com/nuxt/nuxt.js/issues/2421


```javascript:middleware/redirectLogin.vue
export default function({ redirect }) {
    // 〜ログイン済チェクとか〜
    redirect({ name: 'login' });
}
```

```javascript:login.vue
export default Vue.extend({
    created() {
        console.log(this.$route.name);
        // "login"
    }
});
```

コードを見ると、以下のように `router.resolve` してくれていました。
これで安心！

```javascript:utils.js
       if (pathType === 'object') {
         path = app.router.resolve(path).href
       }
```
display:none の打ち消し

##特定のクラスだけdisplay:noneを打ち消したい時
画像のように`chart-container expanded`クラスは表示させたいが、それ以外のclassは非表示にしたい。
<img width="435" alt="スクリーンショット 2020-06-25 16.19.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417196/2ce7b371-6afd-f63e-6673-c86b39eb2f57.png">

##ポイント
display: flex など指定したら負けるので表示されてしまう
display:none に important をつけたスタイルを自分で設定しておけば大丈夫

```css
.chart-container .ringTotals{
        display:none;
    }
    .chart-container.expanded .ringTotals{
        display:flex!important;
    }
```

これでdisplay:none;を打ち消すことができる
djangoでアップロードしたファイルをMinIOに投入する

### 概要
- [django](https://vroid.com/)を使って、ファイルアップロードエンドポイントを作った際に、取得したファイルオブジェクトをそのままMinIO(https://min.io/)に投入する手順
- 備忘録

---
### 前提
- 環境
    - python: v.3.7.7
    - django: v.2.0.3
    - minio: 5.0.13

---
### Template
- 簡単なアップロード用のtemplateを用意する

```html
{% extends 'base.html' %} // 必要であればベースを読み込んでおく
{% block content %}
// ファイルアップロードのためには、enctypeの記述が必要
<form method="POST" action="{% url 'upload_to_minio' %}" enctype="multipart/form-data">
    {% csrf_token %}
    // ファイルアップロード用 input
    <p>
        <label for="myfile">File:</label>
        <input type="file" name="myfile" required id="myfile">    
    </p>
    // アップロードボタン
    <button type=“submit”>アップロード</button>
</form>
{% endblock %}
```

### urs.py
- uploadのエンドポイント用URLを設定する

```
urlpatterns = [
    path("umc/upload_to_minio/", views.UploadToMinio.as_view(), name="upload_to_minio"
]
```

### views.py
- アップロードされたファイル情報を取得し、MinIOに格納するロジックを記載する

```python
class UploadToMinio(generic.View, LoginRequiredMixin):
    def post(self, request, *args, **kwargs):
        try:
            # アップロードされたファイルは、request.FILESに格納されている
            myfile = self.request.FILES['myfile']
            # ファイルのバイナリデータをメモリ上に読み込む
            # 巨大ファイルを取り扱う場合は注意
            file_obj = myfile.read()
            # ファイルサイズを取得
            file_size = myfile.size

            # 格納先のbucket名
            bucket_name = 'hoge'
            # 格納先のobject名
            object_name = 'fuga'

            # minio client
            minioClient = Minio(
                'host:port', # MinIOのアクセス先
                access_key='access_key', # 各環境のaccess_key
                secret_key='secret_key', # 各環境のsecret_key
                secure=True) # https通信の場合はTrue

            # bucketが存在しなければ作成する
            if not minioClient.bucket_exists(project_id):
                minioClient.make_bucket(bucket_name=bucket_name)

            # objectの作成
            minioClient.put_object(
                bucket_name=project_id,
                object_name=uuid,
                data=io.BytesIO(file_obj),
                length=file_size
            )
```
- `put_object` の `data` は `io.RawIOBase` を継承したオブジェクトしか受け付けない。そのため、 メモリ上のオブジェクトに対して `io.BytesIO()` でバイナリストリーム化してあげる。


---
これで動くはず
pandas.IntervalをStringにキャストする方法

pd.cutしたDataFrameをto_sqlするときに以下のエラーが起きて悩んだのでメモ

```bash
sqlite3.InterfaceError: Error binding parameter 3 - probably unsupported type.
```

###👇astype(object)はエラー🤮

```python
df['interval'] = pd.cut(df['x'], 3)
df['interval'] = df['interval'].astype(object)
df['interval'] = df['interval'].str.replace(', ', '~')
```

```bash
TypeError: Object of type 'Interval' is not JSON serializable
```


###👇astype(str)はいける🙆‍♂️

```python
df['interval'] = pd.cut(df['x'], 3)
df['interval'] = df['interval'].astype(str)
df['interval'] = df['interval'].str.replace(', ', '~')
```

無事書き出せました。
slimの始め方

# slimのインストール
アプリのフォルダ内でslimをインストールする。

```
gem install slim
```

これで拡張子が.html.slimのslimファイルを、みなさんが普段使っている.html.erbとして変換されるようになるそうです。

```
gem install html2slim
```
これでhtml.erb　→　html.slim　に変換させることができるようになるそうです。

```
bundle exec erb2slim app/views app/views
```

これでエラーが出た場合は、gemfileに下記の２文を追加してbundle installします。

```
gem 'slim-rails'
gem 'html2slim'
```

```
bundle install
```

これでviewフォルダに元からあったerbファイルを削除するそうです。
※拡張子が.erbのファイルがない場合は、飛ばしてよし。

```
bundle exec erb2slim app/views app/views -d
```

今後自動的にslimファイルを作成されるようにするためには　、
config/application.rbにあるconfigを以下のようにslimを指定すればOK。

```config/application.rb
module App
  class Application < Rails::Application
    config.generators.template_engine = :slim #slimに変更
  end                                                                                                                                                                     
end
```

#slimファイルを表示させる前の準備

```
rails g controller tweets
```

viewフォルダのなかに、tweetsフォルダができています。
そのなかにindex.html.slimというファイルを新しく作ります。
そのファイルの中に分かりやすいように何か書いておきましょう。

```views/tweets/index.html.slim
Hello, world!
```

コントローラーの中にindexアクションを追加しておきます。

```controllers/tweets_controller.rb
class ArchivesController < ApplicationController
	def index
	end
end
```

次にルーティングです。

```config/routes.rb
Rails.application.routes.draw do
  root "tweets#index"
end
```



# サーバーを再起動して、ページを表示
サーバーの再起動を忘れないようにしましょう。
再起動しないままだと、「ArchivesController#index is missing a template for request formats: text/html」というようなエラーが出ます。

http://localhost:3000/


# 参考記事
- https://qiita.com/ngron/items/c03e68642c2ab77e7283
- https://teratail.com/questions/149418
Matクラスからデータを取り出してダンプする

```C#
private string Dump(Array data, List<int> indices, int dimension = 0)
{
    string result = "[ ";

    for (var i = 0; i < data.GetLength(dimension); i++)
    {
        if (dimension == data.Rank - 1)
        {
            var temp = data.GetValue(indices.Concat(new int[] { i }).ToArray()).ToString();

            temp = Regex.Replace(temp, @"(Vec[2346][bdfisw] )|([xyz]:)", "");
            temp = Regex.Replace(temp, @"\(", "[");
            temp = Regex.Replace(temp, @"\)", "]");

            result += temp;

            if (i != data.GetLength(dimension) - 1) result += ", ";
        }
        else
        {
            result += Dump(data, indices.Concat(new int[] { i }).ToList(), dimension + 1);                    
            
            if (i != data.GetLength(dimension) - 1) result += ", ";
        }
    }

    return result += " ]";
}

private void Test()
{
    byte[,] array = { { 255, 255, 255, 255, 255, 255, 255, 255 }, 
                      { 255, 255, 255, 255, 255, 255, 255, 255 }, 
                      { 255, 255,   0,   0,   0,   0, 255, 255 }, 
                      { 255, 255, 255, 255, 255, 255, 255, 255 }, 
                      { 255, 255, 255, 255, 255, 255, 255, 255 }, 
    };

    Mat mat = InputArray.Create(array).GetMat();

    mat.GetRectangularArray(out byte[,] data);

    string dump = Dump(data, new List<int>());

    Console.WriteLine(dump);
}
```
結果：
[ [ 255, 255, 255, 255, 255, 255, 255, 255 ],
 [ 255, 255, 255, 255, 255, 255, 255, 255 ],
 [ 255, 255, 0, 0, 0, 0, 255, 255 ],
 [ 255, 255, 255, 255, 255, 255, 255, 255 ],
 [ 255, 255, 255, 255, 255, 255, 255, 255 ] ]
ブラウザ上でzipファイルを圧縮展開できるWebアプリを作ってみた

こんにちわ。

創作意欲が湧いた勢いで、JavaScriptからzip形式のアーカイブを操作できる "JSZip" というライブラリを使用して、ブラウザ上でzipを圧縮展開できる簡単なWebアプリを作ってみました。

- [JSZip - GitHub](https://github.com/Stuk/jszip)


# 作ったもの
- [Online Zipper - github.io](https://dojyorin.github.io/webapps/stable/zip.html)

めちゃくちゃシンプルです。

Babelは通してないので、動作確認済のChrome以外は新生EdgeやFirefoxでなら多分動くと思います。


# 仕組み
凝ったことはしていないので、とても簡単です。

1. Input要素でファイルを読込
2. ファイルをワーカースレッドへ転送
3. ワーカースレッドでJSZipをロードし圧縮展開
4. 処理結果をメインスレッドへ転送
5. a要素に処理結果のBlobURLを充ててダウンロード

全ての処理がローカルで完結しています。

ヘビータスクの圧縮展開はWebWorkerで処理しており、かつファイルはTypedArray化して参照渡し(Transferable Object)しているので、処理中の描画レスポンスへの影響はほとんどありません。
Firebase Cloud Messagingで「FirebaseError: Messaging: This browser doesn't support the API's required to use the firebase SDK. (messaging/unsupported-browser).」

# Firebase Cloud Messaging(以下FCM)で「FirebaseError: Messaging: This browser doesn't support the API's required to use the firebase SDK. (messaging/unsupported-browser).」が出た場合

Chromeの最新版で FCM をつかっていて遭遇した。

## 原因
原因はFCM使ったアプリに<font color=red>**http**でアクセス</font>していたということ

ngrokをつかってデバッグしているときに、うっかり http でアクセスしてしまっていた。
エラーメッセージを読むと「ブラウザがAPIに対応していない」ようにみえてしまうので注意。

## 対策
FCMのクライアントとなるWebアプリは**https**でアクセスしましょう。または開発・デバッグ時は**http://localhost**も可。
Shifter API で Generate Artifact してみた。

# ０．はじめに

AWS EC2 [AMIMOTO](https://ja.amimoto-ami.com/) で [WordPress](https://wordpress.com) サイトを構築してまして…、

それで、先日、[WordPress](https://wordpress.com) を [Shifter](https://go.getshifter.io) に移行したんですが…、

「[WordPress](https://wordpress.com) の予約投稿出来ないの？」という話がありまして…、

とりあえず、[Shifter](https://go.getshifter.io) の API を使って、 Generate Artifact してみました。

参考にしたのは、こちらの記事です。

* [Shifter API \| Shifter Documentation](https://support.getshifter.io/en/articles/762113)
* [Swagger UI](https://developer.getshifter.io/)

事前設定として、

サイトの設定で、「Auto Publish」にチェックしておきます。

![FireShot Capture 386 - Shifter Dashboard - go.getshifter.io.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161939/2743003d-7e1b-4ae7-2e68-1a0f52e8f39f.png)

# １． アクセストークンを取得する。

```bash
# Get an accessToken to access Shifter resources.
curl -X POST "https://api.getshifter.io/latest/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"username\": \"[username]\", \"password\": \"[password]\"}"
```
* username : ログインユーザーID
* password : ログインパスワード

```json
{
  "AccessToken": "[AccessToken]",
  "RefreshToken": "[RefreshToken]"
}
```
* AccessToken : アクセストークン
* RefreshToken : リフレッシュトークン

# ２． サイトを Generate Artifact する。

```bash
# Generate artifact.
curl -H "Authorization: [AccessToken] -X POST "https://api.getshifter.io/latest/sites/[Site ID]/artifacts" -H "accept: application/json""
```
* [AccessToken] : 取得したアクセストークン
* [Site ID] : Generate Artifact するサイトID

```json
{
    "project_id":"[Project ID]",
    "artifact_id":"[Artifact ID]"
}
```
* project_id : プロジェクトID
* artifact_id : アーティファクトID

# ３． Generate した Artifact にコメントを追加する。

```bash
# Update your artifact name.
curl -H "Authorization: [AccessToken] -X PUT "https://api.getshifter.io/latest/sites/[Site ID]/artifacts/[Artifact ID]/artifact_name" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"artifact_name\": \"[Artifact Name]\"}""
```
* [AccessToken] : 取得したアクセストークン
* [Site ID] : Generate Artifact するサイトID
* [Artifact ID] : 取得したアーティファクトID
* [artifact_name] : Artifact に追加するコメント

```json
{}
```

# ９９．ハマりポイント

* 今回は、特にハマることもありませんでした。
* [Swagger UI](https://developer.getshifter.io/) もあったので、わかりやすかったです。

# ＸＸ．まとめ

今回は、とりあえず curl コマンドを確認するまでやってみました。

「[WordPress](https://wordpress.com) の予約投稿出来ないの？」という話だったので、そのまま bash のシェルを作成するとか、別の言語使うなりして、スクリプト作成して、それを、クローンとか、スケジューラとかに登録すれば良いかなと。

その辺は、先々やってみようかなと、思います。

* ※ 参考
    * [ShifterAPIとNo Future Postsプラグインで擬似的な予約投稿にトライ \- 株式会社デジタルキューブ](https://www.digitalcube.jp/shifter/4267/)

以上、ご参考になれば ♪♪♪

👋👋👋
JSON通信に置ける文字列取扱いについて

## json通信における日本語取説

[jsonの仕様上](https://www.json.org/json-en.html)、日本語ははunicode escapeする必要はない
unicode escapeしない場合、機密漏洩上よくないが、デコードすれば解読可能のためいいんじゃないって話
それでもXSSなどセキュリティ大丈夫なのは、制御文字列を¥マークエスケープすればいいから（→どうゆうこと？）

↓こうゆうこと。
[クロスサイトスクリプティング](https://cybersecurity-jp.com/security-measures/33684#XSS)

scriptタグで囲ったデータを登録されることにより、そのデータがブラウザにscriptタグとして、読み込まれて不正なスクリプトが実行されてしまう可能性がある。だから制御文字列は、エスケープする必要がある。

- セッションハイジャック
- 入力フォームのタグを埋め込まれ個人情報不正窃取される
- Webページに偽の情報を表示させる
- Webページ上で強制的に操作される


## pythonの日本語のunicode escape問題
[json標準ライブラリ](https://docs.python.org/ja/3/library/json.html#py-to-json-table)

`json.dumps(str, ensure_ascii=False)` により日本語化を実現可能。

>ensure_ascii が (デフォルト値の) true の場合、出力では入力された全ての非 ASCII 文字はエスケープされていることが保証されています。ensure_ascii が false の場合、これらの文字はそのまま出力されます。

しかし、上記の実装のままだと制御文字列のエスケープが実施されなくなるため、脆弱性を生み出してう。

## MUST be escaped
[JSON仕様書](https://tools.ietf.org/html/rfc8259)
[制御文字コード](http://ash.jp/code/ctrltbl.htm)

### the characters MUST be escaped:
※quotation mark, reverse solidus, and the control characters (U+0000 through U+001F).

|No.|文字列|
|---|---|
|1.|"(ダブルコーテーション)|
|2.|\(バックスラッシュ)|
|3.|NULl（ヌル）|
|4.|Start Of Heading（ヘッダ開始）|
|5.|Start of TeXt（テキスト開始）|
|6.|End of TeXt（テキスト終了）|
|7.|End Of Transmission（転送終了）|
|8.|ENQuiry（問合せ）|
|9.|ACKnowledge（肯定応答）|
|10.|BELl（ベル）|
|11.|Back Space（後退）|
|12.|Horizontal Tabulation（水平タブ）|
|13.|Line Feed（改行）|
|14.|Vertical Tabulation（垂直タブ）|
|15.|Form Feed（改ページ）|
|16.|Carriage Return（復帰）|
|17.|Shift Out（シフトアウト）|
|18.|Shift In（シフトイン）|
|19.|Data Link Escape（伝送制御拡張）|
|20.|Device Control 1（装置制御1）|
|21.|Device Control 2（装置制御2）|
|22.|Device Control 3（装置制御3）|
|23.|Device Control 4（装置制御4）|
|24.|Negative AcKnowledge（否定応答）|
|25.|SYNchronous idle（同期信号）|
|26.|End of Transmission Block（転送ブロック終了）|
|27.|End of Transmission Block（転送ブロック終了）|
|28.|CANcel（取消）|
|29.|End of Medium（媒体終端）|
|30.|SUBstitute（置換）|
|31.|ESCape（拡張）|
|32.|File Separator（ファイル分離）|
|33.|Group Separator（グループ分離）|
|34.|Record Separator（レコード分離）|
|35.|Unit Separator（ユニット分離）|
[1行で完了]最速でReact環境構築

※自分のアウトプット用(メモ)です
## 結論だけ知りたい人用
1行のコマンドで`React`の環境構築を完了する。
[条件]
1.Node.js 8.10以上
2.npm 5.6以上

```bash
$ npx create-react-app プロジェクト名
```
順番通り説明していきます。
## 必要なパッケージのインストール方法
### 1. `brew`をインストール
Macのパッケージ管理システムであるbrewをインストール。
[brew公式サイト](https://brew.sh/)

```bash
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

### 2. `nodebrew`を`brew`でインストール
nodeのバージョン管理ができるnodebrewをインストール。
（brewでインストールするので先にbrewをインストールした）。

```bash
$ brew install nodebrew
```

### 3. `Node.js`を`nodebrew`を使ってインストール
Node.jsはnodebrewで管理した方が使いやすいと思います。他のバージョンに移るの簡単ですし、普通にインストールすると削除するのに手間なんですよね...
ほとんどの場合、安定版をインストールしておけば問題ないと思います。

```bash
// リモートにあるインストールできるNode.jsの一覧表示
$ nodebrew ls-remote

// 安定版をローカル(自分のMac)にインストール
$ nodebrew install stable

// ローカルにインストールされている`Node.js`のバージョンを一覧表示
$ nodebrew ls

// インストールしたバージョンの`Node.js`を選択する
$ nodebrew use 使用したいバージョン番号
```

### 4. `Node.js`のパスを通す

```bash
// "~/.bash_profile"にパスを追記する(bashの場合)
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile

// ターミナルを再起動して反映
// または以下を実行して反映
$ source ~/.bash_profile
```

### 5. `node`と`npm`が使用可能か確認
Node.jsをインストールした時点でnpm(node package manager)もインストールされているので、うまくいっていればこの時点で使用可能になっているはずです。

```bash
// Node.js
$ node -v

// npm
$ npm -v
```
これで準備は整いました。

## `create-react-app`で`React`の環境構築
任意の場所で以下のコマンドを叩いてください。
`npx`コマンドを簡潔に説明すると、パッケージをローカルにインストールすることなく実行できるコマンドです。
環境を汚染しないので手軽に実行して見たいときに便利です。
詳細は[こちら](https://qiita.com/tonkotsuboy_com/items/8227f5993769c3df533d#:~:text=npm%E3%81%A8%E3%81%AFNode.js,%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82)。

```bash
$npx create-react-app プロジェクト名
```
これでカレントディレクトリにreactのプロジェクトが作成されました。
以下のコマンドでブラウザ表示します。

```bash
$ npm start
```
![スクリーンショット 2020-06-25 15.21.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250675/c90ce74a-292e-0efc-f261-bbe5adca7c9d.png)

お疲れ様でした。
Self LanguageのMorphic環境を構築する

# 手動で構築する
## 参照ドキュメント
### Getting Started
https://handbook.selflanguage.org/2017.1/gettingstarted.html

### How to build the world
https://handbook.selflanguage.org/2017.1/buildworld.html

## 手順
1. Selfをインストールする
    - Getting Startedを参照して、実行マシンに応じた方法でインストール
    - この時点で `Self` コマンドが有効になる
2. githubからSelfのソースコードをcloneする
    - How to build the world参照
    - `git clone https://github.com/russellallen/self.git .` (2020/06/25時点)
    - ここでは `/home/user/self/repository` にcloneしたものとする
3. GUI付きでSelf環境を構築する（＝ *reconstruct a world*）

    ```
    Self -f /home/user/self/repository/objects/worldBuilder.self \
      -b /home/user/self/repository/objects \
      -o -morphic,ui1
    ```

4. 完了するとSelfのREPLが立ち上がるので、デスクトップアプリケーションを起動
    - `desktop open`

# 手動で構築しない（Macの場合）
インストールしたときに同梱されているスナップショットを使えばOK.
`Self Control -> Choose snapshot -> morphic.snap`

![スクリーンショット 2020-06-25 15.25.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65937/72cb9709-91f8-0219-5de2-a94949941399.png)
vis.jsを利用し相関図を作成してみた

# 初めに
相関図を作成する機会があり簡単に描画できるライブラリはないかと探した所、
vis.js の [vis-network](https://github.com/visjs/vis-network) が良さそうでした。
サンプルを参考に自分の好きな飲み屋 [徳田酒店](https://tokuda-shouten.co.jp/food/index.html#wc_anc00001) の店舗と利用頻度を描画してみます。

# ソースコード
```tokuda.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>test</title>
    <script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
    <style type="text/css">
        #mynetwork {
            width: 600px;
            height: 400px;
            border: 1px solid lightgray;
        }
    </style>
</head>
<body>
<div id="mynetwork"></div>
<script>
    // create an array with nodes
    const nodes = new vis.DataSet([
        {id:1 , label: '徳田酒店', shape: 'box', color:'#C2FABC'},
        {id:'1-1',  label:'京橋本店', size:25},
        {id:'1-2',  label:'片町店', size:25},
        {id:'1-3',  label:'プロムナード店', size:10},
        {id:'1-4',  label:'西梅田店', size:15},
        {id:'1-5',  label:'御肉', size:20},
        {id:'1-6',  label:'第3ビルB1店', size:30},
        {id:'1-7',  label:'第3ビルB2店', size:20},
        {id:'1-8',  label:'第4ビルB2店', size:5},
        {id:'1-9',  label:'瓦町店', size:15},
        {id:'1-10', label:'ルクア大阪店', size:5},
        {id:'1-11', label:'京阪高架下店', size:5},
        {id:'1-12', label:'ホワイティうめだ店', size:5},
    ]);

    // create an array with edges
    var edges = new vis.DataSet([
        {from: 1, to: '1-1' },
        {from: 1, to: '1-2' },
        {from: 1, to: '1-3' },
        {from: 1, to: '1-4' },
        {from: 1, to: '1-5' },
        {from: 1, to: '1-6' },
        {from: 1, to: '1-7' },
        {from: 1, to: '1-8' },
        {from: 1, to: '1-9' },
        {from: 1, to: '1-10' },
        {from: 1, to: '1-11' },
        {from: 1, to: '1-12' },
    ]);

    // create a network
    var container = document.getElementById('mynetwork');

    // provide the data in the vis format
    var data = {
        nodes: nodes,
        edges: edges
    };
    var options = {
        nodes: {
            shape: 'dot',
        }
    };
    // initialize your network!
    var network = new vis.Network(container, data, options);
</script>
</body>
</html>
```
# 表示結果
第3ビルB1店の利用頻度が高いことが可視化できました。
![tokuda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590304/3646507f-d7a9-050e-6d52-f3c3c079544e.png)

# 最後に
今回は簡単なものを表現してみましたが大量のノード表示や画像に変更するなども可能です。
どのような表現ができるかは [サンプル](https://visjs.github.io/vis-network/examples/) をご確認下さい。
face_recognition使ってみた（ほぼ構築）

顔認証記事見つけて試してみたら、インストール時点でエラーが出てスムーズに出来なかったのでメモしとく。

Python を利用して顔認証ができる。しかもライブラリは公開されている。
しかも簡単らしい。
　最初に見た記事：　https://www.cresco.co.jp/blog/entry/9468/

※そもそもPython初心者なんだけど、適当に書いても動くので甘く見てる。
※環境はWindows10、Python3.8

ちょうど業務で課題となっているものに顔認証が使えないかなーと思っていたので
「pipでインストールするだけでしょ」ぐらいの軽い気持ちで始めて見た。

~~~
＞pip3 install face_recognition
~~~
インストールでエラー出まくって全然先に進めなかった・・・
読めない英語を見ながらググって進めた

wheelが無いよって怒られた。
なにそれ？python配布用のzipらしい。

~~~
＞pip install -U wheel
~~~

まだまだエラー
dlibがどーとか

そもそも、face_recognitionってのはdlibっていう顔認識ライブラリを使うための物らしい。
python用のラッパーかな？
　参考：https://qiita.com/nonbiri15/items/f95b5fb01ae38980c9ce

dlibのインストールが必要らしい。

~~~
＞pip3 install dlib
~~~
やっぱりエラー出まくり

dlibってCで作られてるらしい
CMAKEってのが要るらしい。
cmake-3.18.0-rc2-win64-x64.msi
　↑　をDLしてインストール

まだまだ～
VC++でビルドするらしい（そりゃそーか）
　参考：https://qiita.com/strv13570/items/a0542600532deee61391
Visualstudio2017は入れてたけどVC++なんて触りたくなかったので入れてなかった。
しょうがないのでVC++使うように変更してインストール

以上、pathなどは適宜設定（確認）

~~~
＞pip3 install dlib
・
・
・
Successfully installed dlib-19.20.0
~~~
やっと、dlib通った。

~~~
pip3 install face_recognition
・
・
・
 Successfully installed Pillow-7.1.2 face-recognition-1.3.0 numpy-1.19.0
~~~
やっとインストールできたか、長い道のりだった・・・
　　ググって思ったのが、なんで、みんなアナコンダとか入れてんだろうか？？業務上か？

とりあえず、サイトを参考に2つのフォルダを作って写真入れて試す。
知ってる顔フォルダ　と　知らない顔　フォルダ　を作ってそれぞれ入れてdiff取る感じの使い方。
それぞれ以下で試した。
 ![face.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/5f50338b-f138-d7d6-988a-291203a268ac.png)

![face2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/4ef769cd-da5a-622c-ac21-c6565f493909.png)
※1枚本物入れて見た。
実行結果
![diff_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/025f1dce-42fa-332b-3a0f-5aa955819ca8.png)
tosi3は騙されてるね。

以上、使用レビューのつもりが、インストールメモに成ってしまった・・・

他もいろいろ試してみたい予定
　参考：https://www.kkaneko.jp/dblab/dlib/facerec.html

追記：
　　　　　↑　のサイト見てまんま試してみた

~~~test_face.py
import face_recognition

src_img = face_recognition.load_image_file("./face/obama.png")
src_img_encoding = face_recognition.face_encodings(src_img)[0]
# print(src_img_encoding)

img1="./face2/tosi.png"
img2="./face2/tosi2.png"
img3="./face2/tosi3.png"

dest_img1 = face_recognition.load_image_file(img1)
dest_img_encoding1 = face_recognition.face_encodings(dest_img1)[0]

dest_img_encoding2 = face_recognition.face_encodings(face_recognition.load_image_file(img2))[0]
dest_img_encoding3 = face_recognition.face_encodings(face_recognition.load_image_file(img3))[0]

results = face_recognition.compare_faces([src_img_encoding], dest_img_encoding1)
print(img1 , results)
results = face_recognition.compare_faces([src_img_encoding], dest_img_encoding2)
print(img2 , results)
results = face_recognition.compare_faces([src_img_encoding], dest_img_encoding3)
print(img3 , results)
~~~

~~~ 実行結果.
＞test_face.py
./face2/tosi.png [False]
./face2/tosi2.png [False]
./face2/tosi3.png [True]

Process finished with exit code 0
~~~

顔の特徴を数値化して比較できる
めっちゃ楽じゃんか！！
vlang vscript のメモ

vlang には, bash のような感じでシェルスクリプトっぽい機能があり, クロスプラットホームで使うのによさそうに見えます
(python とかでもできるあるが, python は環境インストールとか必要でめんどい)

https://github.com/vlang/v/blob/master/doc/docs.md#cross-platform-shell-scripts-in-v

ただ, 仕様はころころ変わっていて, web サイト通りには動きません.

以下は

V 0.1.28 bdecbc1 (2020/06/25)

を想定しています.

`ls` は `os.ls` になり, optional 文を使っています.


https://github.com/vlang/v/blob/master/doc/docs.md#optionresult-types-and-error-handling

したがって以下のように記述します.

```
import os

files := os.ls('build') or {
  return
}

for f in files {
  println(f)
}

```