OmniAICreator/Qiita-1.07M huggingface dataset:
VSCodeでopenFrameworksをやる環境構築



of0.11.0が出ました。
公式でVSCodeをサポートするようになったが、やり方が書いてなかったのでそれをやっていく。

1. projectGeneratorの設定を選ぶ
<img width="612" alt="Screen Shot 2019-12-08 at 14.50.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/a03890b3-8a66-a6dd-8032-42ca0bb5d78e.png">

2. `Advanced options`にチェックをつける
<img width="612" alt="Screen Shot 2019-12-08 at 14.50.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/dfe1aa02-188f-a394-b650-fb1639e20282.png">

3. するとTemplateが選べるようになるので`Visual Studio Code`選択
<img width="612" alt="Screen Shot 2019-12-08 at 14.51.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/e0224580-4fa7-8221-0d17-53f37d2595e0.png">

4. するとVSCodeのワークスペースが作られたプロジェクトが作られるので、ワークスペースをダブルクリック
<img width="1091" alt="Screen Shot 2019-12-08 at 14.51.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/c60dcc9c-d05c-b690-9f0d-d502bc7e098f.png">

5. ひらけた
6. <img width="1136" alt="Screen Shot 2019-12-08 at 14.52.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93474/74dd3a05-75a5-9216-5f51-189540e1e5e2.png">

6. `cmd/ctrl + shit + b`でタスクを選択できるので、`build　Debug`を選択するとビルドできる

7. `make RunDebug`とターミナルで実行すれば、アプリが起動する

## ビルドとアプリの実行を同時に行う

8. ビルドとアプリの実行を毎回別で行うのは面倒臭いので、アプリの実行をタスクにして、アプリの実行の前にビルドを走らせるようにする

`.vscode/tasks.json`に以下を追記。

- `"dependsOn"`で先に実行させたいタスクを選択

```json:.vscode/tasks.json
{
    "type": "shell",
    "label": "Run DEBUG",
    "presentation": {
        "reveal": "always",
        "panel": "shared"
    },
    "command": "make RunDebug",
    "group": {
        "kind": "build",
        "isDefault": true
    },
    "problemMatcher": {
        "owner": "cpp",
        "fileLocation": [
            "relative",
            "${workspaceFolder}"
        ],
        "pattern": {
            "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
            "file": 1,
            "line": 2,
            "column": 3,
            "severity": 4,
            "message": 5
        }
    },
    "dependsOn": [
        "Build DEBUG"
    ]
}
```

これで、憎きXcodeから離脱して快適なoFライフ！！
短縮URLとは

# 短縮URLとは
**長いURLを短くしたもの。**

**長いURL**
`https://ja.wikipedia.org/wiki/%E7%9F%AD%E7%B8%AEURL#%E5%A4%A7%E6%96%87%E5%AD%97%E3%83%BB%E5%B0%8F%E6%96%87%E5%AD%97%E3%81%AE%E5%8C%BA%E5%88%A5%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%A7%E3%81%82%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%8C%E5%A4%9A%E3%81%84`

**短縮URL**
`https://bit.ly/34wPwhT`


# URLが長くなる原因
**基本的にURLとして使える文字は、英数字と一部の記号のみです[^1]。
英数字以外（日本語など）がURLにあると英数字にエンコードをしなければなりません。**
例えば、上記の長いURLは、実際のサイトでは以下の様に表示されています。
```https://ja.wikipedia.org/wiki/短縮URL#大文字・小文字の区別が必要である場合が多い```
この様に日本語はエンコードされてしまう為、URLが見にくくなります。
しかし、短縮URLを使うとスッキリします。


# 仕組み
**短縮URLサービスを提供している運営元が、実際のURLと短縮したURLを、運営元のサーバーに保存しています。**
具体的な流れは図の通りです。
　1. 短縮URLを管理している運営サーバーにリクエストを送る。
　2. サーバーが実際のURLを返す（レスポンス）。
　3. 返ってきたURLにリクエストを送る（リダイレクト）。

<img width="896" alt="スクリーンショット 2019-12-08 2.00.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241219/c229b4fd-cd78-f76c-4b8d-8d69b4b8eaca.png">



# メリット
- 見た目がスッキリする（長すぎるURLで画面が埋まらなくて済む）。
- URLをベタ書きしなければいけない際に、デザイン崩れを防止できる。
- 文字数制限のあるSNSやSMSで便利。
- クリック率が上がる（らしい）[^2]。


