OmniAICreator/Qiita-1.07M huggingface dataset:
Basic認証パスワードの作り方

# パスワードファイル(.htpasswd)に記載するパスワード
nginxなどのWEBサーバ側で用意するパスワードファイルのパスワード
`openssl passwd -1 "パスワード"`

# リクエスト時に送信するユーザ/パスワード
アプリからBasic認証する場合、Base64でエンコードされたユーザ/パスワードをRequestHeaderに指定する必要がある。

[Advanced REST client](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo)で対象のURLにアクセスするとBasic認証のプロンプトが表示されるので、ユーザ/パスワードを入力する。

Advanced REST clientのHeader valueにBase64エンコードされた文字列が表示されるため、その文字列を送信時にリクエストヘッダに付与するとアプリからBasic認証ができる。
Nuxt.jsで静的ファイル生成時にサイトマップも自動生成する方法

Nuxt.jsでサイトマップを自動生成できなかな～と思ったら方法があった。
npm run generateで静的ウェブサイトを生成した際に、一緒に自動生成が可能。


## 方法
@nuxtjs/sitemapを使用する。
[@nuxtjs/sitemap](https://www.npmjs.com/package/@nuxtjs/sitemap)


## インストール
npm または yarn でパッケージをインストールする。

```shell-session
$ npm install --save @nuxtjs/sitemap
```


## 設定ファイルに@nuxtjs/sitemapを追加
nuxt.config.jsのmodulesオプション内に、@nuxtjs/sitemapを追加

```js:nuxt.config.js
module.exports = {
  modules: [
    ...,
    '@nuxtjs/sitemap'
  ],

  ...
}
```

使用しているモジュールが一つであれば、

```js:nuxt.config.js
module.exports = {
  modules: ['@nuxtjs/sitemap'],

  ...
}
```


## サイトマップに関する設定
nuxt.config.jsに、sitemapオプションを追加する。
この中にサイトマップに関する設定を書く。

```js:nuxt.config.js
const axios = require('axios')

module.exports = {
  modules: ['@nuxtjs/sitemap'],
  
  sitemap: {
    path: '/sitemap.xml',
    hostname: 'https://example.com',
    // generate: true,
    exclude: [
      '/admin'
    ],
    routes (callback) {
      axios.get('https://api.example.com/articles')
      .then((res) => {
        var routes = res.data.map((articles) => {
          return '/articles/' + articles.id
        })
        callback(null, routes)
      })
      .catch(callback)
    }
  },

  ...
}
```


## 各パラメーターについて
### path
生成されるサイトマップファイルの名前。
generateオプションでdirを変更していなければ、distフォルダの中に生成される。

### hostname
サイト名。

### ~~generate~~
~~nuxt generate時に静的なサイトマップファイルを生成するかの設定。~~
~~ここをtrueにしておかないとサイトマップファイルが生成されないので注意。~~

### exclude
サイトマップに含めたくないURLを指定できる。
管理者ページなどがある場合に使用する。

### routes
サイトマップに含めるURLを追加する。
基本的にはgenerateオプションのroutesと同じように記述すればOK
上のコードはAPIから記事の一覧を取得して、記事毎のURLをroutesに追加する例。


## デプロイ
あとはnpm run generateで静的ファイルを生成すると、サイトマップも一緒に生成される。
生成された他のファイルと一緒にサーバーへアップロードすれば完了。


## 追記
パラメーターgenerateはバージョン1.0.0以降不要となったため、打ち消し線を入れ、サンプルコード内をコメントアウトしました。
herokuコマンドのサブコマンドが無くなってしまったら

突然 `heroku` コマンドが使えなくなってしまった。どうやらサブコマンドが全然無くなってしまった様子に見える。

```terminal
 $ heroku help
Refreshing plugins... !
 ▸    semver has no commands. Is this a CLI plugin?
Refreshing plugins... done
Refreshing plugins... !
 ▸    semver has no commands. Is this a CLI plugin?
Refreshing plugins... done
Usage: heroku COMMAND

Help topics, type heroku help TOPIC for more details:

 auth
 plugins  add/remove CLI plugins
```

あれやこれや試したけれどどうしてもうまく修正できず、結局クリーンアンインストールしてから再度インストールした。

https://devcenter.heroku.com/articles/heroku-cli#uninstalling-the-heroku-cli

自分の場合には、複数バージョンの `heroku` を全部アンインストールして、キャッシュなども消す。

```terminal
$ brew uninstall --force heroku
$ rm -rf ~/.local/share/heroku ~/.config/heroku ~/Library/Caches/heroku
```

そして改めてインストール

```terminal
$ brew install heroku
```

ことなきを得た。
You tried to redirect to the same route you're currently on の解決法

react-routerで、**存在しないパスへのアクセスを全て`/dashboard`へリダイレクトしたい**、などのような実装をするときには以下のようなワイルドカード指定を使ったりします

```html:routes.js
  <div id="app">
    <Route path="/dashboard" component={DashboardComponent} />
    <Route path="/login" component={LoginComponent} />
    <Redirect from="*" to="/dashboard" />
  </div>
```

ですが、このままだとreact-routerは`Warning: You tried to redirect to the same route you're currently on: "/dashboard"`というエラーを吐きます。

これは、`/dashboard`というパスもワイルドカードによって認識されてしまい、同じパスへのリダイレクトが二度起こってしまうからです。

これを解決するには、定義されているルーティングを`Switch`を使って囲うだけです。

```diff
    <div id="app">
+     <Switch>
        <Route path="/dashboard" component={DashboardComponent} />
        <Route path="/login" component={LoginComponent} />
        <Redirect from="*" to="/dashboard" />
+     </Switch>
    </div>
```

参考: https://github.com/guyellis/learn/issues/205#issuecomment-334965112
Windows Subsystem for Linux(Ubuntu)にMongoDBをインストール

Windows Subsystem for Linux(Ubuntu)にMongoDBをインストールする方法です。
開発に使うだけならWSLにインストールしても問題なく使えそうです。

#環境
Windows 10 Fall Creators Update（バージョン 1709）
Ubuntu 16.04.3 LTS
MongoDB v3.6.1

#インストール
公式サイトの通りインストールするだけです。
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/

ターミナル(Ubuntu)を開いて次の通りインストールします。

```bash:
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
$ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
$ sudo apt-get update
$ sudo apt-get install -y mongodb-org
$ sudo chmod 777 /var/lib/mongodb
$ sudo chmod 777 /var/log/mongodb
```

#起動
mongodコマンドで直接サーバーを起動します。
プロンプトから抜けてこなければ正常に起動できています。

```bash:
$ mongod --config /etc/mongod.conf
```

別のターミナル(Ubuntu)を開いてmongoコマンドでちゃんとサーバーに接続できるか確認します。
プロンプトが表示されたら正常に接続できています。
プロンプトから抜けるのは「exit」です。

```bash:
$ mongo
MongoDB shell version v3.6.1
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.1
Server has startup warnings:
2018-01-06T17:24:53.031+0900 I CONTROL  [initandlisten]
2018-01-06T17:24:53.031+0900 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-01-06T17:24:53.031+0900 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2018-01-06T17:24:53.031+0900 I CONTROL  [initandlisten]
>
```

#バックグラウンド起動

Windows 10 April 2018 Update バージョン 1803 からバックグラウンドタスクに対応しています。
バックグラウンドで起動してプロンプトを終了しても mongod が終了しなくなりました。

http://ascii.jp/elem/000/001/620/1620316/

```bash:
$ mongod --config /etc/mongod.conf &
$ exit
```

プロンプトを終了しても MongoDB は起動したままです。
コマンドプロンプトのフォントにRictyが使えるようになってた！！

# コマンドプロンプトのフォントにRictyが使えるようになってた！！

恥ずかしながら今更気づいたのでQiitaにメモっておきます。

## やり方
フォントの変更方法は従来と同じ。

1. コマンドプロンプト左上のアイコンを右クリック
2. `右クリックメニュー > 既定値`を選択
3. `フォント`タブを表示し、`フォント`のリストからお好みのフォントを選択。
今まではここに表示されないフォントが沢山あった！！
4. `OK`をクリックし保存
5. コマンドプロンプトを起動し直すとフォントが変わってる

ちなみに、`既定値`で設定変更すると文字通り、既定値となり新たなコマンドプロンプトがそのパラメーターで起動される。
逆に`プロパティ`で設定変更すると表示しているプロンプトの設定のみ変更される。


## PowershellもBash on WindowsでもRicty使えるよ
PowershellのプロンプトでもBash on Windowsのプロンプトでも同じ設定手順でフォントが変えられます。

## Windows の便利なシェル環境を簡単に使い分ける
ここからは私の好みですが、PowershellもBash on Windowsもコマンドプロンプト並に手軽に呼び出したい！
のでショートカットを登録してコマンド一発で各シェルが起動するようにしています。

パスの通ってるディレクトリにショートカット貼れば良いだけですが、
私は`%USERPROFILE%`配下に`ps`と`ubuntu`というショートカットを作ってます。
ここはアクセス制限の厳しい環境でも大抵は書き込めるの便利だからです。

後はファイル名を指定実行から`ps`と`ubuntu`と打てばそれぞれのプロントが起動できます。

## あとがき
今までもレジストリをいじれば可能だったけど色々とめんどくさかったのでコレは嬉しい。
バージョンの付け方

セマンティック バージョニング
書式は、「メジャー.マイナー.パッチ」

- メジャーバージョン
APIの変更に互換性のないバージョンアップ

- マイナーバージョン
後方互換性があり機能性を追加したバージョンアップ

- パッチバージョン
後方互換性を伴うバグ修正をしたバージョンアップ
Vim日本語チートシート作った

先人のvimmer様が作ったチートシートはUS配列の図か、
日本語化されたものでもコマンドの羅列のみの物が多かったので、
JIS配列＋日本語表記のvimチートシート作りました。

#  まずはテンプレート作成
世界一有名であろう[この図](http://www.viemu.com/a_vi_vim_graphical_cheat_sheet_tutorial.html)を元に作成する。
![vi-vim-cheat-sheet.gif](https://qiita-image-store.s3.amazonaws.com/0/131788/f259fbcb-5787-bc15-14e8-419ef14d7e57.gif)

幸いなことにこの図をJIS配列化している[Vimmerの方](http://ma.ruyama.net/vim-のチートシート/)が居たので、
JIS配列化されているものを使用する。
![vim_cheetSheet1-2.gif](https://qiita-image-store.s3.amazonaws.com/0/131788/f6db68ce-5613-2222-e4c5-d893dfe8aa56.gif)


そして英語説明部分を切り取ったものがこちら。
![vimチートシートJIS配列.png](https://qiita-image-store.s3.amazonaws.com/0/131788/2cc3faaf-436d-d858-4978-d05cc324dd84.png)
#  日本語化
まっさらな状態のJIS配列表にキー説明を書き込んでいく。
![記入例.png](https://qiita-image-store.s3.amazonaws.com/0/131788/e381a383-6391-37e0-2372-05f7c8659b27.png)


最後に自分用のメモ書きを書き込んで完成!
![オレオレチートシート.png](https://qiita-image-store.s3.amazonaws.com/0/131788/140445b3-5329-7925-4ba2-0358721a6171.png)

キーマッピングを独自に変えててこのままじゃ使えないよ!という先輩Vimmer様はまっさらな状態の物から自分専用チートシートを作ってください!
(間違っている箇所があればご指摘ください!)
レイヤ化アーキテクチャ


> <a href="http://amzn.to/1mpcTTA">Patterns of Enterprise Application Architecture</a>, Chapter 1 Layering を参考にレイヤ化アーキテクチャとはどういったものなのかをまとめました

　レイヤ化は、複雑なソフトウェアのシステムを分割するために使用される技法です。コンピュータの構造やネットワークなどソフトウェア以外の設計でも使われています。各レイヤはその下のレイヤに依存します。レイヤ３はレイヤ２を利用して、レイヤ２はレイヤ１を利用します。レイヤ化アーキテクチャにおいて最も難しいのは、必要なレイヤと各レイヤが行うべき内容を決定することです。

# レイヤ化のメリット

* 他のレイヤを気にせず、１つのレイヤを全体として考えることができる
* 同じインターフェースを持つだいたい実装でレイヤを置き換えることができる
* レイヤ間の依存を最小限にできる
* レイヤは標準化に適している
* レイヤを構築することにより、多くの高水準サービスがそのレイヤを使用できるようになる

# レイヤ化のデメリット

* 物事をカプセル化してしまうため、連鎖的な変更が起こる場合がある
* パフォーマンスを損ねる場合がある

　UI上で表示すべきフィールドの追加が、前者の具体的な例になります。追加されるフィールドに対応するものがデータベース上に存在する必要があります。このためUIからデータベースまでのすべてのレイヤにそのフィールドを追加する必要が生じます。後者についてはパフォーマンス損失以上にトランザクションの制御などの最適化によって得られる恩恵が多いケースもあるので検討が必要です。

# レイヤ化の発展

　90年代に登場したクライアント/サーバシステムは2レイヤのシステムでした。クライアントはUIとアプリケーションコードを保持して、サーバーは通常のRDBという構成でした。アプリケーションがRDBの内容の表示と更新といった単純なものであれば適切に動作しましたが、妥当性の検証など複雑なドメインロジックを伴い始めると、たちまち重複コードが増えたり、コードの扱いが難しくなったりする局面がでてきました。そのころオブジェクト指向も注目を集めていて、コミュニティではプレゼンテーション、ドメインロジック、データソースの3レイヤにすることにより、ドメインロジックに関する問題を解決しました。最終的にはWebやJavaの登場により、こうしたやり方が受け入れられ、定着することとなりました。

# 3層レイヤ
## プレゼンテーションレイヤ

　ユーザとソフトウェアの相互作用を扱うのがこのレイヤの役割になります。ユーザーに情報を表示したり、ユーザーからのコマンドをドメインやデータソースでの動作に変換したりするようなコードがここに含まれます。

## ドメインレイヤ

　システムそのものであるロジックを置くレイヤです。ビジネスロジックとも呼ばれます。入力データや格納データに基づく計算や、入力データの妥当性検証、また状況に応じたデータソースの選択などがこのレイヤに含まれます。

## データソースレイヤ

　他のシステムとの通信を行い、アプリケーションのためにタスクを実行します。

# レイヤ化アーキテクチャとヘキサゴナルアーキテクチャ

* [ヘキサゴナルアーキテクチャに関する記事](http://blog.tai2.net/hexagonal_architexture.html)

　ヘキサゴナルアーキテクチャは、外部システムへのインターフェースで囲まれた核としてシステムを視覚化したものです。外部にあるものはすべて外側のインターフェースとします。よって、ヘキサゴナルアーキテクチャは他への提供するサービスと他のサービスを利用することを区別しない、対称的な構造を持っています。対して、レイヤ化アーキテクチャは、他へのサービスとして提供するインターフェースと、他のサービスを利用することを区別する、非対称的なスキーマになっています。そして、この部分がプレゼンテーションレイヤとデータソースレイヤの違いとなっています。

# レイヤリングの方法

　システムの規模によって異なります。単純なものであれば、各レイヤのふるまいをサブルーチンとしてあげるだけで大丈夫です。より複雑なときにはクラスに分割を行い、さらに複雑な場合には幾つかのパッケージにクラスを分割してあげるということができます。状況によって一番適切な分割をするのが望ましいですが、最低でもサブルーチンレベルでの分割を行う必要はありそうです。

# レイヤ間の依存関係

　ドメインとデータソースはプレゼンテーションに依存しないようにします。ドメインとデータソースの関係は複雑なため、データソースのアーキテクチャに応じて考えていく必要がありそうです。

# レイヤの実行

　PoEAAの内容のかなりの部分は、論理的なレイヤについて解説したものになっています。システムを分割して、その境界部の結合を減らすことについての説明が書かれています。レイヤの分割は１台の物理マシンで実行していたとしても役に立ちます。しかし実行場所が異なることによって違いがもたらされることもあります。

　クライアント/サーバーなアプリケーションを例にとれば、サーバーですべてを実行すると、アプリケーションの更新は容易になります。一方クライアント側での実行はレスポンスや切断時の操作を考えると優れています。
railsでcsvを色々できるCSVメソッド

# CSVライブラリ

```
require 'csv'
```
これで読み込める

# CSV.read

```ruby:csv.rb
require 'csv'

csv_data = CSV.read('member.csv', headers: true)
```

.read(読み込むcsvの指定,headers:無視したいヘッダー行があるか)

headers:trueにすると上の一行をheaderとして無視する。

# CSV.foreach

.readで一気に読み込むのと結果は変わらないがこのやり方でも読み込める

```ruby:csv.rb
require 'csv'
CSV.foreach('member.csv', headers: true) do |data|
 intro_msg = "#{data["club"]}クラブ所属の#{data["age"]}歳、#{data["name"]}です。\n"
 puts intro_msg
end
```

# CSV.generate

generateはcsvを逆に生成するためのメソッド

```ruby:csv.rb
require 'csv'
intro_csv = CSV.generate do |csv|
  CSV.foreach('member.csv', headers: true) do |data|
    intro_msg = [
      data["id"],
      data["name"],
      "#{data["club"]}クラブ",
      "#{data["age"]}歳"
    ]
    csv << intro_msg
    puts intro_msg
  end
end

File.open("intro.csv", 'w') do |file|
  file.write(intro_csv)
end
```
>このメソッドは与えられた文字列をラップして CSV のオブジェクトとしてブロックに渡します。 ブロック内で CSV オブジェクトに行を追加することができます。 ブロックを評価した結果は文字列を返します。

https://docs.ruby-lang.org/ja/latest/method/CSV/s/generate.html

generateは１行ずつなので繰り返しかつ１行ずつintro_csvに入れていっているという処理。

# 参考にした記事

https://qiita.com/shizuma/items/7719172eb5e8c29a7d6e
[Note] Compile Rust to WebAssembly on Mac

## Install necessary modules from Homebrew

- cmake
- emscripten

```sh
$brew install cmake emscripten
```

After installing `emscripten`, you can see text like following on console.

```sh
Manually set LLVM_ROOT to
  /usr/local/opt/emscripten/libexec/llvm/bin
  and comment out BINARYEN_ROOT
  in ~/.emscripten after running `emcc` for the first time.
```

## Modified ~/.emscripten

I modified my `~/.emscripten` like this after calling `emcc` once.

```
# this helps projects using emscripten find it
EMSCRIPTEN_ROOT = os.path.expanduser(os.getenv('EMSCRIPTEN', '/usr/local/Cellar/emscripten/1.37.27/libexec')) # directory
#LLVM_ROOT = os.path.expanduser(os.getenv('LLVM', '/usr/bin')) # directory
LLVM_ROOT = os.path.expanduser(os.getenv('LLVM', '/usr/local/opt/emscripten/libexec/llvm/bin')) # directory

# Manually set LLVM_ROOT to
#   /usr/local/opt/emscripten/libexec/llvm/bin
#   and comment out BINARYEN_ROOT
#   in ~/.emscripten after running `emcc` for the first time.
#
# BINARYEN_ROOT = os.path.expanduser(os.getenv('BINARYEN', '')) # if not set, we will use it from ports

# If not specified, defaults to sys.executable.
```

## Compile

In root directory of your project, run following.

```sh
# compile a specific file.
rustc --target=wasm32-unknown-emscripten src/main.rs -o dist/main.js

# build you project into wasm
cargo build --target=wasm32-unknown-emscripten
```
VSCode + ES6 module: Parsing error: The keyword 'import' is reserved

If you're a VSCode+React coder, and you installed the ESLint in the VSCode, you might found that there is an error: 

**Parsing error: The keyword 'import' is reserved.**

The problem is: The "module" setting for reactjs is not enabled at the beginning. 

But it's an easy fix :) 

Just overwrite some settings in the User Settings of the VSCode:

```javascript
"eslint.options": {
        "parserOptions": {
            "ecmaVersion": 6,
            "sourceType": "module",
            "ecmaFeatures": {
                "jsx": true,
                "modules": true
            }
        }
    }
```

Done!
gae + spring boot

参考
https://github.com/GoogleCloudPlatform/getting-started-java/tree/master/appengine-standard-java8/springboot-appengine-standard

************
まだ書きかけ
************

# SpringBootServletInitializer継承クラスが必要

```
public class ServletInitializer extends SpringBootServletInitializer {
  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
  return application.sources(YourApplication.class);
  }
}
```
chrome拡張機能:onMessage.addListenerに登録する関数にasyncを指定するとコールバック関数が実行されない

# 状況
```javascript:content_script.js
chrome.runtime.sendMessage({type: 'sendMessage'}, response => {
  console.log('コールバック');
});
```

```javascript:background.js
chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
  if (message.type === 'sendMessage') {
    await aaa();
    sendResponse({type: 'sendResponse'});
    return true;
  }
});
```

background.jsで`chrome.runtime.onMessage.addListener`に登録する関数に`async`を指定すると、`return true;`を実行しても返り値が`Promise`になってしまう。そのため、content_script.js側のコールバック関数が意図したタイミングで実行されない。

# 対処法

```javascript:content_script.js
chrome.runtime.sendMessage({type: 'sendMessage'});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'sendResponse') {
    console.log('コールバック');
  }
});
```

```javascript:background.js
chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
  if (message.type === 'sendMessage') {
    await aaa();
    chrome.tabs.sendMessage(sender.tab.id, {type: 'sendResponse'});
  }
});
```

`chrome.runtime.sendMessage`のコールバック関数は使わず、`chrome.tabs.sendMessage`で新しくメッセージを送信する。
Amazon ECS でコンテナをローリングアップデートする

![ecs01.png](https://qiita-image-store.s3.amazonaws.com/0/141934/3bedc946-a5e9-fef9-04a0-0f818eb71baa.png)

# はじめに

ECSのローリングアップデートの動作を確認しましたので、備忘録として投稿します。

# もくじ

1. 旧バージョンのコンテナをデプロイ
2. 新しいリビジョンのタスク定義を作成
3. サービスを更新して新バージョンのコンテナをデプロイ

# ローリングアップデートの流れ

![update01.png](https://qiita-image-store.s3.amazonaws.com/0/141934/2d8596c3-5e79-45cf-4ae6-b5a1acd1ab66.png)

# 参考

- [ECSでコンテナのrolling update \- Carpe Diem](http://christina04.hatenablog.com/entry/2016/11/02/190000)
- [Amazon ECS launches new deployment capabilities; CloudWatch metrics; Singapore and Frankfurt regions \| AWS Compute Blog](https://aws.amazon.com/jp/blogs/compute/amazon-ecs-launches-new-deployment-capabilities-cloudwatch-metrics-singapore-and-frankfurt-regions/)

# コンテナイメージについて

ローリングアップデートの動作確認用にECRへ`v1`、`v2`とタグ付けしたコンテナイメージをプッシュしておきます。

今回の投稿では

- `v1`　旧バージョンのコンテナイメージ
- `v2`　新バージョンのコンテナイメージ

として扱います。

![update02.png](https://qiita-image-store.s3.amazonaws.com/0/141934/7a529933-fedd-ac93-a92a-7ccce7f7c592.png)


```html:index.html(v1)
<h1>Test v1</h1>
```

```html:index.html(v2)
<h1>Test v2</h1>
```

# 1. 旧バージョンのコンテナをデプロイ

旧バージョンのコンテナ(v1)をデプロイしておきます。

## タスク定義

タグ`v1`を明示的に指定して、旧バージョンのコンテナイメージを含んだタスク定義、サービスを作成してデプロイ。

![update03.png](https://qiita-image-store.s3.amazonaws.com/0/141934/891a0878-6305-9ac0-b686-e70802cb290d.png)

## アクセス確認

ブラウザからALBにアクセスして旧バージョンのHTMLが表示されることを確認。

![update04.png](https://qiita-image-store.s3.amazonaws.com/0/141934/625c8407-db78-4f00-c4d9-bad535050458.png)


# 2. 新しいリビジョンのタスク定義を作成

コンテナイメージのタグを`v2`に更新した新しいリビジョンのタスク定義を作成します。

![update20.png](https://qiita-image-store.s3.amazonaws.com/0/141934/9866b56a-1695-e948-21d9-2b5664a7c556.png)
![update21.png](https://qiita-image-store.s3.amazonaws.com/0/141934/ff86bfde-41da-a561-b119-058836425258.png)
![update22.png](https://qiita-image-store.s3.amazonaws.com/0/141934/f613d5ed-c79b-5b2c-fa30-482ece6153d0.png)


# 3. サービスを更新して新バージョンのコンテナをデプロイ

サービスを更新して新しいリビジョンのタスク定義をデプロイします。

## サービスの更新

**タスク定義**に新しいリビジョンを指定。

![update30.png](https://qiita-image-store.s3.amazonaws.com/0/141934/85e1d52b-0ff9-0394-51b5-98d711fd3a31.png)

> 補足：最小ヘルス率
> `50`を指定しているので、アップデート中にhealty状態のタスクが必要数の50%まで低下する可能性がある
> 補足：最大率
> `200`を指定しているので、アップデート中にhealty状態のタスクが必要数の200%まで増加する可能性がある

## Runningタスクの推移

アップデート前の**タスク**。
リビジョン１(旧バージョン)のタスクだけ稼働している。

![update31.png](https://qiita-image-store.s3.amazonaws.com/0/141934/ca7a724d-4e50-a914-92ac-7ad4962a4ef8.png)

アップデート中の**タスク**。
リビジョン１(旧バージョン)のタスクとリビジョン２(新バージョン)のタスクが混在する。

![update32.png](https://qiita-image-store.s3.amazonaws.com/0/141934/9201bfd1-b0ac-067c-a7d2-1c3b7d9d5bcb.png)

アップデート後の**タスク**。
リビジョン２(新バージョン)のタスクだけ稼働するようになる。

![update33.png](https://qiita-image-store.s3.amazonaws.com/0/141934/f686a9af-6127-cca1-0a09-ab03f0579b11.png)

## アクセス確認

ブラウザからALBにアクセスして新バージョンのHTMLが表示されることを確認。

![update34.png](https://qiita-image-store.s3.amazonaws.com/0/141934/bda34010-7504-dd5b-a746-5795ed6a20e8.png)
clapでコマンドライン引数解析 / Rust

# clapの宣言

```Rust
extern crate clap;
use clap::{App, Arg, SubCommand};
```

# アプリの宣言

```Rust
let app = App::new("git")
    .version("0.1.0")                       // バージョン情報
    .author("myname <myname@mail.com>")     // 作者情報
    .about("git CLI interface")              // このアプリについて
```

# フラグ

boolean型のオプション。

```Rust
let app = App::new("ls")
    .hogehoge(fugafuga)
    .arg(Arg::with_name("all") // フラグを定義
        .help("Show all")      // ヘルプメッセージ
        .short("a")            // ショートコマンド
        .long("all")           // ロングコマンド
        );
```

# オプション

通常のオプション。
値をとるフラグとも言う。

```Rust
let app = App::new("ls")
    .hogehoge(fugafuga)
    .arg(Arg::with_name("color") // オプションを定義
        .help("color option")    // ヘルプメッセージ
        .long("color")           // ロングコマンド
        .takes_value(true)       // 値を持つことを定義
        );
```

# 位置引数

位置固定の引数。

```Rust
let app = App::new("mkdir")
    .hogehoge(fugafuga)
    .arg(Arg::with_name("directory") // 位置引数を定義
        .help("victim directory")    // ヘルプメッセージ
        .required(true)              // 必須引数に設定することもできる。
        );
```

# サブコマンド

`git commit --amend`の`commit`の部分。
内部で`--amend`の部分を設定する。

```Rust
let app = App::new("git")
    .hogehoge(fugafuga)
    .subcommand(SubCommand::with_name("commit") // サブコマンドを定義
        .about("commit subcommand")             // このサブコマンドについて
        .arg(Arg::with_name("amend") // フラグを定義
            .help("amend flag")      // ヘルプメッセージ
            .long("amend")           // ロングコマンド
        );
```

# 引数を解析

```Rust
let matches = app.get_matches();
```

# 位置引数の処理

```Rust
if let Some(directory) = matches.value_of("directory") {
    //mkdir $directory
}
```

# オプションの処理

```Rust
if let Some(color) = matches.value_of("color") {
    //ls --color=$color
}
```

# フラグの処理

```Rust
if matches.is_present("all") {
    //ls -a
} else {
    //ls
}
```

# サブコマンドの処理

```Rust
if let Some(ref matches) = matches.subcommand_matches("commit") {
    if matches.is_present("amend") {
        //git commit --amend
    } else {
        //git commit
    }
}
```
gitのbranchは増えるとcheckoutがめんどくさいのでpecoってやった。

# 概要

####**めんどくさいgitのコマンドをもっと楽に使いたい!!!**

という強い衝動に駆られたため、pecoを使ってやってみた。前提わかっている方は、下まで読み飛ばすこと推奨。pecoなど初心者なので修行不足なところは指摘お願いいたしますm(_ _)m。


# 今回は以下の環境でpecoっている。

- MacOS：10.13.2
- peco：v0.5.2 (built with go1.9.2) <=Homebrewでのインストール

# そもそもpecoとは？

とてもシンプルなツールで 「標準入力から受けた行データをインクリメンタルサーチして、選択した行を標準出力に返す」 コマンド。

シンプルゆえに様々な組み合わせ次第で効果を発揮する。
あらゆる場面での選択肢を標準入力で受け取って結果を出力する。

**ほう。いや、ちょっと待ってくれ。**

# インクリメンタルサーチがわからん。

リアルタイムで結果が下に並んだりするアレ。

pecoっている様子を公式のGitから引用させてもらうと、、、

![sample.gif](https://qiita-image-store.s3.amazonaws.com/0/183308/a7d62b9f-a4ce-4f04-b999-1e2fbcda65e8.gif)
(出典：[peco-README(GitHub)](https://github.com/peco/peco))

# なるほどわかった。じゃあ。gitをpecoってやろう。

.bashrcに以下の記述をする。

```sh:.bashrc
alias gch='git checkout `git branch | peco | sed -e "s/\* //g" | awk "{print \$1}"`'
```
そのあとはこのファイルを適用するために以下のコマンドをうつ。

```shell
$ source ~/.bashrc
```

これで「gch」とうてば既存のブランチを検索かつ選択してcheckoutされる。

# 余談

aliasを設定すると「git commit -m "first commit"」などと打たなくても良い。打つのがめんどくさいものは容赦無く、aliasで省略している。それは別途Qiitaでまとめるつもり。
PostgreSQLのB-Treeについて（１）

# はじめに
PostgreSQLで使われてるB-Treeについてちょっと調べてみようかと思い、B-Tree関連のREADMEを読んでみたので理解したことの整理。ひとまず全部は理解不可能だった。

# B-Treeについて
B-TreeのREADMEはソースファイルの src/backend/access/nbtree/README にあるのでそれを閲覧。
B-Treeの構成はP. Lehman and S. Yaoの論文「[Efficient Locking for Concurrent Operations on B-Trees](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5027&rep=rep1&type=pdf)」に基づいているが、deleteに関する箇所はシンプルなロジックにするよう別の論文（V. Lanin and D. Shashaの「A Symmetric Concurrent B-Tree Algorithm」に基づいている。

前者の論文の解説をしているスライドを見つけたのでリンク貼っておく。
https://www.slideshare.net/myui/blinktree-presentation
後者の論文は買わないと入手できないっぽいのでちょっと放置。

論文を読んでみたところ、従来のB-Treeだと、SELECTとINSERTが並行して動いているときにINSERTによってB-TreeがsplitするとSELECT側で問題が発生する可能性があるので、同レベルのページとページを結ぶリンクポインターを用意しましょうというような話だと理解した（超ざっくり）。

アクセスパスの話を考えるときにもconcurrencyの話が出てくるんだなあと感慨深く思ったけど、その界隈の人からするときっと当たり前の話なんだろうなぁ。

# PostgreSQLでの変更点
PostgreSQLではLehmanとYaoの論文に完全に則っているわけではなく、いくつか変更点を加えている。
・論文ではB-Treeはすべてユニークキーが前提になっているけど、ユニークキーじゃなくてもB-Treeを使う
・論文ではread lockを必要としていなかったけど、PostgreSQLではread lockをとる
・論文ではリンクポインターを左から右（小さい値から大きい値の方向）に張ることとしていたが、
　PostgreSQLでは両方向に張る（インデックスを逆方向からスキャンすることを考慮）

他にもあるみたいだけどとりあえず今日はここまで。
READMEにはこの後にもDeletion Algorithmの解説とかが長々と続くけど、ちょっと理解できなかった。リベンジしたい。
新人エンジニア教育の3ヶ月間を振り返る

会社として新人入社は初めてで、新人もほぼ未経験に近い状況からスタート。
教える側、教わるか側両方とも試行錯誤しながらあっという間の３ヶ月でした。
そこで新人のエンジニアに教えたこと、これからの課題をまとめました。

ちなみに、新人は少しJavaの経験はありましたが、今回はiOS開発の研修にしました。


##１ヶ月目（実戦コードを書く前に）

### Swift知識の取得

本を１冊選んで目次から具体的に1日に学習する範囲を決め、学習した内容をレビューする形にしました。３週間ぐらい進めたら1冊を終ることができました。

>大事なことは分からない内容があっても止まらずに進むこと。
読んでいる時点では分らなくても後で分かるようになる。

###よく使うデザインパターンを知る
CocoaFrameworkで使われているデザインパターン中心にネット上に公開されたコードを真似して書き、後はサンプルコードを書く練習をしました。
Swift学習と並行で行い、Swift文法にもなれるようにしました。

###Git, GitHubの使い方を覚える
デザインパターンを学習する際に、GitHubを使うようにしました。
その前にGitについて１日は概念の説明、基本操作コマンドを教えました。


## ２ヶ月目（アプリ作成）
１０画面ほどの規模、サーバーAPI連携とテーブルビューを使うのを条件でアプリを考え、
GitHub上にレポジトリを作成し、アプリを作ることにしました。
明確な目標があった方が良いと思ったので１ヶ月スケジュールで進めました。

経験できたことは、
- アプリ設計（機能、遷移など）
- issue管理ツール使い方
- CocoaPodsの利用
- XCodeでDebugになれる
- テストケース作成、テスト


##３ヶ月目（アプリのリリース）
1.0バージョンのアプリが完成しましたのでリリースのための準備をしました。
AppStoreに登録する時にApple Developerで事前作業で証明書、Provisioningの説明をし、作成するまで一緒にやってみました。
ここからはほぼお任せにしてやらせたですが、順調に進んで行ったので今日AppStore公開されました。

公開されたアプリ
https://itunes.apple.com/jp/app/simpledocbase/id1329447639?mt=8
また、課題はたくさん残っています。

##その他（もっと良いエンジニアになるために）
新人にとってはアプリ作成の一通りの経験ができたので自己学習能力は付いたと思いました。
また、自分の知識をみんなに共有できるエンジニアになるために「技術ブログを書く」ことを話しています。
これからどんどん成長できることを期待しています。


## まとめ
- 3ヶ月でアプリがリリースできた。
- 次の新人教育は少し上手くなるかも。
- 新人を教えるのは大変、代わりに自分にも凄く勉強になる。
- 久しぶりに個人のGitHubが「みどり」になった。
- 私が新人の時にはこんなにはできなかったので本当に感謝してる。
Azure Logic AppsでBoxコネクタを使う時Boxサインインできない

Azure Logic AppsでBoxに画像ファイルが作成された時をトリガとする処理作ろうとしたらBoxサインインがうまくいかない事象でハマったので対処法メモ。

#事象
AzureLogicAppsで空のロジックアプリ追加して
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/e9b427ea-7bf0-a83c-600f-1286a58ec391.png)

Box検索して
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/0104de73-971c-c012-04f6-cf24950564d1.png)

ファイルが作成された時を選んで
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/80d7b7e1-545b-48d5-a05e-7e2043f47f93.png)

サインインしたいんだけど
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/7936e8b7-7196-caff-708d-bc4fc726ac03.png)

サインインをクリックすると一瞬だけNotFoundのブラウザが起動して
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/65bebabc-1625-d915-145d-46751ecf8975.png)
こうなったり
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/be4735ba-48a2-1bcc-d13c-a9294b276017.png)
こうなる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/61db621d-1c13-5aca-70c4-19294b6043c6.png)

#対処法
原因は不明だけど以下で解消した

リソースグループから対象のグループ選択して
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/29124d20-2668-d275-2af9-3d2bbad794d7.png)

リソースグループのディレクトリ見ると、作った覚えのない「box」と名の付くAPI接続ができてた。（サインイン失敗した回数だけどんどん増えてしまってる）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/4989b365-ec0a-7a32-1e77-e8a07c97e030.png)

まず失敗した分だけ増えたものは削除して
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/41638c0e-062c-cf77-ed7a-d75cb9196a42.png)

残す１つの[この接続は認証されていません→]というバーをクリックして
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/47f6d209-bbc9-8e39-4246-20aea22eb1e2.png)

承認をクリックすると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/c1005dd5-fd2a-aea5-783a-4d97c70bd3fc.png)

Boxの認証画面ブラウザが起動するのでサインイン
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/4d9142cb-1088-093b-6520-33eb3f86ad78.png)

こんなの出るので許可して
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/5cea0139-c7cd-2f2f-ba3b-29aeb12f81eb.png)

保存すると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/030368b1-6427-da6e-130a-afb11eb6b19f.png)

通知が表示されて
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/2aa7f3d9-beb1-7c2b-5527-7f4f1cee2c75.png)

さっきのオレンジのエラー的なバーがなくなって表示名項目にBoxアカウントが表示されてる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/94a8e05d-56d0-b1de-4547-45ca2a2eb493.png)

LogicAppsでもう一度Boxコネクタクリックすると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/77d169f5-f45a-7bb3-5911-680f7f220dad.png)

サインインされた状態で追加できた。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/178016/610dee1d-e0fd-2c74-b58b-a0f33de7f96a.png)

よくわからないけど何度やってもこの手順でやらないとBoxコネクタ追加できない…
誰か原因とかもっといい手順知ってたら教えてください。
はじめてのLT（ライトニングトーク）で気をつけた21のこと（申込、準備、資料作成、練習、発表までのまとめ）


# はじめに
先日、人生初LTをしてきました。
学びが非常に多かったのでまとめました。
気をつけたことは全部で21個あります。
これからLTする人の参考になれば幸いです。

## LTをやろうと思った理由
**インプットだけでなく、アウトプットにも挑戦したかったから**です。
Qiitaや[はてなブログ](http://www.yokoyan.net/)も書きますが、書くことだけでなく、社外で人前で話すことにも挑戦しようと思いました。

## LTをした勉強会
ぼっち参加でしたが、とても楽しかったです。

[Co-Edoでエンジニア・Webデザイナー飲み会 『Co-Edoでコエドビールを飲みながら2018年の目標を立てる会』](https://coedo-dev.doorkeeper.jp/events/68103)

## LT資料
SlideShareにアップしました。

[35歳だけどrailsチュートリアルを完走したら人生が変わった話](https://www.slideshare.net/ssuserb75d92/35rails)

## LTをする際に気をつけたこと
### 申込編
- LT枠を確認する
- やりたい！と思ったらすぐ申し込む
    - **できる、できないじゃない！やるか、やらないかだ！！**
    - 私の場合、迷っている間に枠が埋まってしまった
        - でも諦めない
        - **やらず後悔よりも、やって反省の方針**で挑むことにした
    - ダメもとで申し込んだところ、補欠枠での参加となった

### 準備編
- LTの目的を考える
    - **プレゼンテーションは、相手に共感してもらい、相手に動いてもらうためにするもの**
    - **自分が話したいこと＝参加者が聞きたいこととは限らない**
    - 相手が動いてくれたらプレゼンは成功
- 自分が5分で伝えたいことを整理する
    - 資料を作る前に、紙に書いてみる
    - 5分のトークから、参加者に持ち帰ってもらうものを考える
- 参加者をイメージする
    - 自分のテーマに対して、参加者が詳しいとは限らない
        - 今回は、そもそもRailsチュートリアルを知っている人なのか？を考えた
        - エンジニア・デザイナー飲み会なので、皆無ということはなさそう
        - 知らない人がいることも想定して、「無料のチュートリアルで、全部やるとTwitterのようなサービスが作れます」という説明にした
- 時間を確認する
    - 3分なのか、5分なのか、10分なのかで全然違う
        - 今回は5分だった
        - 当日の進行で急に短くなることもあるので注意

### 資料編
- LTの先輩たちの資料を見る
    - [SlideShare](https://www.slideshare.net/)
    - [Speaker Deck](https://speakerdeck.com/)
- 先輩たちの凄さに自信を失うが、自分は自分。**気にしすぎない**
- 資料は凝り過ぎない
    - パワーポイントでも十分伝わる
    - デザインに凝り過ぎると時間が取られる
- **自分の一番伝えたいことを、スライドの最初と最後に入れる**
    - 時間がなくても伝えられるようにする
- 笑いは取れたらラッキー、くらいでやる
    - ネタに凝り過ぎて滑るとリカバリできない
    - ネタは一瞬入れるくらいでちょうどいいと思う
- できる限り文字は減らす
    - 文字は大きくシンプルに、わかりやすさを心がける

### 練習編
- 必ず事前に練習する
    - 家やカフェでぼっち練習
        - 今回は7回練習した
    - 資料を見ながらぶつぶつ呟いてみる
    - しゃべってみると、説明しづらい箇所が絶対出るので、資料を修正する
    - 時間を測り、必ず5分で終わるようにする
        - 練習時にどうしても5分15秒を切れなかったため、思い切ってテーマ説明と自己紹介を大幅にカットした
        - 当日は4分50秒くらいだった

### 発表編
- LTをする前にお酒を飲み過ぎない
    - お酒が出る勉強会・飲み会には気をつける
    - 緊張をほぐしたり、歓談中に飲むくらいでいい
- LT開始時には、「よろしくお願いします」と言う。頭も下げる
    - 挨拶は大事！
- 自己紹介は一言（10秒くらい）で済ませる
    - 貴重な5分の中で、自己紹介に時間を割くのは危険
    - LTの自己紹介ページは必要
    -  「Railseエンジニアやってるよこやんです」くらいでいい
    - 参加者が聞きたいのは**自己紹介ではなく、LTのテーマ**
    - 本当に自分に興味がある人は、LT後に話しかけてきてくれる
    - 自分語りで終わる5分にするのではなく、**何か1つでも参加者が得るものがある5分にしたほうがいい**
- 熱意を持って話す
    - たとえ資料や技術が拙くても、気持ちは伝わると思う
    - 自分の好きなことや、生々しい体験談は自然と熱意が入る
    - 成功体験、失敗体験、テーマによって取り入れる
    - **ただし、自分ポエムを話し過ぎないように気をつける**
- LT中は笑顔！
    - 緊張して早口にならないように気をつける
- 横目でタイマーを見ながらLTを進める
    - 主催者の方が用意してくれていると思う
    - 無かったら自分のスマホで代用
    - 時間を守ってこそのLT
- LT中に自分の味方を見つける
    - 自分の話を聞いてくれない人に話し続けるのは辛い
    - 自分の話にうなずいてくれる人（女性が多い印象）に向かって話す
- LT終了時には、「ありがとうございました」と言う
    - お礼は大事！
    - **貴重な時間を割いてくれた参加者のみなさんに感謝**

# おわりに
**習得した技術や経験を話して、誰かの役に立てるということは素晴らしい**と思いました。
これからもどんどんLTに挑戦したいと思います！
Windows Subsystem for LinuxからUbuntuをアンインストール

Windows Subsystem for LinuxにインストールしたUbuntuをアンインストールする方法です。
環境が汚れてきたのでアンインストールしようとしたらちょっとハマった・・・。

#環境
Windows 10 Fall Creators Update（バージョン 1709）

#インストール
インストールは以下の記事を参考にさせていただきました。

Windows Subsystem for Linuxをインストールしてみよう！
https://qiita.com/Aruneko/items/c79810b0b015bebf30bb

#アンインストール
「アプリと機能」からUbuntuをアンインストールするだけです。
スタートメニューからUbuntuを右クリックしてアンインストールでもいいです。

以下の記事でLinuxディストリビューションのアンインストール方法がありました。

Windows Subsystem for Linuxとは？ そのインストールと使い方
http://www.buildinsider.net/enterprise/wsl/01

lxrunコマンドでアンインストールするものと思ってました・・・。
Raspberry Pi 3の無線LAN(内蔵WiFi)をオフにする

# はじめに
Raspberry Pi 3 MODEL B、いろいろと設定しています。２通りの内蔵無線LAN(WiFi)をオフにする方法があるようなのでメモしておきます。(2018年1月現在)

# 記述方法

下記のどちらかを設定すれば大丈夫です。両方とも記載する必要はありません。

## /boot/config.txtに書く方法

ファイルの最後に追記します。

```diff:/boot/config.txt
# Additional overlays and parameters are documented /boot/overlays/README
+ #turn wifi and bluetooth off
+ dtoverlay=pi3-disable-wifi
+ dtoverlay=pi3-disable-bt
```
ほかにも機能のオン/オフの制御ができるようなので、チャレンジしてみたい場合は`/boot/overlays/README`または[GitHub](https://github.com/raspberrypi/firmware/blob/master/boot/overlays/README)を見てみるとよいかも。

## /etc/modprobe.d/raspi-blacklist.conf に書く方法

```ini:/etc/modprobe.d/raspi-blacklist.conf
# internal wifi off
blacklist brcmfmac
blacklist brcmutil

# internal bt off
blacklist btbcm
blacklist hci_uart
```

構築されている環境によって`/etc/modprobe.d/raspi-blacklist.conf`のファイルはあったりなかったりするようです。自分が試した環境ではファイルが無かったので新しく作りました。


# 参考
- [How to disable the Pi3's WLAN & Bluetooth ? - Raspberry Pi Forums](https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=138610)
- [raspbian - Disable WiFi (wlan0) on Pi 3 - Raspberry Pi Stack Exchange]( https://raspberrypi.stackexchange.com/questions/43720/disable-wifi-wlan0-on-pi-3)
- [Raspberry Pi 3の内蔵WiFiを無効にしてUSB WiFiアダプタを利用する by mascii](https://qiita.com/mascii/items/14cccd6c791f43beb492)
デザイナーがGIthubで機能追加のリクエストをIssueにあげてみた

## 経緯
少し前からランチャーツールRunnerを使い始めた。すごく便利で特に
・[Automate](https://github.com/Ashung/Automate-Sketch)
・[FontIcon](https://github.com/keremciu/sketch-iconfont)
との相性が抜群。加えて、[Rename It](https://github.com/rodi01/RenameIt)も同時期に導入し、便利で使っていたが、一点困る点があった。
## 課題
管理の問題なのかもしれないが、Sketchファイル内にデザインのパターンを複数個作っている場合、検索から一括置換で全て変更されてしまうとパターン作成時にとても困るのである。そこでスコープの設定(全てのページ/現在のページ/選択したレイヤー)をお願いしてみた。
※現在のアートボードを選択肢に入れなかったのは、
・選択肢を少なくしたかった
・現在のアートボードのみに適応というのが自分のワークフローで少なかった
## 準備
もともとGithubの利用目的はプロジェクトの管理がメインだったので、バージョン管理用にプライベートのリポジトリしか基本利用しない、かつデザイナーでエンジニア界隈のお作法を知らないので、まず簡潔にわかりやすく伝えるように(無駄なことを嫌う文化なので)他の人がどのようにIssueを上げているのか調査。
**Feature Request:** を文頭につけると良さそうなのがわかった。そしてタイトルも簡潔に**Search scope**のみに。
本文は失礼にならないように比較的丁寧な言い回しの英語を選定。適切そうなUIの提案もやんわり組み込んだ。
## 結果
書き込んだ次の日にメールをチェックしていたら、Githubから珍しくメールの通知が。(普段は請求くらいしか来ない)
> **Re: [rodi01/RenameIt] Feature Request: Search scope (#64)**
> That's a good idea! I will add to the backlog.

・・・・・おおおおおお!!!!!!

自分が提案したアドバイスに対してポジティブなフィードバックがあったこと、プロダクトの改善に役に立てたこと、エンジニアのコミュニティに少し入れたこと、遠い国の開発者([ロドリゴさん](https://github.com/rodi01)はアメリカ在住っぽい)とコミュニケーションをとれたこと等々、全てが新鮮で嬉しかった。

## 今後の目標
オープンソースのコミュニティに少しでも貢献したいのと自分の力試しのためにも、今年はSketchの既存のplug-inをFolkしてカスタマイズを加えて公開しようと思います。目指せ★ゲット。

## その後(※1/6時点)
自分が提案した要望は、現在開発中のv3の中に入っていて既に着手された模様。
![download-3.png](https://qiita-image-store.s3.amazonaws.com/0/223203/60deb7fc-761a-93c5-fab0-6d4b22b98ab7.png)
AndroidのContentResolverで取得したFileの種類を調べる

# はじめに　
Androidの標準ギャラリーのようなアプリを作りたいと思って調べていたのですが、画像と動画を同時に表示する方法を載せている記事が少なかったため、まとめておきます。
下にサンプルコードを載せておくので、面倒な方は飛ばして使ってください。

# 概要
見るべき場所は

```kotlin
val proj = arrayOf(MediaStore.MediaColumns._ID,MediaStore.Files.FileColumns.MEDIA_TYPE)
```
この部分で、ここで欲しい情報を付与できます。今回であればIDと、FileのMediaType(画像or動画or...etc)の２つを指定しています。

これを使って

```kotlin
val crsCursor = contentResolver.query(
                    MediaStore.Files.getContentUri("external"),
                    proj,  //欲しいデータカラムの指定
                    ...
```
でCursorを取得したら、あとは

```kotlin
//1:image 3:video
val mediaType=crsCursor.getInt(crsCursor.getColumnIndex(MediaStore.Files.FileColumns.MEDIA_TYPE))
```
でFileの種類を判別できます。

# サンプルコード
```kotlin

val contentResolver = context.contentResolver

val proj = arrayOf(MediaStore.MediaColumns._ID,MediaStore.Files.FileColumns.MEDIA_TYPE)

val selection = (MediaStore.Files.FileColumns.MEDIA_TYPE + "="
                    + MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
                    + " OR "
                    + MediaStore.Files.FileColumns.MEDIA_TYPE + "="
                    + MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO
                    )

val crsCursor = contentResolver.query(
                    MediaStore.Files.getContentUri("external"),
                    proj,  //欲しいデータカラムの指定
                    selection, //filter
                    null,
                    MediaStore.Files.FileColumns.DATE_ADDED + " DESC" //sort
            )
crsCursor!!.moveToFirst()
for (i in 0 until crsCursor.count) {
                val id = crsCursor.getLong(crsCursor.getColumnIndex(MediaStore.MediaColumns._ID))

                //1:image 3:video
                val mediaType=crsCursor.getInt(crsCursor.getColumnIndex(MediaStore.Files.FileColumns.MEDIA_TYPE))

                // URIを取得
                var fileUri:Uri?=null
                if(mediaType==1) {
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　//画像のときの処理
                    fileUri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id.toString())
                }
                else if(mediaType==3){
                    //動画のときの処理
                    fileUri = Uri.withAppendedPath(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id.toString())
                }
                crsCursor.moveToNext()
}
crsCursor.close()
```
既存サービスにRailsでransackを使って検索機能を作成する

# Railsでransackを使って検索機能を作成する。
目標：友人と作成しているWebサービスで検索機能をつけたい。

- Rails:5.0.2
- ruby:2.4.0
- Bash on Ubuntu on windows Version 10.0.15063
- ransack（今回はこちらで実装してみるという記事）

# ダミーのプロジェクトでransackを実装してみる。
こちらの記事を参考にさせていただき、ダミーのプロジェクトでransackを実装してみる。
http://ruby-rails.hatenadiary.com/entry/20141008/1412774436

![test.gif](https://qiita-image-store.s3.amazonaws.com/0/139636/4e83a08c-b5a7-6edb-23d0-13239a80baa6.gif)

# 既存PJにransackを導入し検索画面を作成する。

この節での目標は友人と作成しているWebサービスに対してransackを導入し、商品に当たるテーブルを検索する画面、検索結果を表示する機能を実装するところである。
（この記事の最終的な目標は上記の通りなので、それまでの1つ目のステップ）

- ransackをinstallする。

```ruby:Gemfile
gem 'ransack'
```

``` bundle install ```
Using ransack 1.8.4 インストール時点(2017/12/17)で左記のバージョンがインストールされました。

- 検索を行いたいテーブルのコントローラーにindexアクションを追加する。

```ruby:hobbies_controller.rb
  def index
    @q        = Hobby.search(params[:q])
    @hobbies = @q.result(distinct: true)
  end
```

- ルーティングを追加する。

```ruby:routes.rb
 - resources :hobbies, only: %w(create)
 + resources :hobbies, only: %w(index create)
```


- 検索機能を実装したいテーブル（hobby）のViewファイルを作成する。


```ruby:view/hobby/index.html.slim
h1 趣味検索
= search_form_for @q do |f|
  = f.label :name_cont, "キーワード"
  = f.search_field :name_cont
  br/
  = f.submit '検索', class: 'record-form__submit-button'

  table
    thead
      tr
        th 趣味名
    tbody
      - @hobbies.each do |hobby|
        tr
          td = hobby.name
  br/

```

今検索機能をつけたいテーブルの構造はこんな感じでnameの検索ができれば十分。

```ruby:db/schema.rb
  create_table "hobbies", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string   "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
```

結果、趣味の検索ができた。

![test2.gif](https://qiita-image-store.s3.amazonaws.com/0/139636/03b266a8-b693-32f6-f9ef-663f65157b3c.gif)

# 検索結果にリンクを付け検索結果より別画面に遷移する。
先ほどまでで商品に当たるテーブルを検索する画面、検索結果を表示する機能ができた。ここでは、検索結果の商品（趣味）にリンクをつけて、検索結果のレコ―ドをクリックすると別画面に遷移させる機能を実装する。

- 検索結果の商品（趣味）にリンクを付ける。
実装としては、商品（趣味）のshowアクションで商品（趣味）個別のページを作成する。

```ruby:hobbies_controller.rb
  def show
    @hobby = Hobby.find(params[:id])
  end
```

routes.rbにshowアクションを追加。

```ruby:routes.rb
 - resources :hobbies, only: %w(index create)
 + resources :hobbies, only: %w(index show create)
```

showアクションのviewファイルを作成。

```ruby:view/hobby/show.html.slim
h1 一覧
table
  thead
    tr
      th 趣味名
      td = @hobby.name
```

indexのviewファイルを変更。

```ruby:view/hobby/index.html.slim
    tbody
      - @hobbies.each do |hobby|
        tr
-          td = hobby.name
+          td = link_to hobby.name, hobby
```

以上で、一旦完了。



# 参考文献
下記参照させていただいた文献一覧です。

http://ruby-rails.hatenadiary.com/entry/20141008/1412774436
https://qiita.com/nysalor/items/9a95d91f2b97a08b96b0
https://qiita.com/nishina555/items/2c1f8bae980e426519bc
DynaModelを継承したクラス経由で生成したレコードのnullの取扱いで困ったときのメモ

## 環境
Python 3.6.1

## 事象

- boto3ライブラリのDynaModelクラスのputメソッドを使って
DynamoDBにレコードを登録した際、nullableなカラムに明示的にnullを入れても
生成されたレコードにカラムが出来上がらない。

    →ライブラリ側の仕様でputメソッド内でレコード生成時にnull入りカラムは明示的に除去している様子。

上記の除去されたカラムを含むレコードを取得してきてSchemaクラスで定義しているフィールド(カラム)に
普通にアクセスしようとするとAttributeErrorで叩き落ちる。


## 対応

### その1
nullの可能性があるカラムのみ、ビルドイン関数のhasattrを使用して判定してからアクセス。

```python3:hasattr.py

attribute = model.attribute if hasattr(model, "attribute") else None

```

### その2
追加開発するタイミングとかで必須カラムを追加することになったりして、
すべての必須カラムがnullになりうるとする。
「都度都度hasattr噛ませたり噛ませるための関数を呼ぶのうざくない？」と思い至り
DynaModelクラスを拡張して、ほぼ恒久的にこの件を気にしなくて済む方法を考えてみた。
こっちがメモを残しておきたい本題。

```python3:dynamodel.py
from dynamorm import DynaModel as BaseDynaModel

class DynaModel(BaseDynaModel):
    def __getattr__(self, item):
        field_names = self.Schema.dynamorm_fields().keys()
        if item in field_names:
            return None
        else:
            raise AttributeError(
                ": '{}' object has no attribute '{}'".format(
                    self.__class__.__name__, item)
            )
```

`__getattr__`がPythonのクラスに標準搭載されている隠しメソッドで、
存在しないカラム(フィールド)へアクセスしたタイミングでのみ呼ばれる。
このメソッドが呼ばれるタイミングでNone返せば叩き落ちずに済む。

ただし、Schemaクラスで定義済みのもののみNoneを返したくて、
他のパターンはエラー返さないとバグ検知できなくなっちゃうのは避けたかったので、
Schemaクラスへ定義済みのフィールドを全部返してくれる
`dynamorm_fields()`ってライブラリ内で用意されてる関数を使って定義有無確認の処理を挟んだ。

## 参考

Swiftでいう変数に直接設定できるゲッターセッター的なものがPythonにはないのだろうかと
あれこれググって、以下の記事で`__getattr__`について見つけてとても助かりましたm(_ _)m

[Pythonを書き始める前に見るべきTips]
(https://qiita.com/icoxfog417/items/e8f97a6acad07903b5b0)
intra-mart実践入門の作成記録  #000 はじめに


# はじめに
　同タイトルの一連の記事は執筆時の備忘のために書かれています。内容の全てを公開するつもりはありませんが、一部の情報は公開するかもしれません。

# 概要
　中小企業の情報システム部門の技術者が[intra-mart](https://www.intra-mart.jp/)を基盤とした社内システムを__SIerや地場ベンダーに発注せず内製する__かつ__スクラッチでの開発は行わずintra-mart社が提供している機能をフル活用して開発を行う__という前提で、公式ドキュメントよりはややマニアックな内容を中心に記述していきます。キャッチフレーズは__e-Builderを使ったら負け__です。

# 対象者
　内容を読まなくても一部のキーワードからシステムの構築が出来るレベルの技術者向けの書籍ではありません。どちらかと言えば__いきなりintra-martが上から降ってきて「これでリプレースよろしく」と言われた__という技術者向けの書籍です。また、スクラッチ開発は行わないので顧客のシステム構築の参考にしたい技術者にはあまり役立たないかもしれません[^1]。

# 執筆環境
　執筆は[Re:VIEW](http://reviewml.org)を利用して行う予定です。前回執筆時にはmarkdownからPDFへの変換を使いましたが、__今回は出版社を通しません[^2]ので、ある程度体裁を整った書籍を自力で用意する必要がある__ためです。
　編集したドキュメントは[Visual Studio Team Services(VSTS)](https://www.visualstudio.com/ja/team-services/)のGitレポジトリで管理し、ブランチへのpushをトリガーとしたCIをしながら確認していく予定です。また、購入希望者でMSアカウントをお持ちの方には私のVSTSアカウントにステークホルダーライセンスでアクセスしていただき、執筆してほしい項目について希望を募ることも考えています[^3]。

# システム構成
　私が前職で経験した以下のシステム構成[^4]を基準に執筆を行います。

* OS：CentOS 7.x
* JDK：1.8.x ～ 1.9.x
* AP：Resin 4.x
* DB：PostgreSQL 9.x ～ 10.x


[^1]: NTTデータイントラマート社の営業担当ですら『カスタマイズせず自社開発する企業は珍しい』と発言していました。5000社を超える導入実績があれども、本書の内容が必要になる技術者はかなり少数になると予想されます。これが出版社を通さなかったり価格が高めになったりする理由でもあります。
[^2]: 出版社を軽んじる人もいますが、企画・校正・組版・印刷・流通・広告・著作権管理等の個人ではできないサービスを提供してくれます。真っ当な需要を見込めるのであれば、出版社を通して執筆する方がより良いものを世に送り出すことが出来るはずです。
[^3]: 未経験の内容の場合は必ず書くとは言えないですが。
[^4]: オンプレミスを前提としますが、タイミングを見計らってクラウドでの構築についても加筆する予定です。
the sample using == operator and any and all in more than 3 dimensions and where method

```python
print("====sample1====")
A = np.random.randint(0,5,(3,2,2))
B = np.random.randint(0,5,(2,2))
print(A,B)
C = (A == B)
print(C)
print(C.shape,A.shape,B.shape)
print("====sample2====")
A = np.random.randint(0,5,(4,3,1,1))
B = np.random.randint(0,5,(2,2))
print(A,B)
C = (A == B)
print(C.shape,A.shape,B.shape)
print(C)
print("====any====")
D = C.any((3,1))
print(D)
print(D.shape,C.shape)
D = C.any((3))
print(D)
print(D.shape,C.shape)
print("====all====")
D = C.all(1)
print(D.shape)
print(D)
rows = np.where(D)
print(rows)
print(rows[0])
```
* e.g.

```
====sample1====
[[[0 3]
  [4 1]]

 [[2 4]
  [3 0]]

 [[0 2]
  [4 4]]] [[0 2]
 [3 3]]
[[[ True False]
  [False False]]

 [[False False]
  [ True False]]

 [[ True  True]
  [False False]]]
(3, 2, 2) (3, 2, 2) (2, 2)
====sample2====
[[[[4]]

  [[1]]

  [[1]]]


 [[[3]]

  [[4]]

  [[2]]]


 [[[0]]

  [[4]]

  [[0]]]


 [[[2]]

  [[2]]

  [[2]]]] [[4 2]
 [2 4]]
(4, 3, 2, 2) (4, 3, 1, 1) (2, 2)
[[[[ True False]
   [False  True]]

  [[False False]
   [False False]]

  [[False False]
   [False False]]]


 [[[False False]
   [False False]]

  [[ True False]
   [False  True]]

  [[False  True]
   [ True False]]]


 [[[False False]
   [False False]]

  [[ True False]
   [False  True]]

  [[False False]
   [False False]]]


 [[[False  True]
   [ True False]]

  [[False  True]
   [ True False]]

  [[False  True]
   [ True False]]]]
====any====
[[ True  True]
 [ True  True]
 [ True  True]
 [ True  True]]
(4, 2) (4, 3, 2, 2)
[[[ True  True]
  [False False]
  [False False]]

 [[False False]
  [ True  True]
  [ True  True]]

 [[False False]
  [ True  True]
  [False False]]

 [[ True  True]
  [ True  True]
  [ True  True]]]
(4, 3, 2) (4, 3, 2, 2)
====all====
(4, 2, 2)
[[[False False]
  [False False]]

 [[False False]
  [False False]]

 [[False False]
  [False False]]

 [[False  True]
  [ True False]]]
(array([3, 3]), array([0, 1]), array([1, 0]))
[3 3]
```
# Refs.
* [NumPyのall関数とany関数の使い方](https://deepage.net/features/numpy-allany.html)
* [where](https://deepage.net/features/numpy-where.html)
今まで食わず嫌いだった僕がDockerやってみる

# 概要

今まで、VirtualBoxとかでいいじゃん。VPSでいいじゃんと思ってました。
会社でDockerを触ってみたら、思いの外便利だったので、ちょっと使ってみたいと思います。

# 環境

MacBookを使ってやってみます。
内容はHighSierra 10.13.2
Macbook 12-inch Early 2016
1.1GHz Core m3
メモリ 8GB

という状況

# インストール

brewで入れればOK

```shell
$ brew cask install docker
```

これで入る。
入ったらアプリになってるのでランチパッドからDockerを起動

権限が必要なのでパスワードが要求されるので、入れてやる。

updateがあるらしいので、受け入れた。

# ubuntuさわってみるか

```
$ docker run -it --rm ubuntu:latest /bin/bash
root@3e04fa26ef15:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
root@3e04fa26ef15:/# cat /etc/os-release 
NAME="Ubuntu"
VERSION="16.04.3 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.3 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
```

これでもうubuntuがさわれる

--rmオプションいれてるのでexitすれば、コンテナ消えてきれいさっぱり

# centosさわってみるか

```
$ docker run -it --rm centos:latest /bin/bash
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
85432449fd0f: Pull complete 
Digest: sha256:3b1a65e9a05f0a77b5e8a698d3359459904c2a354dc3b25ae2e2f5c95f0b3667
Status: Downloaded newer image for centos:latest
[root@c4839eb88252 /]# ls
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                etc  lib   media  opt  root  sbin  sys  usr
[root@c4839eb88252 /]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
```

こっちも--rmオプションいれてるのでexitすればきれいさっぱり

簡単すぎる

# まともに利用する場合の手順メモ

あたらしいコンテナつくって起動、名前はhogehogeにしてこれであとからアクセスする

```
$ docker run -it --name=hogehoge ubuntu:latest /bin/bash
```

コンテナにログイン中に抜ける方法

```
control + P control + Q
```

起動中のコンテナを調べる

```
$ docker ps
```

停止中も含めて全部調べる

```
$ docker ps -a
```

起動中のコンテナのコマンドにアクセスする(hogehogeは名前、psで確認したコンテナIDでもいい)

```
$ docker attach hogehoge
```

attach中のコンテナを止める
exit打つとよさげ

```
ubuntu@[id] # exit
```

detach中にコンテナを止める

```
$ docker stop hogehoge
```

停止中のコンテナを再度起動する

```
$ docker start hogehoge
```

起動しつつさらにattachもする

```
$ docker start -a hogehoge
```

停止中のコンテナを消す

```
$ docker rm hogehoge
```

起動しているコンテナでなにか別のコマンドを走らせる

```
$ docket exec hogehoge [何らかのコマンド]
```

dockerにログインしなくても、いろいろとできました。

おぉ便利と思ったわけだが
とりあえずなにかしたいことはないな・・・いまのところ。
Pythonの例外処理「except」は複数連結出来る

小ネタ。
常識っちゃ常識らしいがしらなかったので。
# 環境
Python 3.6.2
# 例
```python:example.py
def example():
    try:
        num = float(input("入力する値は？"))
    except KeyboardInterrupt:
        print ("終了します.")
        sys.exit()
    except ValueError:
        print ("値が不正です")
        example()
    except Exception as e :
        print ("不明なエラーです")
        print (e)
        sys.exit(1)
   
```

というようにエラーの内容別に処理を分けることが出来る。
UnityでAndroidのバックボタン対応を1行で解決する

# やりたいこと
AndroidのBackボタン(左向きの三角ボタン)を押した時にアプリを終了させたい時の話です。

Daydreamでは品質要件にて実装がすべきと明確に決まっています。
[Daydream App Quality Requirements - Functionality  |  Google VR  |  Google Developers](https://developers.google.com/vr/distribute/daydream/functionality-requirements#FN-A2)


# 方法
今まではこういうノリのコードを書いていたのですが、

``` test.cs
void Update()
{
    if (Application.platform == RuntimePlatform.Android && Input.GetKeyDown(KeyCode.Escape))
    {
        Application.Quit();
        return;
     }
}
```

実は一行で対応できることを知りました。

``` solution.cs 
Input.backButtonLeavesApp = true;
```

[Unity - Scripting API: Input.backButtonLeavesApp](https://docs.unity3d.com/ScriptReference/Input-backButtonLeavesApp.html)

Daydreamは「X」ボタンとバックボタンの両方がこれ1行で対応できました。
supersetを使って人口統計・推計を見えるようにしたら



# 環境
* macOS High Sierra 10.13.2
* python 3.6.3

# インストール
公式の
https://superset.incubator.apache.org/installation.html#getting-started
の通りで，特に問題なかった．

設定ファイルは`/usr/local/lib/python3.6/site-packages/superset`の下にある．


# 動機
* 年末年始で暇だし何かしたいなぁ，と思って
* 去年読んだ[この本](https://www.amazon.co.jp/%E7%B8%AE%E5%B0%8F%E3%83%8B%E3%83%83%E3%83%9D%E3%83%B3%E3%81%AE%E8%A1%9D%E6%92%83-%E8%AC%9B%E8%AB%87%E7%A4%BE%E7%8F%BE%E4%BB%A3%E6%96%B0%E6%9B%B8-NHK%E3%82%B9%E3%83%9A%E3%82%B7%E3%83%A3%E3%83%AB%E5%8F%96%E6%9D%90%E7%8F%AD/dp/4062884364/ref=la_B00IZAVXN0_1_1?s=books&ie=UTF8&qid=1515213811&sr=1-1)とか[この本](https://www.amazon.co.jp/%E6%9C%AA%E6%9D%A5%E3%81%AE%E5%B9%B4%E8%A1%A8%E3%80%80%E4%BA%BA%E5%8F%A3%E6%B8%9B%E5%B0%91%E6%97%A5%E6%9C%AC%E3%81%A7%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89%E8%B5%B7%E3%81%8D%E3%82%8B%E3%81%93%E3%81%A8-%E8%AC%9B%E8%AB%87%E7%A4%BE%E7%8F%BE%E4%BB%A3%E6%96%B0%E6%9B%B8-%E6%B2%B3%E5%90%88%E9%9B%85%E5%8F%B8-ebook/dp/B071WR8G74/ref=asap_bc?ie=UTF8)を思い出して
* 国連(国連経済社会局 人口部)には[こんな感じのサイト](https://esa.un.org/unpd/wpp/Maps/)があったり，フランスの国立人口統計学研究所には[こんなサイト](https://www.ined.fr/en/everything_about_population/graphs-maps/population_graphs/)があったりするのを見て

# データ

* [estat](https://www.e-stat.go.jp/)
国勢調査（2000年，2005年，2010年，2015年）の結果を利用．

* [国立社会保障・人口問題研究所(社人研)](http://www.ipss.go.jp/)
2010年の国勢調査をベースにした，2040年までの5年おきの[地域別人口推計](http://www.ipss.go.jp/pp-shicyoson/j/shicyoson13/3kekka/Municipalities.asp)を利用．

> この記事を編集している間に，estatがリニューアルされたようで，そこで社人研のデータが使えるようになれば，以下の内容もestatのダッシュボードで見えるようにできるはず...


# 可視化例

* 都道府県別の人口推移

![都道府県.png](https://qiita-image-store.s3.amazonaws.com/0/228676/adf7ab2e-76cc-cc45-37a0-3a4def7da10b.png)

* 東京都特別区部の人口推移

![特別区部.png](https://qiita-image-store.s3.amazonaws.com/0/228676/7bf80c2d-c578-32e8-6b95-f9417b08e854.png)

足立区が結構減っていく...

* 夕張市の年齢別人口推移

![夕張市.png](https://qiita-image-store.s3.amazonaws.com/0/228676/827006b8-4fb3-190d-f513-eca5320fc3a9.png)

夕張市を選んだのは，上で引用した本の中で触れられていたので，可視化してみようかと...子供の数に比べて高齢者の数が大きく減っていくのか...

# 感想

* superset自体の扱いは簡単．
* 国勢調査の結果は，どれを使えばいいのか最初は結構迷った（例えば特定の都道府県の人口推移が，別ファイルになっているのかと思いきや，時系列でまとめられたファイルがあったので．インタフェースがリニューアルされたことで解消されているのか？）


# まだできていないこと

* 日本地図へのmapping．[ここ](https://superset.incubator.apache.org/visualization.html#country-map-tools)を参考にすればいいのかな．