OmniAICreator/Qiita-1.07M huggingface dataset:
Kotlinのasync/awaitをカジュアルに使う話


Kotlinの1.2.xではまだexperimentalだけど、1.3で正式導入予定のCoroutine、特にasync/awaitはAPI呼び出しなどの非同期な処理に便利そうです。

ただ、AndroidのActivityやFragmentにはライフサイクルがあって、Activityが破棄されたあとにViewをいじったりすると例外が発生してしまうという問題があります。

その辺のことをまじめに考えずに、非同期処理を書いてしまっったら、上記の問題はどうなるのでしょうか？

結論を言ってしまうと、適当に書いても問題なさそうです。

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    companion object {
        const val TAG = "MainActivity"
    }

    private val button by lazy { findViewById<TextView>(R.id.button) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button.setOnClickListener {
            Log.d(TAG, "clicked")
            launch(UI) {
                // coroutineからでないとsuspendedなメソッドを使えない（コンパイル時にエラー）
                Log.d(TAG, "clicked - launch")
                onPressed()
            }
            Log.d(TAG, "clicked - finish")
            finish()
            Log.d(TAG, "clicked - finished")
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "destroy")
    }

    private suspend fun onPressed() {
        Log.d(TAG, "pressed")
        val v = async {
            Thread.sleep(5000)
            Log.d(TAG, "pressed - wake up")
            System.currentTimeMillis().toString()
        }
        Log.d(TAG, "pressed - before await")
        button.text = v.await()
        Log.d(TAG, "pressed - after await")
    }
}
```

こんなActivityを書いて、実行してみます。

onPressed()は、suspend（つまり一旦中断される事がある）で、かつ、UIをいじるメソッドなので、launch(UI)内で使うことになります。

onPressed()内での処理は、確認のために遅延が起こればいいだけなので、5秒スリープしてから、ボタンのキャプションを書き換えるようにしました。

さらに、button.setOnClickListenerでは、onPressed()の終了を待たずに、finish()します。
あと、開発者オプションで、アクティビティを保持しないようにしておけば、Activityが破棄されたあとに、Viewの書き換えが起こるはずです。

そのときのログは、こんな感じになりました。

```
D/MainActivity: clicked
D/MainActivity: clicked - finish
D/MainActivity: clicked - finished
D/MainActivity: pressed
D/MainActivity: pressed - before await
D/MainActivity: destroy
D/MainActivity: pressed - wake up
D/MainActivity: pressed - after await
D/MainActivity: clicked - launch
```

onDestroyのあとにViewをいじっても、エラーにならないんですね。

ちょっと気持ち悪い感じがしないでもないですが、async/awaitを使った非同期処理は、Activity等のライフサイクルを考えずに、つかってもよしなにしてくれると思っていいみたいです。
CiscoのRouterとSwitch1台とPC2台を使ってVlan間ルーティング

#1:ネットワーク構成図
![構成図.png](https://qiita-image-store.s3.amazonaws.com/0/230465/c83701e1-e503-70ce-0574-7076689c8794.png)

#2:用意する機材等
・ルーター1台
・スイッチ1台
・LANケーブル4本
・コンソールケーブル1本
・PC2台(win機)

#3:RouterとSwitchの初期化
既存の設定を初期化
`enable`で特権モード
`erase startup-config`でNVRAM上のコンフィグを削除
`reload`で再起動する

#4:Routerの設定
###interface g0/0の設定
ログイン後にまずは`enable`で特権モード
`configure terminal`でグローバルコンフィグレーションモード
`int g0/0`でインターフェースコンフィグレーションモードへ
`ip address 192.168.1.254 255.255.255.0`でipの設定
`no shutdown`で有効化
`exit`で戻る

###interface g0/1の設定
ログイン後にまずは`enable`で特権モード
`configure terminal`でグローバルコンフィグレーションモード
`int g0/0`でインターフェースコンフィグレーションモードへ
`ip address 192.168.2.254 255.255.255.0`でipの設定
`no shutdown`で有効化
`exit`で戻る

#5:Switchの設定
###vlan10にinterface f0/1とf0/2を設定
ログイン後にまずは`enable`で特権モード
`configure terminal`でグローバルコンフィグレーションモード
`vlan 10`でvlan10を作成
`exit`してからvlan10にf0/0を設定する
`interface f0/1`にして`switch mode access`して
`switch access vlan 10`で設定する
`no shutdown`で有効化
`exit`で戻る

`interface f0/2`にして`switch mode access`して
`switch access vlan 10`で設定する
`no shutdown`で有効化
`exit`で戻る

`save`して`write memory`して設定を保存する

###vlan20にinterface f0/3とf0/4を設定
ログイン後にまずは`enable`で特権モード
`configure terminal`でグローバルコンフィグレーションモード
`vlan 20`でvlan20を作成
`exit`してからvlan20にf0/3を設定する
`interface f0/3`にして`switch mode access`して
`switch access vlan 20`で設定する
`no shutdown`で有効化
`exit`で戻る

`interface f0/4`にして`switch mode access`して
`switch access vlan 20`で設定する
`no shutdown`で有効化
`exit`で戻る

`save`して`write memory`して設定を保存する

#6:pingで疎通確認
win機を2台用意してから、機内モードにし、win機のコントロールパネルからそれぞれに固定ipを割り振る
pcAに192.168.1.5
pcBに192.168.2.5
を振る

ここで疎通を通すのに一番重要なことがwin機はファイアフォールがONになっていると疎通が通らないので、
コントロールパネルからファイアフォールを全てOFFにする。
**疎通確認が終わったら必ずONに戻すこと!!!**
pcAでコマンドプロンプトを開き、`ping 192.168.2.5`をして、疎通できていることがわかる
Edankeun waaa

I really enjoy simply reading all your weblogs. Simply wanted to inform you you have people like me who appreciate your work. Certainly a great publish. The information that you have provided is truly very valuable
http://www.pengobatanlukadiabetesgangren.com/
http://caraalamimelangsingkantubuh.com/
http://obatasamuratterbaik.com/
http://caramengobatisinusitissecaralami.com/
http://obatmataminusherbal.web.id/
http://www.obatkolesterolterbaik.com/
http://obatherbalasma.web.id/
http://vitaminpenambahnafsumakananak.web.id/
http://obatamandel.web.id/
http://obatgondokberacun.web.id/
http://www.pengobatanhidrosefalus.net/
Google Apps Script 用 Slack API ライブラリ作った



### tl;dr
Slack APIのGoogle Apps Script用ラッパーライブラリを作って公開した。
Pythonの人気ライブラリSlackerとおおよそ同様のことができ、これを使うことでSlackのbotなどを無料で作りやすくなった。

レポジトリ：https://github.com/yhay81/GASlacker


## 経緯
Slackでボットを作ろうと思いドキュメントを読んだら[Botkit](https://www.botkit.ai/)というのを[オススメされていた](https://api.slack.com/bot-users#botkit)がややこしいと思った。

サーバー管理不要かつ無料で作りたいと思い Google Apps Script に目をつけた。
ライブラリは[公式にたくさん紹介](https://api.slack.com/community)されていた。が、Google Apps Script用のものはなかった。

Qiita記事「[Slack BotをGASでいい感じで書くためのライブラリを作った](https://qiita.com/soundTricker/items/43267609a870fc9c7453)」を見つけた。
CoffeeScriptで書かれたこのライブラリは簡単な用途で使う分には問題なさそうだったが、最終更新が3年前で最新のSlack APIに追随できていなかったので、もしかすると需要あるかもと思い、自分なりにライブラリから作ることにした。

ちょうどGASをローカルで開発しやすくする「[google/clasp (GitHub)](https://github.com/google/clasp)」というものが最近登場していて、それにも興味があった。

さらにQiita記事「[Google Apps Script をローカル環境で快適に開発するためのテンプレートを作りました](https://qiita.com/howdy39/items/0e799a9bfc1d3bccf6e5)」を見つけて、TypeScriptでかける準備が整っていたので、TypeScriptで書くことにした。

slackのAPIは`https://slack.com/api/chat.postMessage`というようなアクセスポイントにGETやPOSTを投げるのだが、`chat.postMessage`の部分がメソッドによって変わる。GASのPythonインターフェース「[os/slacker (GitHub)](https://github.com/os/slacker)」はそこで`slacker.chat.postMessage(引数)`という記法でAPIにアクセスできるようになっていて、いけてると思ったので真似た。