# デメリット
- **実際のURLが分からない為、悪質なサイトかどうかの判断がつかない**[（具体例）](#example)。
- リダイレクトする為、表示が遅くなる。
- 短縮URLのサービスが終了すると、その短縮URLはリンク切れになる[^3][^4]。
- 名刺やチラシなどの紙媒体は、サービス終了に伴う短縮URL変更に対応できない。
- サービスが終了しない限り、作った短縮URLは消えない。


# [具体例](#example)
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241219/fe7756ad-3951-7dcb-3957-c736a0357e9f.jpeg" width="30%">
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241219/cee665b3-3a59-942e-d4fa-54866293462c.jpeg" width="30%">


# オススメの短縮URLサービス一覧
これらのサービスはアクセス解析もしてくれる優れものです。
- [Ow.ly](https://hootsuite.com/ja/pages/owly)
- [URX.NU](http://urx2.nu/)
- [Bit.do](http://bit.do/)

また、[Bitly](https://bitly.com/)は世界的に有名ですが、一番悪用されている印象を受けます。短縮URLのデメリットを理解している人だと、[Bitly](https://bitly.com/)である時点でクリックしない可能性がありますので、控えた方がいかもしれません。


# まとめ
確かに、長いURLが送られてくると「うわっ。。。」ってなりますし、クリックしにくいかもしれません。
しかし、先ほど述べた様にデメリットとして、**どんなサイトか分からない** という事があります。
フィッシング詐欺や、ブラウザクラッキング、Coinhiveの様なサイトかもしれません。

**短縮URLは便利ですが、デメリットも理解して使いましょう！！！
Nortonみたいなセキュリティソフトをブラウザにインストールして使うことをお勧めします！！！**

[^1]: https://www.ipentec.com/document/web-url-invalid-char
[^2]: https://www.dreamhive.co.jp/201408/2596
[^3]: ピクシブが提供していた短縮URLサービスが終了し、800万以上の短縮URLがリンク切れになった。 http://p.tl/
[^4]: https://japan.cnet.com/article/35107441/
laravelのviewからvueのcomponentに配列を渡す方法

##laravelのviewからvueのcomponentに配列を渡す方法

laravelのviewからvueのcomponentへ配列を渡し、for文で回して値を取得したかったのですが、なかなか苦戦しweb上にもあまり情報がなかったので下記にてシェアいたします。

ここではコードを書くのみとし詳しい説明は最後にリンク先を貼りますのでそちらを参照いただければ幸いです。

##1.laravelのview側の処理

```layout.blade.php
<div id="app">
　<my-component v-bind:categories="{{ ($categories) }}"></my-component>
</div>

//$categoriesにはCategoryModelから渡ってきた下記のような配列が格納されています。
ここから「type」をvue.template内で取得します
0: {id: 1, type: "ビジネス", update_at: "2019-11-30 10:33:58", created_at: "2019-11-30 10:33:58"}
1: {id: 2, type: "小説", update_at: "2019-11-30 10:33:58", created_at: "2019-11-30 10:33:58"}
2: {id: 3, type: "テクノロジー", update_at: "2019-11-30 10:34:31", created_at: "2019-11-30 10:34:31"}
3: {id: 4, type: "プログラミング", update_at: "2019-12-08 07:53:36", created_at: "2019-12-08 07:53:36"}

```

##2.vueのtemplate側の処理(とりあえずの最小構成)

```MyComponent.Vue
<template> 
  <div>
      <ul v-for="(category,index) of categories" :key="index">
         <li>{{ category.type }}</li>
     </ul>
  </div>
</template>
<script>
    export default {
        props:["categories"],
        mounted () {
        console.log(this.categories)
    　　}
    }
</script>

//注意点
・<template> 直下に[v-for]を書くと下記のようなエラーがでます。
 Cannot use v-for on stateful component root element because it renders multiple elements.
```

##3.laravelのindexページ表示部分(layoutをincludeしています)

「npm run dev」でコンパイルした後、下記のようにMyComponent.Vue内の値が表示されます。
・ビジネス
・小説
・テクノロジー
・プログラミング

##4.最後に

下記サイトを参照しました。(＊サイト内英語です。)
[Passing data from Laravel to Vue](https://medium.com/@m_ramsden/passing-data-from-laravel-to-vue-98b9d2a4bd23)
DB用語メモ

データベースに触れる機会は少ないのですが、
知識としては必要になることが稀にあるので、人と会話できるレベルになるためのDB関連の用語をまとめます。


## マイグレーション
`migration(移行)`のことである。
DBに保存されているデータを保持したまま、テーブルの作成やカラムの変更などを行うこと。


## テーブル 
表全体のこと。

| 顧客ID | 名前 | メールアドレス |
|:------:|:--:|:-----------|
| 1     | 佐藤 | sato@mail |
| 2     | 山田 | yamada@mail | 
| 3     | 田中 | tanaka@mail |


## カラム
`Column(列)`。
つまりテーブルの縦の行のこと。


## レコード
テーブルの横の行のこと。


## スキーマ
何らかの構造のことを指し示す言葉ではあるが、抽象的な言葉のため、
ここで具体的に説明することは不可能。

分野によって定義が異なる。
FontAwesomeの導入

##書かれていること
- FontAwesomeとは？
- Hamlで使う時
1.FontAwesome用のgemをインストールする
2.importする
3.Hamlの記述方法

- Htmlで使う時
1.HTMLファイルに記述

- 参考ページ
- 終わりに
##FontAwesomeとは？
ウェブフォントの一種で、文字を扱うのと同じようにアイコンを表示させることができる
#Hamlで使う時
##1.FontAwesome用のgemをインストールする
```ruby:Gemfile
gem 'font-awesome-sass'
#最下部に追加する
```
- Gemfileに追記したら、```bundle install```してサーバーを再起動

##2.importする
```ruby:application.scss
@import "font-awesome";
```
##3.Hamlの記述方法
```haml:表示したいページ.html.haml
.クラス名
 = fa_icon 'acorn', class: 'icon'
```
- FontAwesomeのページを見て使いたいアイコンを探す

###別の記述

`Gemfile`に記述して`bundle`までは同じ

```ruby:application.scss
@import "font-awesome-sprockets";
@import "font-awesome";
```
```haml:表示したいページ.html.haml
%i.fa.fa-acorn　←これでできてる人もいましたが私はだめでした

#または
= icon('fab', 'twitter')#←右側はFontAwsomeの公式ページをみて表示したいアイコン名を入れてね（この記述は成功！）

= icon('fas', 'image', class: 'icon')#こうするとクラスの指定もできるのでscssが当てられる
```

アイコンカスタム！色を変えたりできる
[Font Awesome 5の使い方とカスタマイズ方法を徹底解説！](https://webdesign-trends.net/entry/8351#i-2)

#HTMLで使う時
##1.HTMLファイルに記述
- head内にリンクを記述
- 任意の場所にアイコンの記述をする

```html:表示したいページ.html.erb
#headの中
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
###中省略
<div class="iconのクラス名">
 <i class="fas fa-acorn"></i>　#ここが丸々、アイコンをさすコード
</div>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540209/c5ea21db-8229-28a9-e075-8b49af66d0c2.png)

##参考ページ
- [FontAwesome](https://fontawesome.com/icons?d=gallery)
- [【保存版】Font Awesomeの使い方：Webアイコンフォントを使おう](https://saruwakakun.com/html-css/basic/font-awesome)

##終わりに
hamlの旧形式とHtmlで記述をしていたのですが
Hamlで新しい書き方があるようで忘備録として書いてみました。
別アプリ実装の時に気づいたことがあれば随時、更新予定です。
間違った記述等ございましたら、ご指摘いただけると幸いです。
CakePHPのソースコードを読んでいたら、知らないメソッドの呼び出し方があった

[Fusic Advent Calendar 2019](https://qiita.com/advent-calendar/2019/fusic) - Qiita 9日目の記事です。

今回はPHPでこんなメソッドの呼び出しあるんだ？としらないことがあったので、そのことについて書いてみました。

## 知らなかった呼び出し方

CakePHPのソースコードを読んでいた時に、ここどうなってんだ？となったのがこの部分になります。
https://github.com/cakephp/cakephp/blob/master/src/Datasource/ModelAwareTrait.php#L127

### $factoryに入ってる値

```php
 /src/Datasource/ModelAwareTrait.php (line 128)
[
	(int) 0 => object(Cake\ORM\Locator\TableLocator) {
		[protected] locations => [
			(int) 0 => 'Model/Table'
		]
		[protected] _config => []
		[protected] _instances => []
		[protected] _fallbacked => []
		[protected] _options => []
	},
	(int) 1 => 'get'
]
```
配列の1つ目に`TableLocatorのインスタンス`、2つめに`getという文字列`が入ってます。

### 呼び出し

```php
$factory($modelClass, $options);
```

こうなってます。`配列(引数1, 引数2)`です。
この部分の配列に対して、メソッド呼び出しみたいなことが出来ることを知りませんでした。
動き的には、 `TableLocator::get`が実行されており、`call_user_func` と同じような動作になってます。

## 調べてみました

ググってみましたが、結構情報が出ません。
というか検索しにくい。。。
`php 配列 メソッド実行` とかでググると `call_user_func` ばかり引っかかって目的に到達できません。。。

以下のURLを見つけたのですが、どうやらPHP5.4からすでに実装されてるみたいです(笑)
知らなったよ。。。
PHP5.4っていうと2011年:joy:

**参考URL**
https://blog.sarabande.jp/post/6303916255
https://wiki.php.net/rfc/indirect-method-call-by-array-var

この記事によると、PHP5.5でベンチをとっており、直接インスタンスからの呼び出しが一番早いみたいですが、`call_user_funcより配列からのメソッド実行の方が速い` ようです。

せっかくPHP7.4が出たので、ベンチを取ってみました

## ベンチ結果

基本的にはPHP5.5のときと変わらないですね。
参考URLでは `call_user_func` と `call_user_func_array`で多少差が出ているようですが、自分の環境ではまったく差が出なかったので省きました。

配列からの呼出しを2種類行ってますが、配列からの実行の場合でも書き方によって性能が出ないようです。

※参考URLより、ループの回数を増やしてます。(メソッド直接呼出しをおおよそ1秒に設定)

|  呼び出し方法  |  秒数  |
| ---- | ---- |
|  メソッド直接呼出し  |  0.99343309402466  |
|  call_user_func  |  4.6852278709412  |
|  配列から呼び出し1  |  4.5191860198975  |
|  配列から呼び出し2  |  2.491909027099  |
|  文字列から呼び出し  |  2.6240780353546  |
- PHPバージョン : PHP7.4.0

### ベンチソースコード

```php
class Example {
    public function hoge()
    {
        return ;
    }
}

$e = new Example();
$start = microtime(true);

for ($i = 0; $i < 30000000; ++$i) {
    // この部分のコードのみを置き換えて計測しています。
    $e->hoge();
}
$end = microtime(true);
```

#### call_user_func

```php
for ($i = 0; $i < 30000000; ++$i) {
    call_user_func([$e, 'hoge']);
}
```

#### 配列から呼び出し1

変数に入れずに直接メソッド実行しています。
この方法だと、`call_user_func`と性能が変わらないです。

```php
for ($i = 0; $i < 30000000; ++$i) {
    [$e, 'hoge']();
}
```

#### 配列から呼び出し2

ループの外で変数に配列を入れてからメソッド実行しています。

```php
$arr = [$e, 'hoge'];

for ($i = 0; $i < 1000000; ++$i) {
    $arr();
}
```

#### 文字列から呼び出し

```php
$methodo = 'hoge';

for ($i = 0; $i < 30000000; ++$i) {
    $e->{$methodo}();
}
```

## まとめ

相当ループを回さないと大きな性能差は出ませんが、速度を気にするのであれば`call_user_func`は使わずに以下がよさそうです。

- メソッドを直接実行
- 配列から実行(必ず変数に入れてから実行)
- 文字列から実行

今回はベンチ取ってないですが、以下のようにstaticなメソッドに関しても配列実行可能です。

```php
class Example {
    public static function fuga()
    {
        return ;
    }
}
$arr = ['Example', 'fuga'];

for ($i = 0; $i < 30000000; ++$i) {
    $arr();
}
```
IBM Cloud ObjectStorageにファイルをアップロードする

## やりたいこと
* multer, ibm-cos-sdk, multer-s3を使用して、multipart/form-dataで受け付けたファイルをIBM CloudのObject Storageにアップロードする。
* 参考：https://github.com/IBM/cos-web-gallery/blob/master/src/controllers/galleryController.js
* 備忘録

## 前提条件
* Node.js...10.16.0
* multer...1.4.2
* multer-s3...2.9.0
* ibm-cos-sdk...1.5.4
* IBM Cloud Object Storage・Bucket作成ずみ

## パッケージのインストール
```
npm install --save multer multer-s3 ibm-cos-sdk
```

### upload.controller.js
```javascript
const multer = require('multer');
const config = require('config');
const aws = require('ibm-cos-sdk');
const multerS3 = require('multer-s3');
const ep = new aws.Endpoint(config.objectStorage.endpoints);
const s3 = new aws.S3({ endpoint: ep, region: 'us-south', apiKeyId: config.objectStorage.apikey });
const bucket = config.objectStorage.iam_apikey_name;

const upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: bucket,
    acl: 'public-read',
    key: function(req, file, cb) {
      cb(null, `${new Date().getTime()}_${file.originalname}`);
    }
  })
});

exports.upload = upload;
```

### config/development.json
```json
"objectStorage": {
    "apikey": "自分のAPI KEY",
    "endpoints": "https://s3.{自分のregionのprefix}.cloud-object-storage.appdomain.cloud",
    "iam_apikey_name": "自分のバケットの名前"
  }
```

### uploader.controller.js
```javascript
const uploadImage = async (req, res, next) => {
  // ファイルのURLはfiles[index].locationに保存される
  const imagePathList = req.files.map((file) => file.location);
  const list = JSON.parse(req.body.list);
  const result = await db.update(); // あとはDBの更新なり行ってください。
  res.json(result);
};

exports.uploadImage = uploadImage;
```

### uploader.route.js
```javascript
const express = require('express');
const { upload } = require('./upload.controller');
const { uploadImage } = require('./uploader.controller');

/* eslint new-cap: 0 */
const router = express.Router();
router.route('/upload')
    // upload.array('photos', 10)で10枚まで同時アップロード可能
    .post(upload.array('photos', 10), updateCarStatusWithImage)

```

### テストコード(mocha+chai+supter test)
```javascript
it('should upload multi image file', async () => {
    const result = await request(app)
        .post(`/upload`)
        .attach('photos', path.join(__dirname, 'images', 'image1.jpg'))
        .attach('photos', path.join(__dirname, 'images', 'image2.jpg'))
        .attach('photos', path.join(__dirname, 'images', 'image3.jpg'))
        .attach('photos', path.join(__dirname, 'images', 'image4.jpg'))
         // req.body.listとして送信したい情報がある場合
         .field('list', JSON.stringify(['one', 'two', 'three']))
         .expect(200);
    should.exist(result.body);
});
```
vscodeでyapfが効かなかった話


## 症状

vscodeでautopep8やblackは効くのにyapfだけ効かない 

## 結論

`~/.config/yapf/style`が空ファイルだった。

適当に書く

```:~/.config/yapf/style
[style]
based_on_style = pep8
spaces_before_comment = 4
```

## 確認
vscodeで`ctrl+shift+p`でコマンドパレットを開きShow logs > window > pythonを確認
`> ~/.local/bin/yapf --diff ~/test.py`みたいになっているので端末で同じのを試す。

```console
$ yapf --diff ~/test.py
// yapf: Unable to find section [style] in ~/.config/yapf/style
```
[style]がないのがエラーの原因なので書き足せば動く
goでyamlを直感的にお手軽に操作できるIF「go-rough-yaml」

## 概要

golangでyamlをラフに扱うパッケージを作りました。

> xshoji/go-rough-yaml： go-rough-yaml provide accessor methods to edit yaml.
> https://github.com/xshoji/go-rough-yaml

背景とかいいから使いっぷり教えてよ！って方は[使い方](#使い方)までどうぞ

## 背景

yamlをgolangで参照、加工しようとした際、お手軽にyamlのデータを扱えるパッケージが存在しないことに気づきました。
ここでいう「お手軽」とは、例えば特定のキーを参照、削除、あるいは書き換えたりするだけの操作を指します。
goでyamlを扱うためには

> go-yaml/yaml： YAML support for the Go language.
> https://github.com/go-yaml/yaml

を使うのが一般的です。yamlの内容を構造体にUnmarshalして利用しますが、構造体を定義するのが面倒です。
このとき構造体を定義せずとも、`map[interface{}]interface{}`という最強の型なしmapにUnmarshalすることで、
ある程度お手軽にyamlのデータを参照、加工できるのですが1点大きな問題があります。それは、

- yamlに戻したときにmap構造のキー順が保証されない（勝手にソートされる）

ということです。

```
bbb:
  c: 1
  b: 2
aaa:
  f: 3
  e: 4
```

というyamlをmapにUnmarshalして、そのままMarshalでyamlに戻すと

```
aaa:
  e: 4
  f: 3
bbb:
  b: 2
  c: 1
```

という感じで勝手にキーでソートされてしまいます。これは嫌です。
なぜなら、見やすいように意図的に整理しているyaml内のデータが勝手にソートされたら困りますし、
加工せずMarshalしたyamlであっても一切変更がないのに差分だらけになります。
この問題に対して、`yaml.MapSlice`という便利な構造体が用意されていて、これは上述の課題を解決するものです。
この構造体を使うことで、map構造の順序を保持したままyamlを加工できます。
が、mapではなくsliceとしてデータを扱うため、mapのキーバリュー構造のように簡単に目的の値にアクセスできません。
また、値の加工もかなり面倒です。

そこで、この`yaml.MapSlice`の特性（map構造の順序を保持する）を活かしつつ、
キーバリュー構造のようにアクセスできるIFを備えたパッケージを用意しました。

> xshoji/go-rough-yaml： go-rough-yaml provide accessor methods to edit yaml.
> https://github.com/xshoji/go-rough-yaml

## 特徴

go-rough-yamlの特徴は以下の3つです。

- シンプルなインターフェース
- スキーマレス
- map構造の順序の保持

以下に使い方と合わせて特徴を詳しく説明します。

## 使い方

1行（yamlは複数行ですが...）でyamlを読み込めます。

```golang
roughYaml := goroughyaml.FromYaml(`
ddd:
  ccc:
    c: value-c
  bbb:
  - 10
aaa:
  zzz: value-zzz
`)
```

入れ子構造の値の有無を意識せず、メソッドチェーンで目的の値を参照、更新できます。

```golang
// get value
roughYaml.
Get("ddd").
  Get("ccc").
    Get("c").Value() // => value-c
roughYaml.
Get("xxx").
  Get("xxx").Value() // => nil

// set value
roughYaml.
  Get("aaa").
    Set("zzz", nil)
roughYaml.
  Get("aaa").
    Get("zzz").Value()) // -> nil

// delete key
roughYaml.Delete("aaa")
roughYaml.Get("aaa").Value()) // -> nil
```

このように、メソッドチェーンでゆるくyamlを扱えます。つまり、構造体の定義が不要（＝スキーマレス）です。
yamlへ戻す場合も1行で済みます。かつ、map構造の順序が保持されます。

```golang
// print as yaml
/**
ddd:
  ccc:
    c: value-c
  bbb:
  - 10
 */
roughYaml.ToYaml()
```

## まとめ

go-rough-yamlの実装にあたって、以下の3点についての理解が浅かったため、苦労しました。

- ポインタ
- interface{}
- nil

golangであるあるなトピックなので今更、という感じですが、今回実際に苦しめられてかなり学びがありました。
特に`interface{}`と`nil`の話は、過去に他の方がよくまとめてくれていたのでそれらの情報にとても助けられました。先人の知識はとても大切です。
基本的な操作しか実装、テストしていないので、バグや必要な機能がもしあればIssueでご連絡いただければ対応します。
golangでyamlをゆるく取り扱い方に少しでも貢献できていたら嬉しいです。もしかしたらjson版も作るかもです。
Vim本体だけでHTTP通信してみた話

こんにちわ、ゴリラです。

Vimを使っているみなさんは、`channel`機能はご存知でしょうか？
`channel`を使用することで、他のプロセスと通信することができます。通信は`TCP/IP`プロトコルで行われます。

本記事は`channel`機能を使って、HTTP通信をしてみた記事になります。（HTTPについては解説しません）
`curl`といった外部コマンドに頼らなくても簡易なGETなら、Vim本体だけで行うことができます。

では、早速解説していきます。

## デモ
こんな感じです。
![http.vim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/652b7466-ca53-cf67-a3df-8c4e3cbce24f.gif)

## チャネルについて
`channel`は`RAW`、`NL`、`JSON`、`JS`といった通信フォーマットがあります。
`JSON`なら送信したメッセージがJSONに変換されます。例えば`hello gorilla`を送信した場合、`[1, "hello gorilla"]`に整形され送信できます。
`RAW`ならテキストがそのまま送信することができます。HTTPの実態はプレーンテキストなので、今回は`RAW`を使用します。
詳細は`:h channel`を参照してください。

## チャネルを開く
`ch_open`関数を使用します。
`let channel = ch_open("localhost:80", {"mode": "raw"})`だけで接続できます。
`echo ch_status(channel)`でチャネルの状態を確認できます。`open`は接続中、`close`は接続終了を指します。

## リクエストを送信
チャネルに対して送信するには`ch_sendraw()`関数を使用します。これはテキストをそのまま送信する関数になります。
レスポンスはコールバック関数を使用することで受け取ることができます。

HTTPのGETリクエストをチャネルで送信処理は次になります。

```vim
func! MyHandler(channel, msg) abort
    new RESPONSE | set buftype=nofile
    call setline(".", a:msg->split("\r\n"))
    nnoremap <buffer> <silent> q :bw!<CR>
endfunc

let s:get_request = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"

call ch_sendraw(channel, s:get_request, {'callback': "MyHandler"})
```

`ch_sendraw`の第2引数は送信したいテキスト、第3引数はコールバック関数`MyHandler`を設定します。
`MyHandler`では新たなバッファを作成して、受け取ったレスポンスをバッファに書き込んでいます。

## Dockerのコンテナ一覧を取得
このやり方をちょっとだけ応用して、Dockerのコンテナ一覧を取得することもできます。
`ch_open`でDockerのサーバーを指定して`s:get_request`を`GET /containers/json?all=1 HTTP/1.1`変えるだけです。

![http-vim-container.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/724f626a-f028-9148-441f-439346d5db3a.gif)

Macの場合は`socat TCP-LISTEN:80,reuseaddr,fork UNIX-CONNECT:/var/run/docker.sock`という感じでソケット通信をTCPに変換してからやってみてください。

## まとめ
以上、とても簡単ですがVim本体だけでHTTP通信をしてみました。
興味あるかたはぜひ試してみてください。

サンプルコードは[こちら](https://github.com/skanehira/http.vim)に置いてあります。
主キーはコンボボックス内の必要カラム

コンボボックスをウィザードで作成した際、中でtanton_Cのカラムだけ呼び出したいと
tantou_Cのみを使用する設定にして作成完了すると、値集合ソースの中はこうなっている。

SELECT [T_sample].[ID], [T_sample].[tantou_C] FROM T_sample; 
[ID]は主キーである。

[ID]は要らないし、おまけにコンボボックスをプルダウンさせるとIDのみ出力される。
プロパティの連結列を1→2に変えてみると、きちんとtantou_Cが出力されるが…

ならば連結列は1のままで、[T_sample].[ID]を消してしまってはどうか。
結果…プルダウンの中身が空白となった。

どうやら値集合ソースのSELECT文内の主キーは使わなくても外せないようだ。

以上
Vue.jsでScssをつかう

##Vue.jsでScssを使いたい
src/assets配下にscssフォルダを作成
<img width="319" alt="スクリーンショット 2019-12-01 15.27.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447438/8e30e09c-6683-116b-3adb-57533e1df2c3.png">

common.scssの中身はこんな感じ

```scss:common.scss
// vender
@import "vender/normalize";

// foundation
@import "foundation/variables";
@import "foundation/functions";
@import "foundation/mixins";

// components
@import "object/_main";
```
```scss:_main.scss
p {
  color: blue;
}
```

下記コマンドでcssが生成される

```
npm run build
```

### 生成されたcssを読み込むには
プロジェクト配下にvue.config.jsを作成

```javascript:vue.config.js

const isProduction = process.env.NODE_ENV === "production";
module.exports = {
  chainWebpack: config => {
    config.module.rules.delete("eslint");
  },
  css: {
    loaderOptions: {
      scss: {
        prependData: `@import "~@/assets/scss/common.scss";`
      }
    }
  },
  productionSourceMap: !isProduction
};

```

import-resolver.jsも設置

```javascript:import-resolver.js
System.config({
  paths: {
    '@/*': 'src/*',
  },
});
```

### 確認する
css生成して

```
npm run build
```
立ち上げる

```
npm run serve
```

### 結果
反映されました
<img width="330" alt="スクリーンショット 2019-12-01 16.02.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447438/e90e430a-1477-be40-a659-6a6c0e5e2b3c.png">
Gatsby.jsでWordPressのAPIをGraphQLで取得しるときによく使うquery

gatsby.jsのplugin「gatsby-source-wordpress」でWordPressが提供しているRestAPIをGraphQLで取得できるようになります。
そのよく使うqueryについてまとめました

※Headless CMS(WordPress)とGatsby.jsでサイト制作するの備忘録については別の記事としてまとめています。「[Headless CMS(WordPress)とGatsby.jsでサイト制作する際の備忘録](https://qiita.com/macotok/items/501e581ff826c6755ab7)」

## GraphQLで取得したdataをcomponentのprops展開する方法

```javascript
import React from 'react';
import { graphql, StaticQuery } from 'gatsby';

const Hoge = () => (
  <>
    <StaticQuery query={graphql`
      {
        allWordpressPage{
          edges{
            node{
              id
              title
              content
            }
          }
        }
      }
    `} render={props => (
      <>
        {props.allWordpressPage.edges.map(page => (
          <div key={page.node.id}>
            <h1>{page.node.title}</h1>
            <div dangerouslySetInnerHTML={{ __html: page.node.content }} />
          </div>
        ))}
      </>
    )} />
  </>
);

export default Hoge;
```

### 投稿ページ

```
{
  allWordpressPost{
    edges{
      node{
        wordpress_id
        title
        content
        excerpt
        date(formatString: "YYYY/MM/DD hh:mm")
      }
    }
  }
}
```

### 固定ページ

```
{
  allWordpressPage {
    edges {
      node {
        id
        slug
        status
        template
        title
        content
        template
      }
    }
  }
}
```

### メニュー

```
{
  allWordpressWpApiMenusMenusItems(filter: {
    name: {
      eq: "Main menu"
    }
  }){
    edges{
      node{
        items{
          title
          object_slug
        }
      }
    }
  }
}
```

### サイトタイトルとディスクリプション

```
{
  allWordpressSiteMetadata{
    edges{
      node{
        name
        description
      }
    }
  }
}
```

### カスタム投稿タイプ「portfolio」

```
{
  allWordpressWpPortfolio{
    edges{
      node{
        id
        title
        slug
        excerpt
        content
        featured_media{
          source_url
        }
      }
    }
  }
}
```

### Advanced Custom Fieldsのdataを取得

- WordPressのプラグイン「Advanced Custom Fields」「ACF to REST API」をinstall

```
{
  allWordpressWpPortfolio{
    edges{
      node{
        title
        acf {
          portfolio_url
        }
      }
    }
  }
}
```
🉐学生なら使うべし! 学生エンジニアの為のアカデミックライセンスまとめ

大手キャリアの学割やAmazonPrimeStudent...様々な『学生割引』があります。
学生の皆さんなら最大限使っていきたいですよね！
本記事では、学生エンジニアなら登録しておいて損はないアカデミック（student）ライセンスをまとめてみました。
他にこれ便利ーというものがあればコメントお願いしますm(_ _)m

### アカデミックライセンスとは
教育・研究機関向けに提供されている、無償若くは割引のあるライセンスです。学生個人で取れるものから、大学や研究機関といった大枠でのライセンスの2種類があります。後者については規約等で個人取得が制限されてたりもしますのでここでは触れません。
要は、**学生だからお手頃に使えるよ！**です。

# アカデミックライセンスを提供している主なサービス一覧

### バージョン管理
- [GitHub](https://github.com/)
    - [Student Developer Pack](https://education.github.com/students)
        - [取得のヘルプ](https://help.github.com/ja/github/teaching-and-learning-with-github-education/applying-for-a-student-developer-pack)

- [Bitbucket](https://bitbucket.org)
    - [Bitbucket Education](https://bitbucket.org/product/education)

### クラウドサービス

- [Haroku](https://jp.heroku.com)
    - 要Github Student ([Heroku for GitHub Students](https://jp.heroku.com/github-students) )
       
- [Amazon Web Service (AWS)](https://aws.amazon.com/jp/)
    - [AWS Educate](https://aws.amazon.com/jp/education/awseducate/)

- [Microsoft Azure](https://azure.microsoft.com/ja-jp/)
    - [Microsoft Azure for Students Starter ($100クレジット取得)](https://azure.microsoft.com/ja-jp/free/students/)
    - [Microsoft Azure for Students Starter プランの有効化](https://azure.microsoft.com/ja-jp/offers/ms-azr-0144p/)

### 開発ツール

- [JetBrains](https://www.jetbrains.com)
    - [JetBrains Student Pack](https://blog.jetbrains.com/jp/2019/08/22/2105)

- [Atlassian](https://www.atlassian.com/ja)
    - [Atlassian Classroom License](https://www.atlassian.com/survey/classroom-license-request)

### 情報共有サービス

- [esa.io](https://esa.io)
    - [アカデミックプラン](https://docs.esa.io/posts/129)

### おまけ
無料でGoogle Drive とか使い放題になるが、申請は団体限定。

- [G Suite](https://gsuite.google.com/intl/ja/)
    - [G Suite for Education](https://edu.google.com/intl/ja/products/gsuite-for-education/?modal_active=none)

送料無料になったりする

- [楽天市場の学割](https://young.rakuten.co.jp/promotion)

言わずもがなAmazonプライム

- [Amazon PrimeStudent](https://www.amazon.co.jp/amazonprime)

# 取得方法
各サービスのアカデミックライセンス申請ページから申し込みを行います。
大抵、学校から付与されているメールアドレス(*~ac.jp*)を使えば、在籍の証明として扱ってもらえます。

学校のアドレスがなかったり、ac.jpのアドレスでの申請がリジェクトされたりする場合は、**英文の在学証明証**を送りつけてやりましょう。私はGithub登録時に英文在学証明を送りつけました（色々あったようで）
SPA（Gatsby）を使い、Google OptimizeでA/Bテストをする方法

# 概要
SPAはネイティブアプリと遜色ない体験設計が出来ますが、非同期通信の特性上[Google Optimize](https://marketingplatform.google.com/intl/ja/about/optimize/)でA/Bテストをするには、特殊なやり方が必要になります。
やり方さえわかれば簡単なのですが、日本語でまとめられたドキュメントがなかったので、自分で作ることにしました。
GTM（Google Tag Manager）を使ってOptimizeを配信するやり方は、[Google公式から非推奨となっているので](https://support.google.com/optimize/answer/6314801?hl=ja)、直接コードを埋め込みます。



# Gatsbyをインストールする
```terminal
npm install -g gatsby-cli
```



# Gatsbyでサイトを作る

```terminal
gatsby new [site name] https://github.com/gatsbyjs/gatsby-starter-default
```



# Google Optimizeの準備をする
[オプティマイズスニペット](https://support.google.com/optimize/answer/6262084?hl=ja#get-optimize)と、~~[アンチフリッカースニペット](https://support.google.com/optimize/answer/7100284?hl=ja)~~を、```gatsby-ssr.js```に記載して、Google Optimizeを使う準備をします。
Gatsbyならプラグインがありますが、Optimizeから警告が出たので、直接コードを埋め込みます。

```javascript
import React from 'react';

export const onRenderBody = ({ setHeadComponents }) => {
 if (process.env.NODE_ENV === `production`) {
   setHeadComponents([
     // オプティマイズスニペット
     <script async src="https://www.googletagmanager.com/gtag/js?id=UA-........."></script>,
     <script
       dangerouslySetInnerHTML={{
         __html: `
         window.dataLayer = window.dataLayer || [];
         function gtag(){dataLayer.push(arguments);}
         gtag('js', new Date());
         gtag('config', 'UA-.........', { 'optimize_id': 'GTM-.........'});
         `
       }}
     />
   ])
 }
}
```

### 追記（2019/12/8）
後述のカスタムイベントのタイミングでテストを開始する場合、アンチフリッカースニペットは必要ないみたいです。
Optimizeのインストール診断をすると、アンチフリッカースニペットを埋め込む様推奨されますが、特に問題はありません。
<img width="1075" alt="アンチフリッカースニペット.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244212/9d346f01-23bc-c3cd-8884-3da4c5786d02.png">
# テストの有効化のタイミングを変更する
SPAの場合、デフォルトの設定であるページ読み込み時のままテストを行うと、**ページ読み込み時に一瞬テスト結果が反映され、その後JSでテスト結果が上書きされてしまいます。**
そうなると、Optimize上では50/50ですが、**実際はオリジナルのデザインの描画が増えます。上書きされた場合でも、変更したBパターンとして記録される**ので、数値に誤差が出ます。
また、SPAは読み込みが発生しないので、**ページ読み込み時のままの設定だと、遷移した際テスト結果が反映されません。**
それでは困るので、有効化のタイミングを[カスタムイベント発火後](https://support.google.com/optimize/answer/7008840?hl=ja)に設定します。



# カスタムイベントを埋め込む

```javascript
dataLayer.push({'event': 'optimize.activate'});
```

上記のコードを、テストを行いたいページに埋め込みます。

```javascript
import React, { useEffect } from "react";

const IndexPage = ({ location }) => {
   useEffect(() => {
     window.dataLayer = window.dataLayer || [];
     window.dataLayer.push({'event': 'optimize.activate'});
   }, [location.pathname])
   return (
     <div>...</div>
   )
}
export default IndexPage;
```



# Google Optimize側の設定
エクスペリエンスを作成したら、テストの有効化のタイミングを```optimize.active```にします。
<img width="3200" alt="アクティベーションイベント.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244212/c9421d65-64b6-1845-24df-3ed5ee34722e.png">



# デバックする
パターンを追加したら、正常に動作するかデバックします。
<img width="3200" alt="デバック.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244212/2aba89dc-dd0b-d1c5-09df-d6be1f73c006.png">
エラーが出なければ完了です。
<img width="3200" alt="デバック結果.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244212/25eb3cb6-7806-63c7-468a-2c90161194bb.png">
Ubuntu 16.04 に サポートされていない古いJDKを入れる プロキシ環境未対応

# 目的

- Ubuntu16.04には現在JDK8かJDK9の二つがサポートされているが、古いバージョンのJDKを入れる方法をまとめる
- 今回は例としてJDK7を導入する。

# 実施概要

1. PPAリポジトリよりJDK7用のリストを取得
1. インストール可能なパッケージの一覧を取得
1. JDK7の本体を取得
1. JDKのバージョン切り替え
1. バージョンの確認

# 実施詳細

1. PPAリポジトリよりJDK7用のリストを取得
    1. 下記コマンドを実行してJDK7をインストールするリストを取得する。

        ```terminal
        $ sudo add-apt-repository ppa:openjdk-r/ppa
        ・
        ・
        ・
        >Reading package lists... Done
        ```

1. インストール可能なパッケージの一覧を取得
    1. 下記コマンドを実行してインストール可能パッケージ一覧を取得する。
    
        ```terminal
        $ sudo apt-get update
        ・
        ・
        ・
        >Reading package lists... Done
        ```

1. JDK7の本体を取得
    1. 下記コマンドを実行してJDKの本体を取得する。

        ```terminal
        $ sudo apt-get install openjdk-7-jdk
        ```

1. バージョンの切り替え
    1. 複数のJDKバージョンをインストールしているときはJDKのバージョン切り替えを行う(下記の出力があったら、チェンジしたいJDKのバージョンの行の最初に記載されている数字を入力してEnter、今回はJDK7にしたいため1を入力後Enter)

        ```terminal
        $ sudo update-alternatives --config java
        >There are 2 choices for the alternative java (providing /usr/bin/java).
        >Selection    Path                                            Priority   Status
        >------------------------------------------------------------
        >* 0            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      auto mode
        >1            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      manual mode
        >2            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      manual mode
        >Press <enter> to keep the current choice[*], or type selection number: 
        ```
1. バージョンの確認
    1. 下記コマンドを実行してJDKのバージョンを確認する。(下記の様になっていればOK)

        ```terminal
        $ java -version
        >java version "1.7.0_95"
        >OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-3)
        >OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode)
        ```
#Nutanix で実現するハイブリッドクラウドな世界～その１

**本記事は[Nutanix Advent Calendar 2019 #2](https://adventar.org/calendars/4014) 12/8 分の記事です。**

今年のAdvent Calenderは４枚もあるというなかなかハードな状態ですけれども、
まだみんな生きてますね。

今回はハイブリッドクラウドなお話です。
まだ正式リリースでない情報も含むため、
非公式な情報という位置づけでお読みくださいませ～。

# Nutanixでハイブリッドクラウドお話なんてあったっけ？
大事なことなんで最初にお伝えしておきますが、
Nutanixの変わらないビジョンとして、
ITインフラを意識させない世界を作るということがあります。

ストレージを仮想化するところから始め、
今ではクラウドまでもを対象とした、
ITインフラ全体をその範疇にいれたビジョンを示しています。

つまり、オンプレミスな環境だけでなく、
ハイブリッドクラウド・マルチクラウドも
実現していく世界のうち、ということになります。


# ハイブリッドクラウド・マルチクラウドの言葉を整理しておく
ハイブリッドクラウドとマルチクラウドは言葉として使い分けています。
世の中的には色々定義があるかもしれませんが、
ここでは以下の通り定義します。

ハイブリッドクラウドは顧客が手元に持つプライベートクラウドと
サービス事業者が展開する共用型のクラウドの双方を接続し、
利用できる状態を指しています。

一方のマルチクラウドは、
サービス事業者が展開する共用型のクラウドを複数組み合わせて利用している状態です。
この時プライベートクラウドを含めるかは微妙な議論ですが、
個人的には含めてよいと思っています。


# 具体的なNutanixが実現するハイブリッドクラウドの世界
Nutanixとして、ハイブリッドクラウドを意識した話は、
2015年頃から始まっています。
AWSやAzure、GCPといった記述もそうですが、
独自ブランドとして展開するNutanix Xi Servicesも発表しています。

実際的には、
　１）HCI環境に提供される機能をさらにクラウドにも提供できる形に拡張
　２）IaaS的な部分→AWS、Azure、GCPといったメガクラウドを活用
　３）Xi Servicesで、メガクラウドだけでは実現できないより上位レイヤーの機能を提供
という考え方ですね。

3としては、個人的な言葉でまとめたひと言シリーズで紹介すると、
　・マルチクラウド展開を可能にするDaaS「Xi Frame」
　・マルチクラウドのコストとセキュリティ管理を「Xi Beam」
　・DRを所有から利用へ「Xi Leap」
　・IoTの運用を現実的なものへ「Xi IoT」
というあたりがあります。
それぞれの紹介は、別のブログ等々にお任せしますので、
ここでは割愛します。

一方で、１＆２の要素としてハイブリッドクラウドを実現していこうという
製品開発も行われています。
ここでメインに取り上げる
　**「Nutanix Clusters」**
です。
2019年5月に開催された.NEXTのイベントで開発が発表されました。
※当時の発表名称は「Xi Clusters」でしたが、改称されてくる予定です

本記事執筆時点ではまだリリースされていないのですが、
今後登場してくるハイブリッドクラウドを実現するための
新たな製品となります。

# ハイブリッドクラウドの現状と課題
日本国内でもパブリッククラウドの利用が本格化し始めてきまして、
メディアでも数多くの事例記事を見かけるようになりました。
多くの記事でもハイブリッドクラウドといったキーワードが
掲載されていますが、多くの実態は
「ネットワーク的につながっているだけ」という状態であろうと思われます。
（もちろん全部とは言いません）

これは仕方ない部分もあり、
プライベートクラウド側のテクノロジと
パブリッククラウドで用いられるテクノロジが明確に異なる為、
高度に連携した使い方ができず、
ネットワーク的につながって通信できるという程度に
とどまっている為です。
当然、システムが異なるクラウド間で行き来するということは、
テクノロジの観点で実現できていません。

つまり、現状ではプライベートクラウドと
パブリッククラウドをその特性に応じて、
上手く使い分けるということが現実的に難しいというのが実情です。

# クラウドを上手く使い分ける必要性

使い分ける必要性を企業に提示したのが、
2019年8月のAWSの大規模障害でした。

[関連記事]
https://tech.nikkeibp.co.jp/atcl/nxt/mag/nc/18/020600011/082900038/
https://www.nikkei.com/article/DGXMZO49049320X20C19A8000000/
https://www.nikkei.com/article/DGXMZO50293040X20C19A9910M00/

決してAWSさんを非難するわけではなく、
教訓として、止まらない仕組みはなく、その時にどうリスクヘッジを行って、
事業の継続性を担保するのかを知る機会であったということです。

製造業の方ならより詳しいと思いますが、
サプライチェーン断のリスクを想定して、
複数の調達先を確保しておくというのが常識的に
実施されていることだと思います。
ITの世界も供給されるものを使うので、
全く同じ考え方をすべきであるということです。

今回は障害という形でしたが、
例えば何らかの形で日本での提供が終了したり、
大幅な値上げが発生したり、
データの所有権を変更されてしまったり、
特定のサービスを利用する１本足でいることは、
企業経営において非常に重大なリスクをもたらします。

そういうリスクをしっかりと評価した上で、
何を用い、何を用いないのか、
ベンダーロックインしない必要性を考え、
世の中の流れに単純に流されない必要があるのです。

# ハイブリッドクラウドを実現する"Nutanix Clusters"
Nutanixでは、ハイブリッドクラウドを実現するための製品として、
"Nutanix Clusters"が提供されます。（本記事執筆時点はまだ正式提供前です）

端的に言えば、Nutanix HCIをパブリッククラウド上で展開し、
オンプレミスと同じテクノロジの足回りを持つことで、
プライベートとパブリッククラウドの行き来を
スムーズにすることが可能となります。

スムーズというのは、つまり仮想マシンの変換など、
小難しいことをすることなく、
”そのまま”引っ越して持っていくことができるということです。
これを本格的に活用することで、
本当にプラットフォームとシステムを切り離すことができ、
プラットフォームにロックインされない、
可搬性のあるシステムを実現します。

他にもまだまだメリットがありますが・・・
記事も長くなってきたので、今回はここまで。
「Nutanix Clusters」がどういったものか、
明日の記事でより深堀していきたいと思います。

今回は以上です。
カルーセルを自作する

# 始めに
カルーセルのライブラリといえばslick.jsやSwiperなどがあると思いますが、どちらもオプションが多く、バグにもよくハマっていました。おまけにファイルサイズも大きいので、簡単なことやるだけに入れる必要があるのかなと思うことがありました。
そこでカルーセルを自作してみたのですが、どんな感じで実装したかを記事にまとめてみました。

# 実装方法
## 各項目の表示と位置について
要素の移動はtransformでまとめて移動する方法を取りますが、移動量は可能な限りシンプルになるようにしました。
親要素は`white-space: nowrap`で改行されないようにし、子要素で`display: inline-block`で横に並べていきます。この時marginはつけないようにします。marginをつけずぴったりくっつけることで1つ移動するたびに`translate3d(-100%, 0, 0)`で遷移できるようになります。
スペースを入れたい場合はpaddingを入れて、その中で新たに要素を入れることで実現しています。
※一番上の親要素はあえてblockのままにすると項目一つ分のサイズにできるので中央ぞろえがやりやすくなります。
※translateXでなくtranslate3dにしている理由はGPUレンダリングにさせるためです

![43d38bcc-78da-4dc6-8eea-4660442b2810.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/0ae89f17-04a3-b2b5-dadc-6e9e7ac998d6.jpeg)

## スワイプ中の処理
上の方法で各項目の場所に移動するのはできるようになりました。
次にスワイプの処理ですが、これは単純に開始位置と移動中の位置を取得して、その差分だけずらしてあげればいいです。
上の説明と合わせると%とpxの指定になりますが、`transform: translate3d(-100%, 0, 0) translate3d(-30px, 0, 0)`のように重ねてtranslateできます。
後は離したときにその差分に応じて前か後ろに移動したらOKです。
注意として、話した後の移動はCSSアニメーションでいいですが、スワイプ中の移動でそれがあるともたついているように見えるので、スワイプ中はCSSアニメーションはOFFにする必要があります。

図ではマウスを例にしていますが、タッチの場合も同じことをすればいいです。
![89915560-9ead-45ab-9f67-59257840df72.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/7e7890a3-1930-bcc3-211a-d04b0cf3354a.jpeg)

# 無限カルーセルの実装
以上が通常のカルーセルの実装でしたが、無限カルーセルをする場合はどうするかについても紹介したいと思います。

まず表示は前後にコピーの要素を配置します。これで初期位置でも前に最後の要素が見えるようになります。
次に遷移先の場所の調整ですが、通常のカルーセルでは0～要素数になるようにスワイプを終えたときに調整してましたが、無限スクロールではアニメーション中まではその調整は行わないようにします。なのでアニメーション中はコピー要素が中心に来るときもあります。
このまま進めたらいつかコピー要素もない場所まで移動できてしまうので、アニメーションが終わったタイミングで一気に逆サイドの本体要素の場所まで移動します。この移動はアニメーションをOFFにしていると気づかないので問題ないです。

![325b7c92-407b-40fd-939c-ad2c700584db.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/28b86f86-abc6-34b5-f845-d86f3987d64d.jpeg)
![db1c3535-925f-4d4b-a9e6-5573dc56550a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/c7dc472e-fa53-e34b-16e4-dba9179fb08a.jpeg)

# 終わりに
以上がカルーセルを実装する方法でした。コードを書こうとすると結構ごちゃごちゃして分かりづらかったのであえて図だけで説明しました。
詳しい実装はCodePenに書きましたので、そちらを見ていただけると幸いです。

<p class="codepen" data-height="636" data-theme-id="default" data-default-tab="js,result" data-user="wintyo" data-slug-hash="MWYaxgz" style="height: 636px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="カルーセル">
  <span>See the Pen <a href="https://codepen.io/wintyo/pen/MWYaxgz">
  カルーセル</a> by wintyo (<a href="https://codepen.io/wintyo">@wintyo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
Python で`pause`の代わりになるもの

# 備忘

Python で C 言語でいう`System('pause');`に値するコマンド，つまり，入力待ち状態を作るためには，

```python
input()
```

と書けばよい．

これで，ループ内で1反復ずつ状態を確認しながらプログラムを実行することができる．
Automation Anywhere Enterprise (v11)のKeystrokesコマンドの挙動を検証してみた

#はじめに
Keystrokesコマンドの挙動を少し検証してみました。
こちらのコマンド、公式のドキュメントではDelayについては、「デフォルト値は0です。」としか書かれていません。
実際、最後の一文字の後に遅延は入るのかなど、謎が多かったので、挙動を可視化してみることにしました。

#試した環境
Automation Anywhere Community Edition ver 11
LabVIEW 2019 Base Package

#実験してみる
確かめたかったのは、コマンド内で設定できるDelayがどう働くのかと、どれくらいの精度でタイミングよく打ってくれるか。
また、コマンド間で遅延は発生するのか。など。
こんなようなBotを作成して、検証用のツールのユーザーインターフェースに文字を入力させます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/21a39be3-c213-12c3-818f-771ea959485a.png)
テスト用のツールはこんなようなものを用意しました。
LabVIEWという計測制御用の開発ツールで作りました。(2020年以降にCommunity Editionが出るみたいです。）
上の白い入力フォームに文字が一文字追加されると、チャートに波形として出てくるようになってます。
最速で1msの周期でアップデートされるように作っています。精度はそれなりです・・・。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/8890689d-3091-8151-82b5-469b6930dbf3.png)

#結果
実際文字を打たせてみた結果が以下の通りです。
チャートの左から、以下のように文字を打った結果が波形として表示されています。
4	Keystrokes: ai in "test.vi" with delay: 1000 ms
5	Keystrokes: aiueo in "test.vi" with delay: 1000 ms
6	Keystrokes: aiue in "test.vi" with delay: 1000 ms
7	Keystrokes: aiueo in "test.vi" with delay: 1000 ms
チャートを見るとわかるのですが、以下の結果が得られました。
・設定したDelayの値は文字数で割られる。（文字列全体を何msかけて入力するか）
・コマンド間は若干遅れが生じる。
・文字入力間のDelayも若干揺らぎがある。（10msくらい？でも実使用上は問題にはならなそう。）
・Insert Keystrokesに記入した各文字の間だけでなく、最後の文字の後ろにもDelayが入る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/1dfb3fcb-5dd3-c12e-5754-bc706728f83e.png)

#確認出来たこと
こんな事して何の意味があるの？と思われるかもしれませんが、
リモートデスクトップ越しのアプリケーション操作や、オブジェクトが取れないアプリケーションの制御の際に、仕方なくInsert Keystrokesを使うケースがありますが、
その際にこういった挙動を知っておくと、より的確にBotを組むことができます。
Insert Keystrokes内で長めにDelayを設定しておけば、直後にわざわざDelayコマンドを入れなくても済む。とか、
長い文字を打つときは文字数x文字間で待たせたいms分のDelayを設定しないといけない。とか。
その辺が確認できました。

####今回判ったInsert KeystrokesのDelayに関する豆知識
- Delay ＝ 入力する文字列全体を何msで入力するか。
- 文字間の遅延時間 ＝ Delay/入力する文字数。
- 最後の文字の後ろにも遅延時間が入る。
firebaseのfunctionでCORSしてるつもりないのにCORS関連で怒られたとき

#CORSしてないつもりなのにCORSエラーを吐く

firebaseのfunction便利ですよね。
クライアントからfunction叩いた時に、CORSしてない（同一プロジェクト内のfunctionを叩いている）のに下記のエラーを吐いてしばらく困りました。


```javascript:console.log
Access to fetch at 'functionのURL' from origin 'hostingのURL' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
```

##結論はただのミス

見出しの通りです。`countUP`というfunctionを呼び出そうとしていたのに`countUp`と書いていたのが原因でした。

```javascript:index.js
✕ const countUP= firebase.functions().httpsCallable('countUp')
〇 const countUP= firebase.functions().httpsCallable('countUP')
```


他にもfunctionの書き方で`onCall`と`onRequest`とかによってCORS関連のエラーを吐く場合があるようなので
firebaseのドキュメントの[アプリから関数を呼び出す](https://firebase.google.com/docs/functions/callable?hl=ja)のページも見てみてください
**しっかりコードを見直しましょう！！(戒め)**
Laravelのmigrateに何度も嵌められる

何度も間違えるんだよ。嵌って泣きそうになるんだよ。
別の記事にも書いたけど、あんまり気づかないので独立して書いちゃうよ。

#Laravelでmigrateすると、怪しいエラーが発生する

新しくプロジェクトを作ってHomesteadも作って、ちゃんとLaravelの初期画面は表示されるのに、php artisan migrateをすると下記のエラーになる。

```console
C:\Users\hoge\code\hege>php artisan migrate


  at C:\Users\hoge\code\hege\vendor\laravel\framework\src\Illuminate\Database\Connection.php:669
    665|         // If an exception occurs when attempting to run a query, we'll format the error
    666|         // message to include the bindings with SQL, which will make this exception a
    667|         // lot more helpful to the developer instead of just the database's errors.
    668|         catch (Exception $e) {
  > 669|             throw new QueryException(
    670|                 $query, $this->prepareBindings($bindings), $e
    671|             );
    672|         }
    673| 

  Exception trace:

      C:\Users\hoge\code\hege\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70

  2   PDO::__construct("mysql:host=127.0.0.1;port=3306;dbname=test", "root", "secret", [])
      C:\Users\hoge\code\hege\vendor\laravel\framework\src\Illuminate\Database\Connectors\Connector.php:70

  Please use the argument -v to see more details.
```

DBの中にテーブルもあるし、ユーザーでDBにアクセスできるし（空だけど）、なぜDBにつながらないかわからない！…のでしたが。
単に、Homesteadでなく、ホストOS側でコマンド入れていたせいでした。
うちの環境はWindows10の中にHomestead(linux)の環境があるので、vagrant sshで仮想サーバーに入って、そこからmigrateコマンドを入れないとDBに接続できないのです。
ホストOSのソースのフォルダ上でmigrate実行→localhostを見に行く→DBなんかないよ、となっていた模様。
Homesteadに入ってからmigrate実行→localhostを見に行く→DBがあるので、そこにmigrateする、ということだ。
二日使ったよ、くそ。
[C#7.2] unsafeステートメントにもマーシャラーにも頼らないで、固定サイズ配列を含む構造体をP/Invokeで受け渡しする方法

## TL;DR

- `StructLayout`属性で`Size`を指定した構造体を用意する。
- それを`ref`と`Span`構造体で読み出す。

## 従来の方法:unsafeステートメントとマーシャラーを使用する場合
P/Invokeで、固定長サイズ配列を含む構造体を受け渡す場合、主に下記の2つの方法を用いると思います。
`GetMonitorInfo`と`MONITORINFO`を例にすると、下記のような定義です。

ネイティブの定義(`UNICODE`ビルド前提で簡略可)

```cpp
#define CCHDEVICENAME 32
struct MONITORINFOEX
{
    DWORD   cbSize;
    RECT    rcMonitor;
    RECT    rcWork;
    DWORD   dwFlags;
    WCHAR   szDevice[CCHDEVICENAME];
};