詳しくはこちら。[Slack API Document](https://api.slack.com/methods)

## 使い方

https://drive.google.com などから Google Apps Script を新規作成(ライブラリ用にする)。
dist/bundle.jsの内容を丸々コピペして保存し、`公開＞実行可能APIとして導入`をして、API IDを発行し、コピーしておく。

Google Apps Script をさらにもう一つ新規作成(自分のアプリ用にする)。
Resourcesタブに、Libraries...というのがあるので、それに先ほどのAPI IDを書くと、`GASlacker`という変数が使えるようになる。
あとは、こんな感じ。

```JavaScript
var token = 'xoxb-34...みたいなトークン';
var slack = GASlacker.methods(token);

function doPost(e){
  var event = JSON.parse(e.postData.contents).event;
  if(event.text.match(/hello/)){
    var text = "Hello," + event.message.username;
    slack.chat.postMessage(event.channel, text);
  }
}
```
GASlackerは唯一のメソッド`methods`を持っている。これにトークンを渡すと、オブジェクトが作られ返される。このオブジェクトを起点に[API methods](https://api.slack.com/methods)名を指定することでAPIにアクセスすることができる。

doPostはGASの特別な関数で、GASにPostが送られてきたときに動作する。GASをWebアプリとして公開して、Slackに権限を適切に設定して登録しておくと送られてくるようになる。

このサンプルはメッセージがSlackで書かれたときに、Postされるようにした場合のもの。eにいろんな情報が入っているので、うまいこと処理して、slack.chat.postMessageに引数として渡すと、自動でメッセージが送信される。

[Slack API Document](https://api.slack.com/methods) を見るとわかるが、引数には必須のものと、オプションのものがある。
Tokenはほぼ全てに必須だが、これはGASlackerでは書く必要がない。
必須のものは、GASlackerでも必須で、オプションのものは飛ばすことができる。さらにドキュメントにない変数を渡すときは`extraArgs`という変数にPOJOで渡す。

## まとめ
APIの量が多くて全てを実装するのは結構大変だった。

今回のものは、Slack APIをそのまま扱うだけのものだが、もっといい感じにラップして、botを作るためだけのライブラリにもできたらいいなと思った。

需要があれば、というところなのでこのライブラリが使えそうだと思った方いれば、スターお願いします。https://github.com/yhay81/GASlacker

## 補足
[このMedium](https://medium.com/@yusuke8h/easy-slack-bot-from-google-apps-script-82065b5e08f7)でGASでのSlackBotの作り方を０から説明してみた。
英語だがほぼ画像で、このQiitaで説明していない、SlackのToken取得部分も説明してます。
非エンジニアにとっては、GASを使うこの方法がもっとも簡単なSlackbotの作り方なのかなと思う。GASlackerも使っておらずできるだけシンプルにしました。
CakePHP2.x ファイルアップロード時に画像のロスレス圧縮

## はじめに
WEBコンテンツのシステムに携わるとSEO対策は必須なわけで
CMSを導入しているシステムでは画像のアップロードをCMS上から行うというのも普通で
今後自分でも使う場面が多そうなので備忘を兼ねて残します。

## 環境
AWSのLinux
PHP 5.6
jpegoptim
optipng

## 準備
圧縮で使用するためにjpegoptimとoptipngをサーバ上にインストールします。

```
yum -y install libjpeg
yum install --enablerepo=epel jpegoptim optipng
```

### Component作成

```ImageCompressComponent.php
<?php

App::uses('Component', 'Controller');

class ImageCompressComponent extends Component {

    private $_jpegQuality = 80;
    private $_pngQuality = 2;

    public function setJpegQuality($val) {
        $this->_jpegQuality = $val;
    }

    public function setPngQuality($val) {
        $this->_pngQuality = $val;
    }

    /**
     * 圧縮の実行
     * @param type $file 圧縮を行うファイルの情報
     */
    public function compress($file) {
        if ($file["error"] != 0) {
            return false;
        }
        switch ($file['type']) {
            case 'image/png' :
                $command = "/usr/bin/optipng -strip all -o{$this->_pngQuality} ";
                break;
            case 'image/jpeg' :
                $command = "/usr/bin/jpegoptim -m{$this->_jpegQuality} -o --strip-all ";
                break;
            default :
                //圧縮に対応していない形式
                return false;
        }

        exec($command . $file["tmp_name"], $msg, $status);
        if ($status != 0) {
            return false;
        }

        return true;
    }

}

```

後はComponentをController側から使用するだけです。

``` hogeController.php
$this->ImageCompress->compress($image);
```

これをAWSのS3バケットにアップする前に圧縮を行うことで、圧縮した画像をS3に保存することができました。

### 参考文献
実装にあたりこちらのサイト様を参考にさせていただきました。
[a-blog cmsで画像のロスレス圧縮をする | a-blog cms | Web雑記帳](https://atsu666.com/ablogcms/entry-88.html)
flow type 書き方の雑メモ

### react routerのpathから貰ったパラメータ値の型

文字列として貰っているので、その辺のパラメータの型定義も`string`にする。

### Objectキーが変数の場合の型定義

```javascript
let var1 = 'key1';
let var2 = 'key2';
let myMap: { [string | void]: string } = {};
myMap[key1] = 'value1';
myMap[key2] = 'value2';
```

### react componentのインスタンス変数の型

```javascript
export default class MyComp extends Component {
    hoge: string;

    constructor() {
        this.hoge = null;
    }

  componentWillMount() {
    this.hoge = 'abc';
  }
}
```

### setIntervalとsetTimeoutの戻り値の型

```javascript
const foo: TimeoutID = setTimeout(() => {}, 300);
const bar: IntervalID = setInterval(() => {}, 300);
```
GitHubへssh接続できるようにする

ssh鍵を作成し、公開鍵をGitHubへ登録するまでの作業メモ

## ssh鍵の作成
暗号化方式：RSA、鍵ファイル名：github(自分の好きな名前)を生成。
passphraseを設定すると毎回のssh接続時に入力が必要。
ファイル名を指定しない場合、デフォルトのid_rsa、id_rsa.pubに
なるので、既に存在している場合は上書きに注意！

```
$ ssh-keygen -t rsa -f ~/.ssh/github
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again:
```

他の暗号化方式とかを知りたい場合は、下記参考。
・[GitHubユーザーのSSH鍵6万個を調べてみた](http://d.hatena.ne.jp/hnw/20140705)

## GitHubへ公開鍵を登録
https://github.com/settings/keys
から、公開鍵を登録。

![スクリーンショット 2018-03-23 15.28.25.png](https://qiita-image-store.s3.amazonaws.com/0/244705/a66e7338-adb4-02d1-c024-b26f29664cf3.png)

まずは、公開鍵の値をクリップボードにコピー。

`pbcopy < ~/.ssh/github.pub` ・Macの場合
`cat ~/.ssh/github.pub | xsel -bi` ・Ubuntuの場合。※インストールが必要かも。

好きなTitleを入力し、
コピーした公開鍵をKeyにペースト、
Add SSH keyで登録。
![スクリーンショット 2018-03-27 17.58.50.png](https://qiita-image-store.s3.amazonaws.com/0/244705/f14e5e4d-c1f4-9cba-19f1-57142fbe854d.png)

## 疎通確認
```
$ ssh -T git@github.com -i ~/.ssh/github
Hi XXXX You've successfully authenticated, but GitHub does not provide shell access.
```

## SSHのConfig設定
毎回ユーザ名とかの指定がめんどい場合、configにエイリアスを設定しておくと楽。

```~/.ssh/config
Host github github.com
    HostName     github.com
    IdentityFile ~/.ssh/github
    User         git
```
webpack4に更新した時にこけた所まとめ

webpackをv3.10.0からv4.3.0に更新したら色々とこけたのでそのまとめです。

参考記事　（チュートリアル?）
https://www.valentinog.com/blog/webpack-4-tutorial/　　

## webpack-cliの追加
__結果__　

```
The CLI moved into a separate package: webpack-cli.
Please install 'webpack-cli' in addition to webpack itself to use the CLI.
-> When using npm: npm install webpack-cli -D
-> When using yarn: yarn add webpack-cli -D
```

__原因__
webpack4からwebpack-cliが必要になった模様

__解決法__
webpack-cliを追加

```
yarn add --dev webpack-cli
```

## webpack.config.js修正
__結果__

```
✖ ｢wds｣: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration[0].module has an unknown property 'loaders'. These properties are valid:
   object { exprContextCritical?, exprContextRecursive?, exprContextRegExp?, exprContextRequest?, noParse?, rules?, defaultRules?, unknownContextCritical?, unknownContextRecursive?, unknownContextRegExp?, unknownContextRequest?, unsafeCache?, wrappedContextCritical?, wrappedContextRecursive?, wrappedContextRegExp?, strictExportPresence?, strictThisContextOnImports? }
   -> Options affecting the normal modules (`NormalModuleFactory`).
 - configuration[1].module has an unknown property 'loaders'. These properties are valid:
   object { exprContextCritical?, exprContextRecursive?, exprContextRegExp?, exprContextRequest?, noParse?, rules?, defaultRules?, unknownContextCritical?, unknownContextRecursive?, unknownContextRegExp?, unknownContextRequest?, unsafeCache?, wrappedContextCritical?, wrappedContextRecursive?, wrappedContextRegExp?, strictExportPresence?, strictThisContextOnImports? }
   -> Options affecting the normal modules (`NormalModuleFactory`).
error An unexpected error occurred: "Command failed.
```

__原因__
webpack.config.jsの書き方変わった（？）

__解決法__
webpack.config.jsのlodersをrulesに変更

```javascript:webpack.config.js
module: {
      rules: [{
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['react', 'es2015'],
        },
      }],
    },
```
## option --modeの追加
__結果__

```
WARNING in configuration
    The 'mode' option has not been set. Set 'mode' option to 'development' or 'production' to enable defaults for this environment. 
```

__原因__
productionとdevelopmentを分けられるオプションのmode設定が必要

__解決法__
--mode development --openを追加

```json:package.json
"scripts": {
  "start": "webpack-dev-server --mode development --open"
},
```
Google Apps ScriptでGoogleカレンダーからタイムスケジュールを作成してみた

# はじめに

- 仕事をする上で、日々のタイムマネジメントは基本的でもありますがとても重要なことです。
- ただ、業務は日々変わるものですし、たくさんの業務を抱えているとタスクの優先度や時間管理が疎かになり、不透明さが増してしまったりします。
- そこで、今回は日々のタスクをGoogleカレンダーに登録された予定からタイムスケジュールを作成するスクリプトを作ってみました。
- 作成されたスケジュールを元に、タスクや時間管理が見える化されることにより落ち着いて業務をこなせるようになればと思っております。

> [タイムマネジメントとは](https://bizhint.jp/keyword/62361)

# 準備すること

1. Googleカレンダーに2週間以内の予定を設定してください。

2. [タイムスケジュールマスタ](https://docs.google.com/spreadsheets/d/1olq_YEKi6Ckv6iIUKGDBa7JMYnJQ2BekKXIEBydLXsE/edit?usp=sharing)を開き、「ファイル > コピーを作成」からドキュメントを作成してください。

3. [Google Apps Script](https://github.com/neriai/time-scheduler)を開き、categorizeSchedule.gsおよびtimeSchedule.gsをファイルごとコピーしてください。

4. １のコピーしてきたスプレッドシートの「ツール > スクリプトエディタ」を開き、２のGoogle Apps Scriptを作成してください。

# タイムスケジュールマスタの各シートについて

## スケジュール設定

スケジュールの開始日と終了日を設定します。
シート上のボタンをクリックすることにより、スケジュールの作成を実行します。

## カテゴリ設定

スケジュールの予定に特定のキーワードが含まれている場合に、このシートで予め設定されたラベル名と色にスケジュールの予定を変換します。

## スケジュール

スケジュールが生成されるシートです。

## 工数内訳

各タスクの合計値や工数を算出するシートです。
GoogleAppsScriptなどとの連動はしていないのであくまでオプションとなっております。

## 祝日一覧

スケジュールシートに祝日を反映させるための祝日のマスタです。

# Google Apps Scriptの各スクリプトについて

## categorizeSchedule.gs

予め設定されたカテゴリを特定のキーワードに基づいてスケジュールの予定を置換し、セルの色付けを行います。

## timeSchedule.gs

Googleカレンダーからスケジュールを取得し、各セルに挿入しています。
基本的に３０分区切りなのではまるめていたりします。
Googleカレンダーのログインユーザのスケジュールを取得しています。
予定が２つ以上の部分は赤い色のセルでコンフリクトを表示しています。

# 注意点

- シート名やシートのフォーマットを変更すると正常に動作しない可能性があります。
- GoogleAppsScriptは、実行時間に５分以上かかるとタイムアウトエラーとなります。もし、発生した場合は再度実行していただくか、スケジュール期間を短くしてください。
- もし、シートのボタンから正常に実行できない場合は、スクリプトの紐付けが外れている可能性があります。紐付けしなおしていただくか、スクリプトエディタの実行ボタンから実行してください。
- ソースコードがところどころイケていないですが、ご了承ください。

# 実行イメージ

## スケジュールの作成

![FireShot Capture 013 - タイムスケジュール - Google スプレッドシート_ - https___docs.google.com_spreadshee.png](https://qiita-image-store.s3.amazonaws.com/0/90598/3942bd4e-1458-2738-50ef-108f472d02c3.png)

> LOとはleave office（退社）

## カテゴライズ

![FireShot Capture 014 - タイムスケジュール - Google スプレッドシート_ - https___docs.google.com_spreadshee.png](https://qiita-image-store.s3.amazonaws.com/0/90598/c6791bf4-98ce-1d78-691d-68df501848f8.png)


# まとめ

- 今回、はじめてGoogleAppsScriptを使ったコーディングを行ったが、JavaScriptとセル操作に関する関数を覚えれば良いだけなので馴染みやすかった。
- 実行時間を工夫する上で１セルではなく１行もしくは１列毎に予めデータを整形したあとにシートに挿入するのが早いのかもしれない。
- あまり継続して使うのかどうか怪しいがGoogleカレンダーの予定とズレが生じないのでこれはこれで個人的には満足。

# 外部参照

タイムスケジュールマスタ
- [スプレッドシート](https://docs.google.com/spreadsheets/d/1olq_YEKi6Ckv6iIUKGDBa7JMYnJQ2BekKXIEBydLXsE/edit?usp=sharing)

Google Apps Script
- [Github](https://github.com/neriai/time-scheduler)
nil empty blankの違い

nil、empty、blankの違いについて、いつも混乱するのでまとめました。

## nilは何も存在しない
器も中身も本当何もない状態
逆に""は、`空白が存在する`という意味になる。

## nil?

```ruby
user.nil?
```

userという器も中身も何も存在しなければ、`true`を返す

## emptyは器はあるけど、中身がない
器に何も入っていない状態。

## empty?

```ruby
book.empty?
```
bookという器はあるけど、中に何も入っていない状態
bookという器がなければ、エラーになる。
文字列の長さが0のとき、配列が空のときにtrueを返す。
数値には定義されていない。
へえ〜、知らなかった。

## blank?
器が存在するか中身が入っているかを確認
nil?とempty?を合体させたメソッド、という感じ
`nil, "", " ", [], {}` のいずれかでtrueを返す。
Actions On Goolgeのユーザー情報リセット

# Actions On Goolgeのユーザー情報リセット

Actions On Googleのベストプラクティスでは、初回ユーザーかそうでないかによって起動時の文言を変えようと言うものがあります。
[Welcome users differently when they return | General Best Practices](https://developers.google.com/actions/assistant/best-practices#welcome_users_differently_when_they_return)

それを実装してみたもののどうやってテストしたらいいんだという人のためのメモです。

#### 手順
1. app directoryを開いて、ユーザー情報を消したいアプリを選択する。
<img width="375" alt="IMG_3A921DCDD490-1.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/127708/0c94cf4e-2325-0453-a16b-e7b03a2ea08f.jpeg">

2. 下の方にスクロールして、「アプリをリセット」を押下。
<img width="375" alt="app-reset2.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/127708/1466892f-06f6-6af8-41bd-0efcf0eb3658.png">


3. 確認ダイアログが出てくるので、「リセット」を押下。
<img width="375" alt="app-reset3.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/127708/3e454413-a74b-7644-cdb0-5eadb832ead7.png">
Tableauのアカウント周りを説明する時のためにざっくり整理してみました

##概要
自分の周りでもTableauを使ってるメンバーが増えてきて嬉しい限りなのですが、
「Tableauのトレーニングビデオ見るために登録いるの？」「Customer Portalって何？」「Tableau OnlineのID、パスワードって何入れればいいの？」的なところの全体像がまとまってると嬉しいなーと思ったのでそれをまとめていこうかなと思います〜。

##全体像（ざっくり）
言ってしまうと、ここにざっくり書いてあるじゃんという話です。
https://www.tableau.com/sso-login
![Tableau ID - サインイン 2018-03-28 12-22-39.png](https://qiita-image-store.s3.amazonaws.com/0/195690/ade629f9-9f59-ff47-8621-29aa79a14889.png)


これをもうちょっと全体像っぽくするとこんな感じになるかと。
![Tableauのアカウント周り整理 - Google Slides 2018-03-28 13-59-08.png](https://qiita-image-store.s3.amazonaws.com/0/195690/5d4c7e04-7104-02d3-913d-1e51e2b79ba6.png)



ということで、
1. まずはアカウントを作成しましょう！https://id.tableau.com/register
2. そして、このアカウントはTableau関連のあれこれで使えるのか〜ということを知っておきましょう！
　　・[Tableau Public(ギャラリー)](https://public.tableau.com/ja-jp/s/gallery)
　　・[Tableau Customer Portal](https://customer.tableausoftware.com/)
　　・[Knowledge Base](https://www.tableau.com/support/knowledgebase)


このページにきた多くの方は既にアカウント作成は完了しているのではないかと思いますので、
Tableau関連のあれこれで使えるのか〜というところを心に刻みましょう！
WSL上のemacsで選択した文字列をWindows側のクリップボードに飛ばす方法

WSL上のemacsの内容をWindows側にコピペする方法としては、マウスカーソルで範囲を選択してCtrl-Cするという方法があります。
ただ、やはり範囲選択はemacs上で行ないたいのが人情というもの。

```emacs-lisp
(defun wsl-copy (start end)
  (interactive "r")
  (shell-command-on-region start end "clip.exe"))

(global-set-key
 (kbd "C-c C-c")
  'wsl-copy)
```

これをinit.elなりに書いておけば、C-c C-cでemacs側の選択範囲がwindows側のクリップボードに登録されます(上のコードもそれを使って持ってきました)。

仕組みとしては、WSL上で`clip.exe`というコマンドに入力された内容がそのままクリップボードに登録されるのを利用しています。
他の事例では特定のコマンドの出力をクリップボードに飛ばすのに以下のようにすることができます。

```sh
hoge.exe | clip.exe
```


[このページ](http://www.clear-code.com/blog/2017/11/8.html)と[このページ](https://www.reddit.com/r/emacs/comments/6xryqh/emacs_in_wsl_and_the_windows_clipboard/)を参考にしました。
matplotlib

#matplotlibとは
pythonでグラフを書くときに使うライブラリである。

##使い方
1.まずインポート
```import matplotlib.pyplot as plt```

2.plot関数にデータを渡す。
```plt.plot(x, y)```
xに入るのがｘ軸のデータ
yに入るのがｙ軸のデータ

3.グラフを出す
```plt.show()```

##実践
***折れ線グラフ***
右肩上がりになるように折れ線グラフを表示してみましょう。
```x = [1,2,3,4,5]```
```y = [1,3,6,9,10]
plt.plot(x, y)
plt.show()```
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/239684/0a98ca37-2e53-8748-0c7c-2ae6736d0cb9.png)

***分布図***
先ほどの```plt.plot(x, y)```を```plt.plot(x, y,"o")```に変える。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/239684/bd8015ba-d06d-0463-c72c-b9c42acbc1d6.png)
Mac + Docker + Laravel の開発環境下で、異常に遅い時は Laravel Debugbar が原因な説

標題の開発環境下で、異常に遅かったので調べてみた。

結論としては、 `Laravel Debugbar` を無効にすると **3倍近く** 速くなった。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103885/ac4d4abf-e6d7-b2a2-568a-27740cc76298.png)

レスポンスタイムが 2.6秒 → 0.85秒 なので3倍くらい。

# 考えられる要因

Laravel Debugbar は、 `storage/debugbar/` 以下に `Xc590ef0f5b368cf34373093291b95147.json` のようなファイルを **リクエストの度に** 出力するようだ。

```
~> find storage/debugbar -type f | wc -l
      58
```

中身を確認すると、スタックトレースなどが入っている。

`/api` などはミドルウェアなどが多いので、そのファイルのサイズが異常に大きくなる。整形すると **24000行** ものファイルを作っている。

```
~> cat storage/debugbar/X2e75040e69de9cae006253a48fd5276c.json | jq . | wc -l
   24676
```

今回出力されたファイルサイズは **500KB** だった。

```
~> ls -lh storage/debugbar/X2e75040e69de9cae006253a48fd5276c.json
-rw-r--r--  1 kazuya-mac  staff   508K  3 27 18:32 storage/debugbar/X2e75040e69de9cae006253a48fd5276c.json
```

で、Mac上でDocker動かすと、ファイル書き込み処理が重くなるのは有名な話。

よって、このログ出力をやめるだけでもかなりの速度改善になる。

# TODO

Laravel Debugbar 自体は使いたいので、パフォーマンス改善される方法を探す。
下記のいずれか、かなと。

- HTTP経由でどこかに飛ばす
- ログの出力先を共有ボリューム以外の場所にする
- `storage/` 以下を `volume` でマウントしない（Dockerで部分的にマウントしないことができるのか・・？）

Debugbar 以外でも、ログ出力先を共有ボリューム以外にすれば、高速化できるかもしれない。

# 余録

これ便利。

```bash:speedtest
#!/usr/bin/env fish

while true
    curl -H 'Accept-Encoding: gzip' -Ss -LI -o /dev/null -w \
        '%{http_code} in %{time_total} seconds, %{content_type} as %{size_download} \n' \
        $argv
    sleep 1
end
```
CloudFormationのデプロイ時の --parameter-overrides オプションの使い方

`aws cloudformation deploy` コマンドでデプロイする時に環境変数を使いたい。素直にはできないようなので `--parameter-overrides` で代用する。

# template.yml
以下のように`Parameters`を定義する。`TargetParameter`はパラメータ名なので自由に設定可能。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  TargetParameter:
    Type: 'String'
    Default: 'foobar'
...
```

参照は↓のように行う。

```yaml
...
  SomeEC2:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: !Ref TargetParameter
...
```

# deployコマンド
デプロイ時に以下のようにパラメータを指定する。

```bash
aws cloudformation deploy \
  --template-file template.yaml \
  --capabilities CAPABILITY_IAM \
  --parameter-overrides TargetParameter=ami-bec974d8 \
  --stack-name foobar
```
scrapydのキューをsqliteから確認する

# scrapydとは
scrapyをデーモン化し、APIでリクエストできるようになるOSSプロジェクト。
https://scrapyd.readthedocs.io/en/stable/
https://github.com/scrapy/scrapyd
# キュー
APIにリクエストされたキューは、sqliteに保持され順次実行される。APIを叩けば一覧を取得することは可能だが、件数が多くなるとAPIの結果(json)だと面倒なので、内部的に利用されているsqliteにクエリを投げる。
# sqliteログイン
```
sudo sqlite3 /opt/python/current/app/project/dbs/scraper.db
```
# クエリ
spider_queueにキューが格納されているので、クエリを投げることで確認できる。(64万件!)

```
sqlite> select count(*) from spider_queue;
640725
```
PythonによるFitbitAPIの始め方

# FitbitAPI
せっかくFitbitを持っているしAPI使ってなんかしたいなって思ったのでとりあえず導入

# 手順
## 1. [Fitbitのページ](https://www.fitbit.com/dev/dev)へアクセス
日本語ページがあるけど現状手順2からは英語ページに遷移する

## 2. 右上のアプリを登録をクリック
ログインする用に言われたら自分のアカウント情報を入力してログイン

## 3. 必要事項を記入する
注意すべき点は、

- OAuth2.0 Application Typeを`Personal`にする
- Callback URLを`http://127.0.0.1:8080/`にする

の二点
それ以外の項目は適当に埋めればOK

## 4. 必要な情報を控える
- 登録後に表示される**OAuth 2.0 Client ID**、**Client Secret**を控えておく
- direnv([参考](https://qiita.com/kompiro/items/5fc46089247a56243a62))などを用いて管理すると便利

## 5. Access TokenとRefresh Tokenの取得
- [python-fitbit](https://github.com/orcasgit/python-fitbit)を、以下のようににクローン

    ```bash
    $ git clone https://github.com/orcasgit/python-fitbit.git
    ```

- 4.で控えたClient IDとClient Secretを用いて以下を実行

    ```bash
    $ cd /path/to/python-fitbit
    $ ./gather_keys_oauth2.py 'your Client ID' 'your Client Secret'
    ```

- ブラウザが開くのでチェックボックスに必要な分だけチェックを入れて許可
- コマンドラインに戻ると`access_token`と`refresh_token`が表示されているので控える

#### ※「接続しようとしているアプリは Fitbit に有効なデータを提供しませんでした。この問題を報告してください。」と表示される場合
- MANAGE MY APPSから利用したいアプリケーションを選択（OAuth 2.0 Client IDなどが表示されているページ）
- `Edit Application Settings`を選択してCallback URLが`http://127.0.0.1:8080/`になっているか確認
- Callback URLを変更したい場合は[ココ](http://shima-nigoro.hatenablog.jp/entry/2016/05/29/181309)とかを参考に`python-fitbit/gather_keys_oauth2.py`ファイルを変更する必要あり

## 6. Pythonプログラムを書く
- 5までで取得した情報を利用してFitbitAPIを利用する
- 以下のようなプログラムを書けば歩数を取得することができる

```python

import fitbit


class FitbitApp(object):
    CLIENT_ID = 'your Client ID'
    CLIENT_SECRET = 'your Client Secret'
    ACCESS_TOKEN = 'your access token'
    REFRESH_TOKEN = 'your refresh token'
    
    def __init__(self):
        self.fitbit_client = fitbit.Fitbit(self.CLIENT_ID, self.CLIENT_SECRET,
                                           access_token=self.ACCESS_TOKEN, refresh_token=self.REFRESH_TOKEN)
    
    def get_steps(self, base_date, detail_level, start_time, end_time):
        steps_data = fitbit_client.intraday_time_series('activities/steps', base_date=base_date,
                                                        detail_level=detail_lebel, start_time=start_time, end_time=end_time)
        steps_dic_list = steps_date['activities-steps-intraday']['dateset']
        return steps_dic_list

if __name__ == '__main__':
    fitbit_app = FitbitApp()
    base_date = '2018-03-28'
    detail_level = '15min'
    start_time = '10:00'
    end_time = '15:00'
    steps_dic_list = fitbit_app.get_steps(base_date, detail_level, start_time, end_time)
```

- 他にどんなデータが取れるかは[ココ](https://qiita.com/fujit33/items/27d3f3142cf02bb46436)とかを参考に


## 参考
- [Pythonでfitbit APIから心拍数を取得してみよう！](https://qiita.com/fujit33/items/2af7c4afdb4e07601def)
- [Fitbit Charge HRの心拍数データを取得する - もみあげあしめ](http://shima-nigoro.hatenablog.jp/entry/2016/05/29/181309)
- [python-fitbit データ取得クエリまとめ](https://qiita.com/fujit33/items/27d3f3142cf02bb46436)
PhpStormにGoogleMapAPIの補完機能を入れる

# 概要
PhpStormにGoogleMapのスタブを読み込ませて、補完機能を有効にします。
快適なPhpStormライフを送るために。

# 手順
## ライブラリをダウンロード。
以下の`google_maps_api_v3.js`。バージョンについては後述。
https://github.com/google/closure-compiler/tree/master/contrib/externs/maps

## 読み込み
- [PhpStorm] > [Preferences] > [Languages & Frameworks] > [Javascript] > [Libraries] > [Add]を選択。

- 開いたウィンドウで左下の`+`をクリック。
- [Attach Files]を選択し、ダウンロードしたファイルを選択すると以下の画面へ。
![スクリーンショット 2018-03-28 12.40.12.png](https://qiita-image-store.s3.amazonaws.com/0/58712/7f11bc23-da27-19de-9685-672cfbbebf33.png)

- 以下の入力値を確認後、[OK]を押す。
    - Name: 適当に入力
    - Visibility： 現在のプロジェクトでのみ適用する場合は`Project`を選択
- 以下の状態で、`Enabled`にチェックが入っていればOK。
![スクリーンショット 2018-03-28 12.48.31.png](https://qiita-image-store.s3.amazonaws.com/0/58712/a64f55ce-15f4-305a-f14e-a81a2e8d01c2.png)

# 動作確認
## before
![スクリーンショット 2018-03-28 12.51.17.png](https://qiita-image-store.s3.amazonaws.com/0/58712/271e5738-ad9e-2ec7-9013-54bec5c1e8cd.png)

## after
![スクリーンショット 2018-03-28 12.51.34.png](https://qiita-image-store.s3.amazonaws.com/0/58712/dae70f93-4295-655f-02c3-ad0c70097964.png)

補完もバッチリ。
![スクリーンショット 2018-03-28 12.51.52.png](https://qiita-image-store.s3.amazonaws.com/0/58712/f93674c2-9bee-2d57-194f-24165b79948c.png)

# バージョンについて
以下のように`v=3`としてリリースバージョンで利用している場合は手順でダウンロードしているファイルで問題ありません。
個別指定している場合は、対応バージョンのファイルをダウンロードしてください。

```html
<script src="https://maps.googleapis.com/maps/api/js?v=3">
```

**※リリースバージョン指定の場合、バージョンアップごとに取得されるファイルが変化するので、ライブラリの読み込みも都度落とし直してこないといけない点に注意してください。**
Laravel5.5 ローカル環境を外部に公開

# 概要
開発環境を簡単に外部公開できる。Homestead環境ならね・・というお話。

# 環境
Laravel Homestead 7.3.0

# 公開の仕方

VM上のプロジェクトルートディレクトリで以下を実行

```cmd
# homestead.testは、Homestead.yamlに記載したsites.mapの値。
share homestead.test

# 実行すると以下のような出力がされる（ForwardingされているURLが公開URL）
Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.2.8
Region                        United States (us)
Web Interface                 http://192.168.10.10:4040
Forwarding                    http://ee2ee6e0.ngrok.io -> localhost:80
Forwarding                    https://ee2ee6e0.ngrok.io -> localhost:80

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```

# 用途
コールバックURLが必要な外部サービス（LINEとかTwilioとか）とローカル環境を連携したい（開発）時。
その他、開発以外のメンバーに触ってもらいたい時とか。

#蛇足
Laravel5.4からあるっぽい（ドキュメントに書かれてた）
デフォルトでngrokがインストールされてたからもしや！！と思ってググって行ったら、英語記事を経由して最後はドキュメントに辿り着いたorz
iOS8 App Crash "dyld: Symbol not found: ___NSArray0__"

## iOS8でアプリ起動時にクラッシュする問題が発生

iPhoneXやXcode9.2、iOS11.2など最新ばかり対応していて疎かになっちゃう、各サービスでサポートギリギリのiOS8で動作確認した時のことです。
　

```
dyld: Symbol not found: _NSArray0
Referenced from: /private/var/mobile/Containers/Bundle/Application/8B40C8BE-5816-495B-98BF-2E43A2B4009B/soundATM.app/soundATM
Expected in: /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
in /private/var/mobile/Containers/Bundle/Application/8B40C8BE-5816-495B-98BF-2E43A2B4009B/soundATM.app/soundATM
(lldb)

```
 
 　
上記のログは、[Crash on iOS on load "dyld: Symbol not found: ___NSArray0__"](https://github.com/zmxv/react-native-sound/issues/259)の一部から参照したものですが、どうもReact界隈でもここ1年以内に確認されているようですね。


## 調べてみた

**iOS 9.2 SDK以降でビルドする際に、iOS8もサポートしたいならCoreFoundation.frameworkを設定しないとクラッシュすることになっている**ようです。

* [iOS 8をサポートしているときにiOS 9 SDKを使用する](http://iphonedevwiki.net/index.php/Updating_extensions_for_iOS_9#Using_iOS_9_SDK_while_supporting_iOS_8)
* [CoreFoundation Changes for Objective-C](https://developer.apple.com/library/content/releasenotes/General/iOS90APIDiffs/Objective-C/CoreFoundation.html)
  * iOS9から追加された関数（もしかしたらこの辺がiOS8がサポートされる機能に何か関係するのかも）
    * - [CFURLCreate ストリングによって追加パーセントエスケープ（_：_：_：_：_を:)](https://developer.apple.com/documentation/corefoundation/1542665-cfurlcreatestringbyaddingpercent)
    * - [エンコーディングを使用してパーセントエスケープを置き換えることによってCFURLCreate 文字列を生成する（_：_：_：_ :)](https://developer.apple.com/documentation/corefoundation/1541974-cfurlcreatestringbyreplacingperc)


※[Apple Developer Forumsで検索してもちゃんとした回答が見つかりません](https://forums.developer.apple.com/search.jspa?q=dyld:%20Symbol%20not%20found:%20___NSArray0__)でした。


## まとめ

憶測に過ぎませんが、

> コンパイラの変更
>  > 64ビットデバイスにロードされた32ビットバイナリは、32ビットページサイズが4096バイトから16384バイトに変更されたため、実行できません。
>
> iOS 8をサポートしているときにiOS 9 SDKを使用する
> > `@ []`を使用している場合、iOS 8デバイスでクラッシュする可能性があります。これを修正するには、代わりに `[[NSArray alloc] init]`を使用してください。

と、[iOS 9の拡張機能のアップデート](http://iphonedevwiki.net/index.php/Updating_extensions_for_iOS_9)で解説されているため、**チップやデバイス性能にも関わっているのかもしれない。**
A8チップまでアーキテクチャが32ビット製だったようですが、A9チップから64ビット製のアーキテクチャとして大幅にアップグレードされています。

- [公式：Apple A9](https://ja.wikipedia.org/wiki/Apple_A9)
- [64ビットアーキテクチャ搭載A9チップ](https://apple-geeks.com/apple-a9-3186)
- [A8](http://www.wdic.org/w/ABBR/A8)
- [A9](http://www.wdic.org/w/SCI/Apple%20A9)

もしかすると**iOS8が入っているiPhoneSEやiPhone6sなどのA9以上のチップが搭載されたデバイスでは、このクラッシュする問題は起きないカモです。**（あ、そもそもそんな端末ないか笑

また、もしiOS9の頃から開発していたものでこれを確認された場合は、`@ []`が何なのかをちゃんと調べて、その内容が開発しているもので各バージョンの差分を追って、理論付する調査が必要かなとも思いました。
僕は、`@ []`が何なのかiOS Developerじゃないのでわかりません（もともとAndroid Developerだったもので笑
netdev メモ

MAC アドレス一覧を調べたい。しかし `ip` コマンドの出力をパースするのはダルすぎる。netlink をいい感じにパースできるコマンドを作るのも面倒だ。

sysfs を使おう。

```bash
for i in /sys/class/net/*/address; do
  echo $i && cat $i;
done
```

最近なら、こんなのでもいいかもしれない。

```bash
ip -j link | jq ".[]|{ifname,address}"
```
NAYA　memo　シーン描画に関するメモ

#自分用：シーン描画とその操作に関するメモ
###■部分ハイド
**[ビューパネルメニュー]＞[表示]＞[選択項目の分離]**
もしくは**Ctrl+１キー**（ショートカット）

- 任意の点、線、面いずれかを選択自他状態で行う。
- 選択部分以外が見えなくなる。
- Ctrl+Shift+Iキーで反転

###■バックサーフェスカリング
**1. [アトリビュートエディタ]＞[メッシュコンポーネントディスプレイ]＞[バックフェースカリング]**
**2. [ディスプレイ]＞[ポリゴン]＞[バックフェースカリング]**
**3. [ビューパネルのシェーディング]＞[バックフェースカリング]**

- ポリゴンの裏面のON/OFF
- 1と2は同じ（連動している）。ディスプレイに関するカリング。
- 3はシェーディングに関するカリング。
- レンダリング時は関係無いので注意。
- （レンダリングで両面表示したい場合は　**[アトリビュートエディタ]＞[シェイプ]＞[レンダリング詳細]＞[両面]をONにする**)

###■情報表示
**[ディスプレイ]＞[ヘッドアップディスプレイ]＞[ポリゴン数]**

- 画面左上にポリゴン、エッジ、頂点の情報が出る。 

###■描画クリップ
**カメラを選択＞[アトリビュートエディタ]＞[カメラアトリビュート]＞[ニアクリップレーン/ファークリップレーン]**

- オブジェクトが大きすぎたり、小さすぎたりするときに数値を調整する。
    - ニア＞どこまで近くを描画するか値
    - ファー＞どこまで遠くを描画するかの値
    
###■カメラのスケール 
**カメラを選択＞[アトリビュートエディタ]＞[カメラアトリビュート]＞[カメラのスケール]**

- オブジェクトが大きすぎたり、小さすぎたりするときに数値を調整する。
    - マウス操作おけるカメラの移動量に掛ける係数。

###■カメラベース選択 
**選択ツール＞[ツール設定]＞[共通の選択範囲オプション]＞[カメラベース選択]**

- 裏面の選択を無効にするオプション
    - 見えている部分のみ囲い選択する時などに有用。
技適でないPCボードのWi-Fi等を使う方法

# はじめに
Raspberry PI 3 model B+ のように、Wi-Fi, BlueTooth Low Energy等の無線機が載っていて、かつ技適マークがない（執筆当時）ボードはソフトウエア設定で、電波を出さないようにしても、電源を入れれば電波法違反だという。何とか対策はないものか？
私が[総合通信相談所　03-6238-1940](http://www.soumu.go.jp/soutsu/kanto/ques/faq/ques/)に電話して聞いてみました。

# やり取り
＃マイコンボードに技適非対応のWi-Fi等の無線機が載っている場合、電源を入れると電波を出してなくても違法になるというのは間違いありませんか？
＄無線局の開設に当たるので違法です。
＃アンテナパターンを切断したらどうなるでしょう。
＄アンテナをとっても電波は出ますので違法です。
＃ターミネートしたらいかがですか？
＄ターミネートしても電波が出るので違法です。
＃アンテナを取ったり、ターミネートすれば出力はかなり小さくなりますが。
＄小さくなっても電波は出ます。
＃[微弱無線局](http://www.tele.soumu.go.jp/j/ref/material/rule/)の範疇まで弱くなればどうでしょう。
＄使用周波数帯はどこでしょう。
＃2.4GHz帯と5GHz帯です。
＄電界強度はどれくらいでしょう。
＃35μV/m (3m法)以下です。
＄それは微弱無線局で合法です。
＃先に言った「アンテナを外す」、「出力を終端する」いずれの方法でも電波出力が微弱無線局の要件を満たせば違法ではないという事ですね。
＄はいそうです。
＃お名前頂けますか？
＄木上です。
＃木上様ありがとうございました。

# 結論

- Wi-Fi搭載技適非対応ボードは電波を出さなくても電源を入れると電波法違反。
- アンテナを外す、終端する等で電界強度が35μV/m (3m法)以下になるよう改造すれば適法。
AWS CLIでEC2のインスタンスタイプを参照する

#なにができるか
アカウントにある全EC2インスタンスのインスタンスIDとインスタンスタイプが参照できます。

##ユースケース例
インスタンスタイプの変更を行う際に変更前後の状態を確認する際に使います。

##AWS CLIコマンド
```
aws ec2 describe-instances --query 'Reservations[].Instances[].{INSTANCE_ID:InstanceId,INSTANCE_TYPE:InstanceType}'
```

##AWS CLIコマンド説明
###INSTANCE_ID
変更可です、インスタンスIDを表示する際の見出しになるので分かりやすい名前にしましょう。

###InstanceId
変更不可です、インスタンスIDを表示するために必要です。

###INSTANCE_TYPE
変更可です、インスタンスタイプを表示する際の見出しになるので分かりやすい名前にしましょう。

###InstanceType
変更不可です、インスタンスタイプを表示するために必要です。

#あとがき
タグ名も一緒に表示できたほうが便利だと思うので別途試したいと思います。

#追記
人に見せる場合はjsonではなくtable形式で出力したほうが見やすいかもしれませんね。
###table形式出力オプションを付与したコマンド
```
aws ec2 describe-instances --query 'Reservations[].Instances[].{INSTANCE_ID:InstanceId,INSTANCE_TYPE:InstanceType}' --output table
```
さくらインターネットのレンタルサーバー(スタンダード)でsinatra2を使う

# はじめに
　諸事情により、さくらのレンタルサーバーでsinatraを使おうとしたのですが、web上の同種の情報が大分古く、そのままでは動かなかったので、備忘も兼ねて記録します。シェルはbashを使います。

# 環境
                          | バージョン
--------------------------|---
ruby                      | 2.4.3
rbenv                     | 1.1.1
sinatra                   | 2.0.1

# 手順

1. 準備。__rbenv__と__ruby-build__をダウンロードする。

    ```bash
    $ mkdir local
    $ cd local
    $ mkdir bin
    $ git clone git://github.com/sstephenson/rbenv.git rbenv

    $ mkdir rbenv/plugins
    $ cd rbenv/plugins/
    $ git clone git://github.com/sstephenson/ruby-build.git ruby-build
    $ cd ~
    ```

2. __.bashrc__に設定追加

    ```bash
    export RBENV_ROOT=$HOME/local/rbenv
    export PATH=$HOME/local/bin:$RBENV_ROOT/bin:$PATH
    export TMPDIR=~/tmp

    eval "$(rbenv init -)"
    ```

3. __.bashrc__を反映する

    ```bash
$ source .bashrc
    ```

4. __ruby__と__sinatra__をインストール

    ```bash
$ rbenv install 2.4.3
$ rbenv rehash
$ rbenv global 2.4.3
$ gem install sinatra
    ```

5. __~/www__に、下記の__index.cgi__を作る

    ```ruby:index.cgi
    #! /home/ユーザー名/local/rbenv/versions/2.4.3/bin/ruby

    APP_HOME='/home/ユーザー名/deploy/app'
    load "#{APP_HOME}/start.rb"
    set :run, false

    Rack::Handler::CGI.run Sinatra::Application
    ```

6. __index.cgi__に実行権限を付加する

    ```bash
    $ chmod +x ~/www/index.cgi
    ```

7. __~/deploy/app__に、sinatra用のファイルを設置する

    ```ruby:start.rb
    require 'sinatra'

    get '/?' do
      'Hello World.'
    end
    ```

8. ブラウザで __http://ユーザー名.sakura.ne.jp/index.cgi__ にアクセス。"Hello World."が表示されたら成功
feature/xxx というブランチでコミットする時コミットメッセージの頭に必ず xxx: が入るようにした

# これ何

タイトルの通りのことを git alias で実現した。
要は現在のブランチが`feature/SOMEBTS-10000`な時、コミットメッセージの頭に必ず`SOMEBTS-10000: `が入ってくれるようにした。
まあ xxx がチケット番号であること前提な感じはある。

```:.gitconfig
[alias]
  coam = "!fetch(){ p=`git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \\(.*\\)/\\1/' -e '/^feature\\//!d' -e 's/^feature\\/\\(.*\\)/\\1: /'`; git commit -am \"$p$1\" ${@:2}; };fetch"
```

```bash:result
hokkun:gittest [feature/SOMEBTS-12345]$ touch yyy
hokkun:gittest [feature/SOMEBTS-12345]$ git add yyy
hokkun:gittest [feature/SOMEBTS-12345]$ git coam "Super commit"
[feature/SOMEBTS-12345 ff752e6] SOMEBTS-12345: Super commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 yyy
```

１ミリ位シェル芸芸人に近づいた感じがある。

ちなみに普段からプロンプトにはブランチを表示している。その方法についてはこちらの [Qiita 記事](https://qiita.com/caad1229/items/6d71d84933c8a87af0c4)が詳しい。

# ハマったところ

sed で使っているバックスラッシュを二重エスケープする必要があった。これでしばらくハマった。config にそもそもエラーが入ってると `GIT_TRACE=1`とかそもそも効かないのでデバッグがしんどかった。

# ちなみに
feature/ で始まらないときはちゃんと何も入らない。

# 後で直しました
--amend などの option も受け入れる。ただし message の後のみ。
ALBでTLSネゴシエーションエラーが出たのが困った話


# ことのはじまり

サイトのアクセス数が日に日に増えていく中で、どうも一部のアクセスが502エラーになっていると、Mackerel監視でアラートがあがってきました。
とりあえずApacheリスタートをしてみたり、リクエストを別サーバに逃がしてみたりしてみたものの、事象は改善しませんでした。

時同じくして、Mackerelを見ていたら、こんな状態に...（弊社サイトは2台のEc2で冗長構成）

![2018-03-27_11h03_43.png](https://qiita-image-store.s3.amazonaws.com/0/154018/f9d65fcf-5d73-d0e5-ebf0-243b6d6ee0f6.png)

**2台とも落ちてる...**

すぐに画面から弊社サイトを確認してみても、ちゃんと表示できました。

なぜ、2台とも落ちてるのに、画面が表示されたのか分からなかったのですが、
調べていくうちにわかった「なるほどー」を書いておきます。
（そもそも問題を解決しないといけないので、それもあわせて書いておきます。）

# 何が起きていたか

アクセスが増える
↓
Apache側のプロセス生成が追いつかなくなる
↓
TLS ネゴシエーションエラーが起きる
↓
ALBのヘルスチェックが失敗する
↓
２台→１台→２台→１台・・・のループ
↓
TLS ネゴシエーションエラーがさらに起きる
↓
502エラーが返る

ということが起きていて、一度始まるとアクセスが落ち着くまでずっと不健康な状態が発生することがわかりました。

# ALBの絶妙な仕様が作用していた

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/target-group-health-checks.html

> 正常なターゲットが含まれているアベイラビリティーゾーンがない場合、ロードバランサーノードはすべてのターゲットにリクエストをルーティングします。

つまり、全滅したら、どれかにリクエストを寄せたりせず、全台にわりふるということ。

私たちの環境では、2つのターゲットグループ（1つのターゲットグループに1つのEC2）がありますので、

- 1台落ちてるとき
    - HealtyなEC2：リクエスト割り振る
    - UnhealthyなEC2：リクエスト割り振らない

- 2台落ちてるとき
    - HealtyなEC2：リクエスト割り振る
    - UnhealthyなEC2：リクエスト割り振る

という状況になるため、通常時と同じ挙動になるということがわかりました。

たまたまそんな空気を読む仕様だったので、あらかたのリクエストはちゃんと返せていたのか、と驚きとともに
使用しているAWSの仕様ももっと細かいところまで把握しないといけないなーと反省。

# 対処方法

さて、そもそものTLS ネゴシエーションエラーが起きないようにしなければならなかったので
その対応もついでに書いておこうと思います。

今回、TLS ネゴシエーションエラーが発生していた根本原因は、
ALBからEC2のApacheへのコネクションを十分に張れるように設定値の見直しを行いました。

実際に行った変更は下記です。

- MaxKeepAliveRequestsを増やす
    - ALB<>Apache間のコネクションを使い回す上限をあげる＝connection張りっぱなし時間を伸ばす

- MaxClientsを増やす
    - 最大プロセス数の上限をあげる＝捌ける窓口増やす

これで、経過観察をしてエラーが再現しなくなりましたので、晴れて解決となりました！
【翻訳記事】中堅エンジニアになるには(プロジェクト編)

# はじめに
[Insanely Fastで有名なコミュニティ](https://dev.to)で記事が上がっていたので翻訳・共有します。(許可いただきました。)
元記事: [The road to senior dev](https://dev.to/veloceronte/the-road-to-senior-dev--b6k)
今回は同記事の前半、Projectに関しての部分まで。
以下翻訳

# 中堅エンジニアになるには
エンジニアとして、ソフトウェア開発会社の支援を行うに至るまでに、若手のエンジニアのメンタリングを行ってきた。
よく尋ねられるのは、「中堅エンジニアになるにはどうしたらいいのか？」ということだった。
この質問は、全ての組織ごとに「中堅エンジニア」なるものの定義が異なるから、そう単純なものじゃない。
しかし、規模や成熟度の違う様々な会社で働いてきた経験からいえば、単に何かの技術に精通するだけでは不十分だ。
*「良い選択をすること」* 、 *「正確な予測をすること」* 、 *「日頃から時間通りに仕上げること」* こそが、本当に重要なんだ。
以下は、これからキャリアを考え始める若手のエンジニアに捧ぐものだ。経験豊富なエンジニアにとっては当たり前のことかもしれないが、私の仲間が悩み苦しんだことをリストアップしてる。

# プロジェクト

## 優先順位を定めてそれを貫き通すこと
例えば建築の仕事に就いていて、ToDoリストの中に「トイレを設置する」「窓枠を塗る」という2つがあるとする。
もちろん、これらはどちらも完了していなくてはいけないが、トイレがなくてはその家には住めないのに対して、窓枠が塗られていなくても住むこと自体は可能だ。
とてつもなく馬鹿げた例えだし、「プロジェクトのプランはあって、予算も与えられているんだ」(だからこんな馬鹿げたことは考えなくてもいい)と反論するかもしれない。
だが現実には、プランは変わって、予算もカットされる。
重要なのは、「最も重要なことを常に意識して、そしてそれを確実に終わらせるようにすること」だ。

## 憶測をやめて、効果的な質問(powerful question)をすること
憶測は多くの問題の根本原因で、そして、憶測は本来確実に避けられるはずのものだから、この憶測というのはとても疎ましい。
例えば、「スタバに8時集合で」と言われたら、スターバックスの何店なのか、午前8時なのか午後8時なのか、という質問をしないといけない。
プロジェクトにおいても、「自分が何を分かっていないかを認識し、そして一切の不確実性が残らないように効果的な質問をしなければいけない」。

## コーディングの前に分析をすること
特に若いときには、自分の価値を証明したくてとにかくすぐにコーディングを始めたくなることがあるだろう。
ただ、キミがこれから「どうやって」ものを作るのか、これらの手法を通じて先に見通しを立てる方が、結果的には速い。

- いくつか図を作成してみる
- 必要なら粗くスケッチを描いてみる、など

こうして、頭の中に「どこがハードルで、何が解消すべき疑問点なのか」というビジョンをクリアに描いておくことで、コーディングはより安全な形で始められる。

## 「良い選択」をすること
馬鹿げてるだろ？ただ別にこれは「飲酒運転をしない」なんて当たり前のことでもなく、かといってとてつもなく高度で専門的な話でもないんだ。
じゃあどうやって「良い選択」をするのか？

- ある選択肢について、影響しうるあらゆる可能性をリストアップする
    - 実装難易度はどの程度か？
    - 技術にどの程度習熟しているか？
    - パフォーマンスは？
    - コストは？
    - etc..
- 他の選択肢についても同様にあらゆる可能性を検討する

後はピュー・マトリックスのようなシンプルな手法でこれらの選択肢を比較することで、キミの選択をよりソリッドにすることができる。

## 顧客を知ること
ソースコードベースのみで働いていて、作っているソフトウェアが解決しようとしてることに知識も興味もない人がいた。
私は彼らを「コーディング猿(code monkeys)」と呼んでいる。そう遠くない将来にはロボットか、より単価の安い労働者に取って代わられる存在だろう。
顧客の事情を気にかけ始めれば、人々はキミのいう事を聞いて、キミの意見を尋ねて、そしてキミの意見を評価してくれる。
そして着実に、キミの責任範囲は拡がり、キミの価値とチャンスは増大し、結果としてお給料にも色がつくってわけだ。

以上翻訳
実際、お客がどうやってシステムを使うのか？システムが代行したい業務とは何なのか？など、お客のことを知ることは本当に大事だなと思う。
次回はチームワーク編を翻訳する予定です。
Windows Subsystem for Linux（WSL）が正式版になって以降のリセット方法

## 現象について
現在、Fall Creators Updateを適用したWindows10にて、Creators Update時の昔の作業メモからlxrun.exeを利用し、完全に消して入れなおそうとしたが、「インストール、アンインストール操作が保留中です。」と出て、上手く行きませんでした。

```powershell
C:\> lxrun /uninstall /full /y
...
Windows Subsystem for Linux でインストール、アンインストール操作が保留中です。
```
WSLが正式版になったことで、やり方が変わったようです。

## リセット方法
「アプリと機能」を開き、「Ubuntu」をクリックすると、「詳細オプション」選択できますので、クリックしてしばらく待つと詳細オプションの画面へ遷移します。
「記憶域の使用状況とアプリのリセット」にある[リセット]ボタンをクリックして、進めると初期化できました。
Python3でのwindows上のテキスト設定ファイルの読み方

######初めて投稿します。素人の年寄りが少しずつpythonを始めています。備忘録として投稿します。
##目的
#####windowsで扱われているテキストベースの設定ファイルの文字コードは、ほとんどがSJISで書かれていてるが、NT系からの流れか、UTF-16で書かれたファイルもある。いろんな設定ファイルをwindowsにてメモ帳で開いて保存ウインドで表記される文字コード(E): の表記とPythonで読み取るべきコードの対比をまとめました。
##内容
| メモ帳での文字コード(E):| pythonでのエンコード|一般的なコード名  |
|:---------------------:|:------------------:|:---------------:|
| ANSI                  |               CP932|        SHIFT-JIS|
| Unicode               |             utf-16 |UTF-16(ﾘﾄﾙｴﾝﾃﾞｨｱﾝ) BOM付き |
| Unicode big endian    |             utf-16 |UTF-16(ﾋﾞｯｸﾞｴﾝﾃﾞｨｱﾝ)BOM付き|
| UTF-8                 |          utf-8-sig |UTF-8 BOM付き    |
##確認

```python:test.py
ld = open(Unicode.txt,encoding="utf-16")
lines = ld.readlines()
ld close()
print(lines)
```
Openするテキストファイルとエンコードキーワードをいろいろ変えて確認しました。
メモ帳では、UTF-8、UTF-16 もすべてBOM付きとして扱われて、Python3ではUTF-8の場合はBOM付きのエンコードである"utf-8-sig"でエンコードして、UTF-16 の場合はBOM付きの場合はリトルエンディアン／ビックエンディアンの指定なしに"utf-16"でエンコードしてくれる。-sigなんてのもいらない。（BOM無の場合は、"utf-16-le","utf-16-be"が必要らしい。Unicode.txtを"utf-16-le"でエンコードすると先頭にBOMが見えたので。。。）

##感想
知っている方には当たり前かもしれないけれど、コード体系のよくわかっていない素人の私が理解するにはコードの名称定義がそれぞれで曖昧にみえてしまい、時間がかかりました。
私自身で確認した結果のことなので齟齬があるかもしれませんが、とりあえずwindowsの世界でUnicodeとして定義されてるファイルは読める様になりました。
team stint util

### frontもbackもこの制限で許容される要素しか開発させない。 ex) <... lay="xyz"></...>
```js
;(function(root){
 let fn={};
 fn.q=(s,doc=document)=>{return doc.querySelector(s)};
 fn.qa=(s,doc=document)=>{return [].slice.call(doc.querySelectorAll(s))}
 ;
 function entry(q,flg){
  let t='lay',qt='[lay]' //stint name
  ;
  var o={},calc=(d=>{o[d.getAttribute(t)]=d});
  o.el =(flg)?fn.q(q).cloneNode(true):fn.q(q);
  if(!o.el)return console.log('lay query error');
  fn.qa(qt,o.el).forEach(calc);
  if(o[""]) console.log('no capture lay:',o[""]);
  return o;
 }
 root.lay=entry;
})(this);

let a=lay('.f[ed]',true)
console.log(a)
/*
a."" //no name!
a.el
a.info
a.prog
a.ra
a.st
a.th
a.ti
*/
```
```html
<!---test dom--->
<style>[debug]{display:block}</style>
<div leep>
 <div l></div>
 <div c> <div cc></div> </div>
 <div r> <div rt></div><div></div> </div>
</div>
<div class="the-wall"></div>
<dialog debug>
<div class="f" ed>
 <div lay></div>
 <progress value="3" max="68" lay="prog"></progress>
 <div contenteditable="plaintext-only"></div>
 <div lay="info"><b lay="st">✔#001 </b><b lay="th"></b><b lay="ra"></b></b><b lay="ti"></b></div>
</div>
<!---->
<div class="f ed lay05 of-subed debug">
 <progress class="of-ed" value="3" max="68"></progress>
 <div contenteditable="plaintext-only"></div>
 <div class="info"><div class="str">✔$001[3/4]</div><div class="time"></div></div>
</div>
<!---->
<div lay="th"></div>
</dialog> 
```
Linux Mint18.3 でPHP xdebugをインストール

# はじめに
[Linux Mint 18.3](https://linuxmint.com/release.php?id=31) に、xdebugを入れた時のメモです。
PHPはインストール済みから始めています。(PHP7.0)

# 参考資料（感謝！）
[WEBサービス創造記](http://linuxserver.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0/php/xdebug-install#Xdebug-2) 様のページそのままです

# 手順
## PHPがデバッグ版でないことの確認

```
$ php -i | grep Build
Zend Extension Build => API320151012,NTS
PHP Extension Build => API20151012,NTS
Debug Build => no
```

## peclのインストール

```
$ pecl
プログラム 'pecl' はまだインストールされていません。 次のように入力することでインストールできます:
sudo apt install php-pear

$ sudo apt install php-pear
～略～
```

## Developer Package が入っていることの確認

```
$ apt list | grep php7.0-dev
php7.0-dev/xenial-updates,xenial-security 7.0.22-0ubuntu0.16.04.1 amd64
```

## xdebug インストール

```
$ sudo pecl install xdebug
```

## xdebug設定

インストールの最後に出るメッセージに従ってください

```
zend_extension=/usr/lib/php/20151012/xdebug.so
xdebug.remote_enable=1
xdebug.remote_autostart=1
```
【PHP】エラー出力

# PHPでエラーを出力する方法
PHPのエラー出力方法になります。基本、設定ファイル作って管理してるけど、
たまーに直書きすることあるので、コピペしやすいように。

## **php.iniでエラー出力**
```
display_errors = 1
error_reporting = E_ALL
```

## **PHPファイル内でエラーを出力する方法**
```
ini_set( 'display_errors', 1 );
error_reporting(E_ALL);
```

## **httpd.conf .htaccessでエラーを出力する方法**
```
display_errors = 1
error_reporting = E_ALL
```
ansible-vault で値ごとの暗号化をした場合、その内容を簡単に確認する方法

`ansible`でパスワードなどの機密情報を扱うのに便利なのは`ansible-vault`ですよね。

ただ、ファイルまるごとを暗号化してしまうと、その他の値や差分が確認できない問題が生じるので、値ごとの暗号化を使うと便利です。

```yaml:vars/users.yml
users:
  - name: user1
    password: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXX
  - name: user2
    password: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXX
```

ただ、これにも問題があって、ファイルまるごとの暗号化ではないため、`ansible-vault view`で内容を確認することができません。

```bash
$ ansible-vault view vars/users.yml
ERROR! input is not vault encrypted data for vars/users.yml
```

そこで、パスワードを表示する専用のplaybookを用意しましょう。

```yaml:show_password.yml
- hosts: all
  tasks:
    - name: show users
      debug:
        var: item
        verbosity: 1
      with_items: "{{ users }}"
```

このplaybookを実行すると、簡単に確認ができるようになります。

```bash
$ ansible-playbook show_password.yml

TASK [show users] ***********************************************************************************************************************
skipping: [host] => (item={u'password': u'XXXXXXXX', u'name': u'user1'})
skipping: [host] => (item={u'password': u'XXXXXXXX', u'name': u'user2'})
```

`verbosity: 1` を指定しているのは `debug`タスクによる表示を抑制するためです。
`with_items` 時点で `item`　の内容が表示されてしまうので、 `debug`　タスクの表示がされると二重表示になってしまいます。


`ansible-vault view`　が対応してくれるまでの代替措置としてお使いください。
人狼知能開発のPythonAgent接続

人狼知能開発でtensorflowを使ったモデルを適用したいのでJavaじゃなくてPythonを使ってみようと思いました。そのプロセスを公開していけたらいいなと思っています。

## 人狼知能サーバーへのPythonAgentの接続方法

基本的にはHarada Kei,[AIWolfPy v0.4.9](https://www.slideshare.net/HaradaKei/aiwolfpy-v049)を自分用に分かりやすく纏めただけのものです。

1.```./StartServer.sh```
2. Connectを押す
3. ```./StartGUIClient.sh```
3. OpenFileからjarファイルを開き、選択する。
4. SampleRoleAssignPlayerなどのAgentを選択（14人分)
5. [AIWolfPy](https://github.com/k-harada/AIWolfPy.git)をDLし、展開する。
6. 展開した先で```./python_sample.py -h localhost -p 10000```
7. AIwolf Server StarterのStart Gameを押す

以上でPythonで作ったAgentをサーバーへ接続させることができます。

＊追記
鳥海さんがpythonAgentのAutostarterバージョンを[ブログで公開](https://twitter.com/aiwolf_org/status/979539346993831937)してくださっています。
VueでCSS Modulesを使っているCSSファイルをインポートする方法


## styleを外部ファイルからインポートする

公式サイトに書いてある、ソースのインポート方法。
しかし、CSS Modulesを使っている場合、上のような書き方では、ネストしたスタイルが反映されません。


```vue
<template>
  <div class="example">
    <p>{{ msg }}</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello world!'
    }
  }
}
</script>

<style src="./style.css" module></style>
```


```style.css
.example {
  # ネストしたPタグへのスタイルは反映されない。
  & p {
    color: red;
  }
}
```

## 対応策

CSS Modules使う場合は以下のように、外部CSSをインポートしましょう


```vue
<template>
  <div class="example">
    <p>{{ msg }}</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello world!'
    }
  }
}
</script>

<style module>
  @import './style.css';
</style>
```