BOOL WINAPI GetMonitorInfo(
    HMONITOR hMonitor,
    LPMONITORINFO lpmi);
```

### unsafeステートメントの場合

```cs
[StructLayout(LayoutKind.Sequential)]
unsafe struct MONITORINFOEX
{
    public int cbSize;
    public RECT rcMonitor;
    public RECT rcWork;
    public uint dwFlags;
    public fixed char szDevice[32];
};
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
```

この後、`unsafe`コンテキストで`MONITORINFOEX.szDevice`から文字列などにコピーする必要があります。

### マーシャリングする場合

```cs
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct MONITORINFOEX
{
    // ...省略...
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
    public char[] szDevice;
};
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
```
※`MONITORINFOEX.szDevice`は`string/ByValTStr`にしたほうが扱いやすいですが、対比のため`char[]/ByValArray`にしています。

### 問題点
unsafeを使った方がヒープにオブジェクトを作成しない分効率がいいんですが、呼び出し元でもunsafeコンテキストが必要になるので、取り扱いづらいです。
(まぁP/Invokeを使う時点でパフォーマンスを気にしないほうがいいんですが。)

## C#7.2以降で使用できる方法

### `StructLayout`属性で`Size`を指定した構造体を用意する。
ここからが本題です。
昔からですが、`StructLayout`属性には`Size`フィールドがあり、構造体のサイズを設定出来ます。

```cs
[StructLayout(LayoutKind.Sequential, Size = 32 * sizeof(char), CharSet = CharSet.Unicode)]
public struct FixedLengthCharArray32
{
    public char First;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct MONITORINFOEX
{
    // ...省略...
    FixedLengthCharArray32 szDevice;
};
```

ただサイズを設定できるだけで、中身を参照しようとすると`unsafe`ステートメントが必要なので、この構造体を使う意義がありませんでした。

### `ref`と`Span`構造体で読み出す
そこで`ref`と`Span`構造体です。
フィールドの参照から`Span`構造体を構築すれば、後は`ToString`なりインデクサーでアクセス出来ます。
unsafeコンテキストも要らないので扱いやすいです。

```cs
var monitorInfo = new MONITORINFOEX { cbSize = Unsafe.SizeOf<MONITORINFOEX>() };
GetMonitorInfo(hMonitor, ref monitorInfo);
var s = MemoryMarshal.CreateReadOnlySpan(ref monitorInfo.szDevice.First,  Marshal.SizeOf<FixedLengthCharArray32>()).ToString();
```

残念ながら.Net Standard 2.0(.NET Framework)だと`MemoryMarshal.CreateReadOnlySpan`が無いので、相当するメソッドをunsafeコンテキストで実装する(もしくは[ライブラリ](https://github.com/udaken/UnsafeAndSpanExtension)を使用する等の)必要があります。

### 一般化
配列の型とサイズ毎に構造体を用意する必要があり定型コードが多いので、自動生成などをしたほうがいいでしょう。
[T4テンプレート等で作成してみたバージョンはこちら。](https://github.com/udaken/FixedLengthArrays/blob/master/src/FixedLengthArray.tt)
三年前に水没して、タッチパネルが壊れたスマホを直してみた

#三年前に家建ててる時に使っていたNexus5X
大工仕事中にツナギの胸ポケットから落ちて水没。アルコールに浸けてから、一週間ほど良く乾かしたけど、タッチパネルが使えなくて、文鎮となりました。

#修理用のパネルを中華通販で発見
AliExpressの独身の日プロモーションメールでスマホとか眺めていたら、修理用のパネルが売られていることに気づきました。Nexus5x LCDで検索してみると、$10ちょっとでぞろぞろと出てきました。
<img width="802" alt="SnapCrab_19-12-8_16-56-3_00.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/9009232d-df22-610b-8ed3-1a6d53a53627.jpeg">
#一番安いのぽちってみた
この中から、ツール付きで送料込1195円というのをぽちってみました。
<img width="680" alt="SnapCrab_19-12-8_17-6-39_00.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/ad222bb8-163e-1146-3365-3d14f3a27546.jpeg">
#オーダーから26日で到着～
11/12にオーダー、19日に出荷、10日間停滞して、11/30に中国を発ちました。
独身の日セールの大混雑に紛れて遅れたようですね～
<img width="593" alt="SnapCrab_19-12-8_17-15-6_00.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/b8ed38ca-2328-f355-1101-99d87e660603.jpeg">

本日epacket国際書留で、無事到着しました♪
長く旅してきた割には包装はダメージがありませんでした。どこかで山積みされていたのかな～
通関情報はScreensaverとか適当、価格は$9.85とキッチリと書いてある。
LCDパネルは、発泡スチロール箱とプチプチで梱包されていて、ダメージはなさそう。
![nexus1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/c14796a0-ced5-c9b9-7701-96092a8bb55b.jpeg)
#取り掛かる前の準備運動～
取り掛かる前にYouTubeの分解ビデオをじっくり観察します。
[<img width="508" alt="SnapCrab_19-12-8_17-36-24_00.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/c6f0ff67-e439-8b97-7837-874bfb49d045.jpeg">](https://www.youtube.com/watch?v=73K40FeC6ns)

ビデオでは、こじ開け具、ドライバー、ピンセット、ドライヤー、両面テープをつかってました。
おまけのツール以外にピンセットとドライヤーを用意。
パネルの裏には貼付けるテープがついてました。

#作業開始～　
まずは裏蓋をコジコジして開きます。
![KIMG3908.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/f34543bf-f1a5-fb7d-1313-5699f47a3770.jpeg)

次に中蓋のネジを外すのですが、おまけツールにはY字ドライバーが入ってなかったので、手持ちのドライバーを探し出して外しました。
![KIMG3911.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/290ae8d5-d604-7dc5-f647-f4b5000bf142.jpeg)

電池を外しLCDコネクタを外してみると、端子がサビサビでした。少しこすって錆び落としてから組み上げて動作を確認してみたけど、タッチパネルは動作しませんでした。
![KIMG3915.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/3cefb16e-8eac-c7f6-66d0-dc9749581018.jpeg)

もう一度ばらしていきます。基板、スピーカー、LCDコネクタと外して、最後はテープ貼りのパネルをドライヤーで温めながらひっぱがしました。
![KIMG3918.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/00473d18-8c76-0f91-9be1-81067af22e32.jpeg)
![KIMG3921.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/fd92bb5a-e315-e0fe-7ae9-81656bb6eafe.jpeg)
![KIMG3922.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/71404dee-9485-c017-b25f-b399cd7652b0.jpeg)

結構ほこりが溜まっていたので清掃してから、交換用のパネルを取り出して組み上げていきます。
#さて、うまく動作するかな～
電源入れてandroidが立ち上がり、タッチパネルをシュッツとこするとちゃんと動作したわ♪
![KIMG3925.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106489/809508ac-7648-1711-7ff6-db380e3f112a.jpeg)
三年ぶりに復活を遂げたNexus5X、現役復帰でドローンのリモコンとして末永く使っていこうと思います。
#思うに～
中国ではスマホ修理屋さんがゴロゴロしてるので、部品も出回ってるんですね
日本では新しいスマホに安く乗換えていけたのでandroidの修理なんて需要がなかったけど、
総務省の施策で、一括零円とか無くなったので、修理してリユースもこれからは増えてくるような
どんどんたまっていく使用済スマホ　リユースしていかないと、もったいないよね～
県別に路線が多い県を日本地図上で可視化

# 目的
県別に路線が多い県を日本地図上で可視化した際の備忘録です

# コード

```Python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from japanmap import pref_names,pref_code,picture
import matplotlib.pyplot as plt
from pylab import rcParams
import json
import requests

color_map = {}
num = [1]

#rcParams['figure.figsize'] = 8,8
plt.imsave("./picture.jpg", picture({'北海道':'blue','大阪府':(255,0,0),}));

# get the number of prefecture
url = 'http://express.heartrails.com/api/json?method=getPrefectures'
ret = requests.get(url)
ret_json = json.loads(ret.text)
number_of_prefectures=len(ret_json["response"]["prefecture"])
print(number_of_prefectures)

# get max number
for i in range(number_of_prefectures):
    pref_name=pref_names[i+1]
    url = 'http://express.heartrails.com/api/json?method=getLines&prefecture=' + pref_name
    ret = requests.get(url)
    ret_json = json.loads(ret.text)
    num.append( len(ret_json["response"]["line"]) )
max = max( num )
print(max)

# get number of lines in all prefecture
for i in range(number_of_prefectures):
    pref_name=pref_names[i+1]
    url = 'http://express.heartrails.com/api/json?method=getLines&prefecture=' + pref_name
    ret = requests.get(url)
    ret_json = json.loads(ret.text)
    print(i, pref_name, len(ret_json["response"]["line"]), ret_json["response"]["line"][0])
    val = len(ret_json["response"]["line"])
    color_map[pref_name] = (0, val * 255/max, 255)

plt.imsave("./result.jpg", picture(color_map));
```

# テスト


```
$ python sample-map.py
47
88
0 北海道 25 JR函館支線
1 青森県 15 JR五能線
2 岩手県 14 JR八戸線
3 宮城県 15 JR仙山線
4 秋田県 10 JR五能線
5 山形県 9 JR仙山線
6 福島県 13 JR只見線
7 茨城県 14 JR宇都宮線
8 栃木県 15 JR両毛線
9 群馬県 16 JR上越線
10 埼玉県 28 JR京浜東北線
11 千葉県 34 JR久留里線
12 東京都 88 JR中央線
13 神奈川県 38 JR中央本線
14 新潟県 18 JR上越線
15 富山県 17 JR城端線
16 石川県 8 JR七尾線
17 福井県 6 JR北陸本線
18 山梨県 4 JR中央本線
19 長野県 14 JR中央本線
20 岐阜県 15 JR中央本線
21 静岡県 15 JR伊東線
22 愛知県 37 JR中央本線
23 三重県 19 JR参宮線
24 滋賀県 13 JR北陸本線
25 京都府 32 JR京都線
26 大阪府 54 JR京都線
27 兵庫県 40 JR加古川線
28 奈良県 16 JR和歌山線
29 和歌山県 10 JR和歌山線
30 鳥取県 6 JR伯備線
31 島根県 5 JR山口線
32 岡山県 16 JR伯備線
33 広島県 17 JR可部線
34 山口県 9 JR宇部線
35 徳島県 6 JR土讃線
36 香川県 8 JR予讃線
37 愛媛県 12 JR予土線
38 高知県 9 JR予土線
39 福岡県 28 JR久大本線
40 佐賀県 9 JR佐世保線
41 長崎県 11 JR佐世保線
42 熊本県 15 JR三角線
43 大分県 5 JR久大本線
44 宮崎県 5 JR吉都線
45 鹿児島県 12 JR吉都線
46 沖縄県 1 沖縄ゆいレール
```

![result.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344880/09a5d8a8-9b38-8429-2e76-c29e1692e73d.jpeg)


東京都が最も多い。その次に大阪、名古屋、あたりの都市部が多い。

# 参考
[HeartRails Express APIでエリア情報/都道府県情報/路線情報/駅情報/最寄駅情報を取得した際の備忘録（python）](https://qiita.com/seigot/items/ff25ca359b272d82debd)