OmniAICreator/Qiita-1.07M huggingface dataset:
GitHub Owned Projects に別組織の Issues を追加する方法

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Meet your user-owned project board:<br>Personalize your board with automation and fill it with your work.<br>Organize it the way *you* want it.<a href="https://t.co/12ij84NHmT">https://t.co/12ij84NHmT</a> <a href="https://t.co/wowaOSeGoa">pic.twitter.com/wowaOSeGoa</a></p>&mdash; GitHub (@github) <a href="https://twitter.com/github/status/1093573930751877120?ref_src=twsrc%5Etfw">February 7, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

GitHub でプライベートな Project ボードを作れるようになりました。
自分のリポジトリと関連付けて、自分のリポジトリの Issues を登録・管理できます。

しかし、右上の Add Cards ボタンからでは所属している組織の Issues が見つかりません。
私の場合は [eslint/eslint] や [vuejs/eslint-plugin-vue] 等の管理者でもあるので、これらのリポジトリの Issues も登録したいです。

その方法を見つけたので共有します。

1. 各カラムの `+` ボタン (add notes) を押下する。
2. 追加したい Issue の URL を貼り付ける。
3. `Add` ボタンを押下する。

![github-personal-projects.gif](https://qiita-image-store.s3.amazonaws.com/0/72555/78bbafe6-5c5f-f1b8-1e5a-e99bd851c179.gif)

[eslint/eslint]: https://github.com/eslint/eslint
[vuejs/eslint-plugin-vue]: https://github.com/vuejs/eslint-plugin-vue
useEffect の中で以前の state を取得する方法

別に useEffect に限定した方法でもないがユースケース的には以前の値と今の値を比べてゴニョゴニョすることは大体 useEffect だと思う。

```tsx:例
useEffect(() => {
  // こんな感じのことやりたい
  if(prev.count - 1 === count) {
    // do something
  }
}, [count])
```

ただ、この useEffect では componentDidUpdate のように prevState が引数に入ってこない。前回の state を保持する用の state 持つのもなんかめんどくさいしな〜と思っていたところなんと公式ドキュメントにお手製 hooks による解決策が書いてあった。

https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state

こんな感じの hooks を用意する。

```tsx

function usePrevious(value: any) {
  const ref = useRef(null);
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}
```

引数の value には以前の値を取得しておきたい state を入れておく。使う側ではこんな感じになる。

```tsx
function Counter() {
  const [count, setCount] = useState(0);
  const prevCount = usePrevious(count);

  useEffect...
}
```

 ref をDOMにしか使ったことない身としては初見では違和感満載だったが、どうやら ref は props, state など計算が走る値にはなんでもつけられるらしい。正直どうやって動いているのかよく分かっていないのでまた今度勉強してみたい。
Mac Terminal コマンド

環境
OS : macOS Mojave

#よく使うTerminalコマンド
・カレントディレクトリにあるファイルの表示

```
ls
ls -a 　    　#隠しファイルも含めてすべて表示
```

・ディレクトリ移動

```
cd XXX     #カレントディレクトリに存在するXXXに移動
cd ~       #ホームディレクトリに移動
cd ..      #一つ上の階層に移動
```

・カレントディレクトリのパス表示

```
pwd
```

・ディレクトリ作成

```
mkdir xxx
```

・ファイル作成

```
touch xxx.html
```

・ファイル検索

```
mdfind xxx
```
npm startがwebpackの不具合で起動しなくなったので修正方法のメモ

`create-react-app`を使ってReactプロジェクトを作成し、`npm start`を実行すると、

```terminal

/Users/wildmouse/helloworld/node_modules/ajv/lib/keyword.js:65
      throw new Error('custom keyword definition is invalid: '  + this.errorsText(validateDefinition.errors));
      ^

Error: custom keyword definition is invalid: data.errors should be boolean
```

というエラーが発生し、起動しなかったため修正方法を記録しておきます。

私の場合は`create-react-app`に関連して本エラーに遭遇しましたが、webpackを使っている場合なら発生するエラーと思われます。

なおこの不具合は`10 Feb 2019, 08:37 GMT+9`にgithubのwebpackリポジトリに報告されており、修正方法が共有されているため、間も無く修正が完了すると思われます。

現時点ではnpmリポジトリ側の修正はできていないようですが、しばらく経過するとパッケージをupdateすることで修正できる可能性があります。

## 修正方法

webpackの依存パッケージである`node_modules/ajv-error`内にある、index.jsに以下の修正を加えることでエラーが発生しなくなります。

```js:修正前のnode_modules/ajv-errors/index.js(14行目付近)
  ajv.addKeyword('errorMessage', {
    inline: require('./lib/dotjs/errorMessage'),
    statements: true,
    valid: true,
    errors: 'full', // ここが原因
    config: {
      KEYWORD_PROPERTY_PARAMS: {
        required: 'missingProperty',
        dependencies: 'property'
      },
      options: options || {}
    },
```

```js:修正後のnode_modules/ajv-errors/index.js(14行目付近)
  ajv.addKeyword('errorMessage', {
    inline: require('./lib/dotjs/errorMessage'),
    statements: true,
    valid: true,
    errors: true, // 'full',を true, に変更する
    config: {
      KEYWORD_PROPERTY_PARAMS: {
        required: 'missingProperty',
        dependencies: 'property'
      },
      options: options || {}
    },
```

## 参考

- [webpack broken by ajv@6.9.0, "custom keyword definition is invalid: data.errors should be boolean" #8768](https://github.com/webpack/webpack/issues/8768)
Apple Watch でスケールを取得する

# 環境
- Swift 4.2
- watchOS 5

# コード

watchOS では

```swift
WKInterfaceDevice.current().screenScale // CGFloat
```

ちなみに iOS で取得するには

```swift
UIScreen.main.scale // CGFloat
```


# 参考
- https://github.com/AFNetworking/AFNetworking/issues/2808
インストール済みのnpmパッケージのバージョンを確認する方法

マシン全体(global)にインストールされている各パッケージのバージョンを確認する場合は、

```terminal
npm list -g --depth=0
```

でOK。

`--depth=0`は依存しているパッケージのバージョンを表示しないためのオプション(直接インストールしたパッケージのみ表示する)

プロジェクト単位のバージョンを表示したい場合は`-g`を除けばOK。
安全に使える乱数を生成する関数

#### MySQLで簡単に乱数を生成する関数。

```mysql

DELIMITER $$
CREATE FUNCTION randomString(len INT)
RETURNS tinytext
BEGIN
    declare r tinytext;
    declare s tinytext default '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    declare n int;
    set r='';
    while length(r) < len do
    set n=rand() * 61;
    set r=concat(r,substr(s,n,1));
    end while;
    RETURN r;
END$$
DELIMITER ;
```

#### 例

```mysql 
mysql> select randomString(10);
+------------------+
| randomString(10) |
+------------------+
| BL446jgqlr       |
+------------------+
1 row in set (0.01 sec)

mysql> select randomString(4);
+-----------------+
| randomString(4) |
+-----------------+
| cEHA            |
+-----------------+
1 row in set (0.00 sec)

mysql>
```
【Django】APIのキーなどを本番環境では環境変数で、開発環境ではファイルで管理する

# はじめに

LINE Messaging APIなど、APIを利用したDjangoアプリを個人開発する際、APIのキー情報を

- Herokuなどの本番環境では環境変数に設定
- ローカルの開発環境ではlocal_settings.pyに直書き

して管理する方法を採ったので、その方法をまとめます。

# そのような管理にした理由

- GitHubで公開するソースコード(local_settings.py以外)では、APIのキーを秘匿したい

- 開発環境であるMacではAPI利用アプリを複数開発するので、APIのキーを環境変数ではなく、Djangoプロジェクト単位のファイル(local_settings.py)で管理したい

- views.pyやmodels.pyなどではAPIのキーをどこから読み込んでいるか意識させない作りにしたい（本番環境と開発環境でロジックに差をつけたくない）

為です。

# 環境

- Python 3.6.6
- Django 2.1.5

# settings.pyとlocal_settings.pyでのAPIキーの設定方法

local_settings.pyでは、`DEBUG = True`にしつつ、各APIのキーを直書きします。

```python:local_settings.py
# ...

DEBUG = True

SECRET_KEY = 'hogehogehoge...'

LINE_CHANNEL_ACCESS_TOKEN = 'hogehogehoge...' 
LINE_CHANNEL_SECRET = 'hogehogehoge...'
```

settings.pyでは、`DEBUG = False`にした上で、local_settings.pyを読みに行かせ、local_settings.pyの存在しない本番環境であれば(`DEBUG = True`にならなければ）、各APIキーを本番環境の環境変数から読み込みます。

```python:settings.py
# ...

DEBUG = False

# ...

try:
    from .local_settings import *
except ImportError:
    pass

if not DEBUG:
    SECRET_KEY = os.environ['SECRET_KEY']
    LINE_CHANNEL_ACCESS_TOKEN = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
    LINE_CHANNEL_SECRET = os.environ['LINE_CHANNEL_SECRET']
```

# views.pyやmodels.pyなどで、APIのキーを使う

settings.py(local_settings.py)で設定した変数は、

```python
from django.conf import settings
print(settings.LINE_CHANNEL_ACCESS_TOKEN)
```

とすることで、views.pyやmodels.pyなどから参照することができます。

以下はviews.pyにおいて、LINE Messaging APIのキーを使用している例です。

APIのキーを環境変数から読むのかファイルから読むのか、はsettings.py側で制御しているので、views.py側では意識する必要がなくなりました。

```python:view.py
from django.http import HttpResponse, HttpResponseForbidden
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import (
    MessageEvent,
    TextMessage,
    TextSendMessage
)

# settings.pyに設定したAPIキーを参照
line_bot_api = LineBotApi(channel_access_token=settings.LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(channel_secret=settings.LINE_CHANNEL_SECRET)


@csrf_exempt
def callback(request):
    signature = request.META['HTTP_X_LINE_SIGNATURE']
    body = request.body.decode('utf-8')
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        return HttpResponseForbidden()
    return HttpResponse('OK', status=200)

# ...
```

# 参考

- [現場で使える Django の教科書《基礎編》](https://www.amazon.co.jp/dp/B07GK7BWB7/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
ACM会員にならない理由が見つからない

# TL;DR
ACM(Association for Computing Machinery)に入ろう。
年間99ドルでプロフェッショナル会員になれば以下を受けられる。

1. 月刊の学会誌Communications of ACM (CACM) の配布（紙媒体とオンライン）
2. SIG(Special Interest Groups)への参加、カンファレンス参加
3. ACM Online Books: Skillsoft, Morgan Kaufmann, and Syngress
4. ~~ACM Online Books: O'Reilly Safari~~ 提携終了

以下、2018年1月に入会して１年以上経過しているので実際に使っているものを中心に紹介する。

# CACM
* 学術論文ではなく、全体に読み物系なので専門家でなくても興味がある分野は読める。
* AI,機械学習系の比率がかなり高くなっているが、開発言語、テスト、DB、IoT、教育、ダイバーシティ関連までかなり幅広い読み物があり、興味を持っている分野の知識を得るには悪くない。
* 薄っぺらい英語の雑誌なので時間的に余裕がない時はとりあえず積んでおき、出張等で隙間の時間が増える時にまとめて読んでも良い。


# ~~Safariでできること~~
* ~~IT系の書籍やビデオが圧倒的なのはもちろんのこと、意外と読み物系も少なくない。~~
* ~~スマホアプリSafari Queueからのアクセスが可能。（動画を含めコンテンツをダウンロードしてオフライン視聴可能。）~~
* ~~動画コンテンツがとても充実している（個人的に技術英語の習得にも最適と考える）~~
    * ~~Oriole Online Tutorials　：オンデマンド形式。動画＋テキストの比較的短めのトピックの解説。~~
    * ~~Live Online Training　：ライブ形式で事前予約必要。3時間程度のトレーニング、複数日のコースもある。アメリカまたはヨーロッパ時間なので日本の深夜から早朝の時間帯。日本人には厳しい。~~
* ~~O'Reilly主催の各種カンファレンスの参加費用の割引（執筆時点では25%程度？）~~
郵便番号をキーにして、OpenWeatherMapから天気データを読み込んでkintoneに表示させるメモ

デベロッパーネットワークの投稿を元に試してみたメモです。
https://developer.cybozu.io/hc/ja/community/posts/360041094612

好きなAPI kintone.proxy が使われていたので、元のソースコードをお借りして修正してみました。

# ソースコード

```index.js
(function() {
    "use strict";
    // 編集画面と新規作成画面にて
    kintone.events.on(['app.record.edit.show','app.record.create.show'], function(event) {
        // ボタンを作成
        var getWeatherBtn = document.createElement('button');
        getWeatherBtn.id = 'get_weather_btn';
        getWeatherBtn.innerText = '天気を取得する';

        // ボタンクリックイベントで発火
        getWeatherBtn.onclick = function () {
            console.log(event);
            // レコード取得
            var record = kintone.app.record.get();
            console.log(record);
            // 郵便番号フィールドから入力値を取得
            var zipCode = record.record.郵便番号.value;
            console.log(zipCode);
            var apiKey = '1234567890abcdefg'; // OpenWeatherMapのAPIキー
            var owmUrl = 'https://api.openweathermap.org/data/2.5/weather?zip=' + zipCode + ',jp' + '&APPID=' + apiKey ;
            console.log(owmUrl);
            // return new kintone.Promise(function(resolve, reject) {
            // イベントをreturnしない。
            new kintone.Promise(function(resolve, reject) {
                kintone.proxy(owmUrl, 'GET', {}, {}, function(body, status, headers){
                    if (status >= 200 && status < 300) {
                        var json = body.replace(/^\s+|\s+$/g,''); 
                        var result = JSON.parse(json);
                        console.log(result);
                        var todayWeather = result.weather[0].main;
                        console.log(todayWeather);
                        record.record.天気.value = todayWeather;
                        // レコードセット
                        kintone.app.record.set(record);
                        resolve(event);
                    }
                },function(error) {
                    //error
                    console.log(error); 
                    resolve(event);
                });
            });
        };
        // ボタンの描画
kintone.app.record.getSpaceElement('get_weather_btn_field').appendChild(getWeatherBtn);
    });
})();

```

# 画面イメージ
<img width="463" alt="スクリーンショット 2019-02-10 7.07.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/214523/208a8915-1145-6942-54bc-5abab599fceb.png">

# まとめ

- イベントをリターンしない事が肝
- OpenWeatherMapは無料枠がある

# リンク

- OpenWeatherMap https://openweathermap.org/
kintone プラグイン開発メモ　その８（ダミーの設定値を読み込んでJavaScriptカスタマイズしてみる）

その７からの続き。

プラグイン設定画面を作成する前に、先にJavaScriptカスタマイズプログラムを作ります。

# フィールドゼロ埋めJavaScriptカスタマイズ
kintoneアプリのフィールドをゼロ埋めするカスタマイズを作成します。
この時にプラグインの設定値を取得したと仮定してダミーデータを作り、それを利用してカスタマイズしていきます。

### カスタマイズ概要
以下のような内容です。

 - 編集画面、新規作成画面から保存する際に実行
 - プラグインの設定値を取得（ダミーです）
 - 単価フィールドが空欄の時にフィールドにゼロをセットする
 - 保存する 

# 動作イメージ

編集画面又は新規作成画面時にゼロ埋めボタンを表示させます。
<img width="913" alt="スクリーンショット 2019-02-10 6.22.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/214523/6e166a41-98c2-e455-72f9-32a1251ebc84.png">

ゼロ埋めボタンを押下した際に、単価フィールドが空の時にゼロを埋めます。
<img width="900" alt="スクリーンショット 2019-02-10 6.22.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/214523/6f7fd37e-bdd7-ce58-197c-e78a8d98c3eb.png">

保存後の画面です。
<img width="907" alt="スクリーンショット 2019-02-10 6.22.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/214523/515e2fdc-ff54-228b-afb4-7e7a0c65b324.png">

# カスタマイズ側のソースコード
通常のカスタマイズと少し違う点は、設定画面から値を読み込んだと仮定して、下記の流れで作成しています。

 1. 設定値を読み込みます。
 2. ダミーの設定値を用意します。
 3. 設定値を使って処理を記述します。

```customize.js
(function(pluginId) {
    "use strict";
    let config = kintone.plugin.app.getConfig(pluginId)
    console.log(config);

    // var config = {
    //     'DisableItem': JSON.stringify(arrayDisableItem),
    //     'DisableLine': JSON.stringify(arrayDisableLine)
    // };

    config = {
        'ZeroFillItem': ["単価", "単価_1", "単価_0"]
    };
    console.log(config);
    console.log(JSON.stringify(config));

    // 詳細画面　編集、新規作成
    kintone.events.on(['app.record.edit.show', 'app.record.create.show'], function(event) {
        let myIndexButton = document.createElement('button');
        myIndexButton.id = 'my_index_button';
        myIndexButton.innerHTML = 'ゼロ埋めボタン';
        myIndexButton.onclick = function() {
            let record = kintone.app.record.get();
            config.ZeroFillItem.forEach(function(value){
                if (!record.record[value].value) {
                    console.log("record.value is NULL or undefined");
                    record.record[value].value = 0;
                } else {
                    console.log(record.record[value].value);
                }
            });
            kintone.app.record.set(record);
        }
        kintone.app.record.getHeaderMenuSpaceElement().appendChild(myIndexButton);
        return event;
    });
})(kintone.$PLUGIN_ID);
```

次はいよいよ設定画面を作成していきます。
複数のmicro:bitで自動灌水

# はじめに

平成29年[中学校学習指導要領解説 技術・家庭編](http://www.mext.go.jp/component/a_menu/education/micro_detail/__icsFiles/afieldfile/2019/03/18/1387018_009.pdf) P.57には「気温や湿度の計測結果に基づき，灌水などの管理作業を自動的に行う栽培ロボット」が登場します。
![kansui.png](https://qiita-image-store.s3.amazonaws.com/0/44523/519fc6a3-a191-df00-7755-4fa41c2e31c8.png)

という事で、micro:bitの無線機能を使い、複数のmicro:bitでIoT風に組んでみました。
インターネットは使っていないのであくまでも風になります。
ただ、実際の学校現場はかなりネットワーク環境が悪く、授業としてはBluetoothの方がスムーズに授業ができそうに思います。

# システム構成

![system.jpg](https://qiita-image-store.s3.amazonaws.com/0/44523/6a5d19a9-6e58-f680-1bab-5167cbe307c9.jpeg)

# 用意するもの

- micro:bit ＋電池ボックス＋電池　３セット
- 釘２本（紙ヤスリ等で表面のコーティングを削った物）
- ワニ口クリップケーブル４本
- 灯油電動ポンプ(自動停止機能の無い物)＋電池
- プログラム制御スイッチ(TFabWorks [TFW-SW2](http://tfab.jp/sw2))
- フィルムターミナル(TFabWorks [TFW-FT2](https://tfabworks.com/product/tfw-ft2/))
- （記録を取る場合）Windows10 makecodeアプリ

# センサー用micro:bit「センサー１」

センサー用micro:bitは、だたひたすら水分量を司令塔に無線で
送り続けます。
ちゃんとした水分センサーを使ってもいいのですが、とりあえず机上実験なので、釘をP0と3Vに接続して行いました。水分が多い時はアナログ値が1023に近づき、乾いている時は200に近づきます。

![microbit-画面コピー (18).png](https://qiita-image-store.s3.amazonaws.com/0/44523/087c2b66-f13e-a3e9-def8-d4b3874b7d1e.png)
https://makecode.microbit.org/_TvtJY4WyUcHs


# 司令塔

センサー1から受け取った値を監視し水分量が500を超えたらポンプに１を送り、それ以外は0を送ります。

![microbit-画面コピー (13).png](https://qiita-image-store.s3.amazonaws.com/0/44523/fe178224-bf3f-5cf3-b278-f4f07bb6ec55.png)
https://makecode.microbit.org/_bRX97oAP8REW

# ポンプ用micro:bit「ポンプ１」

ポンプ1宛に無線をうけとったら命令の値をデジタルで書き込むをつかってP1に出力します。1が書き込まれると、プログラム制御スイッチが動作し、フィルムターミナルで断線させていた回路が繋がり、ポンプが動き始め散水が行われます。

![microbit-画面コピー (19).png](https://qiita-image-store.s3.amazonaws.com/0/44523/5ff5556a-65e4-aa00-db9e-6fc64bca1685.png)
https://makecode.microbit.org/_WPmU9mf3vCyy


# 完成動画

https://youtu.be/vFMmNtxW5k0
![vlcsnap-2019-02-10-06h19m17s188.png](https://qiita-image-store.s3.amazonaws.com/0/44523/846b65e1-dcaa-dd2e-34a2-5fecb9b7cc64.png)


# 作ってみて

誤動作も無く動きました。
机上で行うのであれば、これで大丈夫だと思いますが、ガチで屋外で灌水するようにするためには、多くのハードルがあると思います。
[TouchDesigner] スライダーのちょっとしたTips

普段、TouchDesignerでスライダー部品を多く利用していると、どのスライダーに何を割り当てているのか分からなくなりませんか？

![スクリーンショット 2019-02-10 5.03.33.png](https://qiita-image-store.s3.amazonaws.com/0/107306/dc9c5f49-2aee-9125-a0ca-b3e9757d38e0.png)

上記の画像の場合、オペレータに適切な名前をつければ判別できるから良いようなもののContainerで表示すると判別がつきません（以下の図参照）。

![スクリーンショット 2019-02-10 5.13.23.png](https://qiita-image-store.s3.amazonaws.com/0/107306/74df88d5-e043-9101-febe-b2b9c6ade4b7.png)

そこで私はボタン部品を参考にして、以下のようにスライダーにラベルをつけてしまいます。

![スクリーンショット 2019-02-10 5.19.32.png](https://qiita-image-store.s3.amazonaws.com/0/107306/ef6ba3d1-acca-e88a-1737-5fce4737f02d.png)

スライダーのノブに字が隠れてしまうのが玉に瑕ですが判別できるのがありがたいです。

やり方ですがスライダーの中に入り込んで以下のようにTOPオペレータのTextとCropとNullを追加します。Cropで余白部分を適当に切り取り調整します。

![スクリーンショット 2019-02-10 5.27.23.png](https://qiita-image-store.s3.amazonaws.com/0/107306/0c40f901-00d3-4f94-8c10-539262be5e45.png)

そして、スライダー部品のプロパティのLookタブのBackground項目に「./null1」のように先ほど追加したTOPオペレータの末端（ここではNull1）を指定するだけで出来上がりです。

![スクリーンショット 2019-02-10 5.29.49.png](https://qiita-image-store.s3.amazonaws.com/0/107306/06930a4a-d429-c0e4-8eea-2b1c723c19ef.png)
MSYS2 + Docker for Windows

Windows10 + MSYS2 + Docker for Windows

## 環境変数 `PATH`
`docker-compose.exe exec` の実行には、`docker.exe` までPATHが通っている必要があった。

```bash
$ docker-compose exec rabbitmq bin/bash
Couldn't find `docker` binary. You might need to install Docker:
```

なので通しておく

```bash
export PATH="$PATH:/c/Program Files/Docker/Docker/resources/bin"
```

## docker-compose 引数の COMMAND が変換されてしまう問題
`/bin/bash` がWindowsのパスに変換されてしまっている（シェル展開）

```bash
[05:03:22 pen@gray2 docker]$ winpty docker-compose.exe exec rabbitmq /bin/bash
OCI runtime exec failed: exec failed: container_linux.go:344: starting container process caused "exec: \"C:/msys64/usr/b
in/bash.exe\": stat C:/msys64/usr/bin/bash.exe: no such file or directory": unknown
```

`bin/bash` なら変換されないのでこれで回避。
`//bin/bash` でもいい。

```bash
[05:03:26 pen@gray2 docker]$ winpty docker-compose.exe exec rabbitmq bin/bash
root@rabbitmq:/#
```

他の解決策としては、WSL から呼ぶというのもある。
[WSLからWindowsのDockerを使う](https://qiita.com/iamapen/items/e7b0190d4e8046c565fa)
Google Calendar API Events: watch できないカレンダーがあるって話

[@koshi_life](https://twitter.com/koshi_life) です。

# TL;DR

Google Calendar API の[Events:watch](https://developers.google.com/calendar/v3/reference/events/watch) を用いて
特定カレンダーの変更通知(Push Notification)を受け取ることができますが、Googleが提供している「国の休日」等のカレンダーにはWatch設定できないっていう話です。

公式ドキュメント、Web上にあまり情報がなかったので備忘します。


## サンプルスクリプト(Ruby)

```CalendarWatcher.rb
class CalendarWatcher

  CALLBACK_URL = 'https://YOUR_SITE'

  # client: Google::Apis::CalendarV3::CalendarService
  # calendar_id: xxx@gmail.com
  def self.start(client, calendar_id)
    # Watchする対象期間は３日後とします。
    expiration = Time.now.strftime('%s%L').to_i + (1000 * 60 * 60 * 24 * 3)

    # Events:watch リクエストパラムの準備
    req = Google::Apis::CalendarV3::Channel.new
    req.id = SecureRandom.uuid
    req.type = 'web_hook'
    req.address = CALLBACK_URL
    req.expiration = expiration.to_s

    # Event:watch コールします。
    client.watch_event(calendar_id, req)
  end

end
```

### Watchできるカレンダー

```
irb(main):00x:0> email = 'xxx@gmail.com'
irb(main):00x:0> CalendarWatcher.start(client, email)
=> #<Google::Apis::CalendarV3::Channel:xxx @id="d81482a7-300a-4c24-8242-39c213f89f22", @expiration=1552330683000, @kind="api#channel", @resource_id="xxxxxxxxxxxxxxx", @resource_uri="https://www.googleapis.com/calendar/v3/calendars/xxx@gmail.com/events?maxResults=250&alt=json">
```

### Watchできないカレンダー１ 「Not Found」

参照権限がないカレンダーに対してWatchリクエストを行った場合は Not Found のエラーとなりました。

```
irb(main):00x:0> email = 'yyy@gmail.com'
irb(main):00x:0> CalendarWatcher.start(client, email)
Traceback (most recent call last):
        3: from (irb):5
        2: from (irb):5:in `rescue in irb_binding'
        1: from CalendarWatcher.rb:xx: in `start'
Google::Apis::ClientError (notFound: Not Found)
```

### Watchできないカレンダー２　「Push notifications are not supported by this resource.」

```
irb(main):00x:0> email = 'ja.japanese#holiday@group.v.calendar.google.com'
irb(main):00x:0> CalendarWatcher.start(client, email)
Traceback (most recent call last):
        2: from (irb):3
        1: from
CalendarWatcher.rb:xx: in `start'
Google::Apis::ClientError (pushNotSupportedForRequestedResource: Push notifications are not supported by this resource.)
```
Push Not Supported For Requested Resource　にもあるように、プッシュ通知できないカレンダーリソースということでした。

他にも Google が提供している以下カレンダーにWatch設定することはできませんでした。同じエラーが発生。

- 日本の祝日: `ja.japanese#holiday@group.v.calendar.google.com`
- その年の経過日数: `#daynum@group.v.calendar.google.com`
- Los Angeles Dodgers: `mlb_19_%4cos+%41ngeles+%44odgers#sports@group.v.calendar.google.com`
- Boston Red Sox: `mlb_2_%42oston+%52ed+%53ox#sports@group.v.calendar.google.com`

おそらくですが、Googleカレンダーから追加できるGoogle製のカレンダーも同様にWatch設定できないものと見ております。

<img width="800" alt="スクリーンショット 2019-02-09 21.36.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/51734/f9d1a264-500a-6715-1bc0-18491bdcecda.png">

言いたきことは、プッシュ通知の設定ができないカレンダーがあるので、考慮したほうがいいですねっていう話です。

それより、MLBのカレンダーが公開されていることに驚きました。
monacaのNIFCloudMBでエイリアス付きメールアドレス(xxxx+1@example.com)が使えない闇を解決する。

## 環境
NIFCloudMB v3.0.0
最新verはちゃんとしてるのかも？しれないね。

## 現象
ncmbでエイリアス付きメールアドレスで認証できない。

## なんでqiitaで書いてるの？
mobile backendの[GithubのISSUE](https://github.com/NIFCloud-mbaas/UserCommunity/issues)を見ると
open 802件とかなっていて、「これ、本家はやる気ないな。。」
というのがありありと見えてissue立てて解決できるものじゃないな、と諦める。終わっとる。
副業でいじる機会があって、なんじゃこれ、となったのでここで記事を書く。
なんとかしてくれませんかって困ってるクライアントが言われて見てみたら酷い有様だった。

## 原因
ncmbが使っている[ljharb/qs](https://github.com/ljharb/qs)が古い。テスト足りてない。
最新のqsはここの挙動を外から指定できる機能がついているが、ncmbが使っているqsにはまだその機能がついていない。

## モンキーパッチ
www/ncmb/ncmb.min.jsをいじる

```javascript
exports.decode = function (str) {

    try {
        return decodeURIComponent(str.replace(/\+/g, ' '));
    } catch (e) {
        return str;
    }
};
```
を

```javascript
exports.decode = function (str) {

    try {
        return decodeURIComponent(str/*.replace(/\+/g, ' ')*/);
        //                           ^^^^^^^^^^^^^^^^^^^^^^^^
    } catch (e) {
        return str;
    }
};
```
こうする。

## 感想
ひどい仕事だった。
以上です。
解析学Part1: ε-近傍について

数列
$$a_n = (1 + \frac{1}{n})$$
のとき，nが∞に近づくならば$a_n$は1に近づく．(図１)
これは直感的に理解できるが次はどうだろう．

<img width="597" alt="スクリーンショット 2019-02-10 3.08.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/33329/8403cb7d-82df-58ae-5ad9-be24e0ebd55a.png">
図１



これは図２のようにe=2.718...　に近づく

$$a_n = (1 + \frac{1}{n})^n$$
<img width="576" alt="スクリーンショット 2019-02-10 3.11.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/33329/5d73a009-70ad-91da-7e0c-b650c7d57ac1.png">
図２

しかし上では１に近づくならば１×1×１×....ならば１であると考えるのが人間の直感的な感想ではないだろうか．
しかしそうではない．そのために数列の収束を示す必要がある．


今回は$\epsilon$-近傍で定義することにしよう．
実数列$\\{a_n\\}^\infty_{n=1}$がある実数$\alpha \in \mathbb{R}$に収束することの厳密な定義を与えるため，$\alpha \in \mathbb{R}$を含む開区間$U_\epsilon(\alpha)$を次のように定義する．

$$ U_\epsilon ( \alpha )  = \\{ x \in \mathbb { R } | \alpha - \epsilon < x < \alpha + \epsilon \\} $$

$$ = \\{ x \in \mathbb { R } | | x - \alpha | < \varepsilon \\} \subset \mathbb { R }$$

を， 点$\alpha \in \mathbb{R}$の$\epsilon$-近傍と呼ぶ．

<img width="424" alt="スクリーンショット 2019-02-10 3.37.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/33329/e72a0cdb-3e47-042d-59e7-d6d8806c04ba.png">

実数列$\\{a_n\\}^\infty_{n=1}$が実数$\alpha \in \mathbb{R}$に**収束**するとは,点$\alpha$のどんなに小さな$\epsilon$-近傍$U_\epsilon(\alpha)$に対しても(すなわち正の実数$\epsilon > 0$をどんなに小さく選んでも)
ある番号$N\in \mathbb{N}$より先の$a_N,a_{N+1},a_{N+2},\cdots$ はすべて$U_\epsilon(\alpha)$に含まれることであると定義する．
<img width="428" alt="スクリーンショット 2019-02-10 3.44.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/33329/7ed3af62-29d1-1f5c-a434-b8bbff4ad5ce.png">

他にもイブシロン・デルタ論法を使って上での定義を書くこともある．

収束条件などは書けば長くなるので次回以降とする．
sedコマンドの怖〜い体験

### お命頂だいっ！

こんにちは、リクームです。
sedコマンドとは文字列を全置換したり、行単位で抽出したり、いろいろなテキスト処理をすることができるコマンドです。
そんな便利なsedコマンドですがヒヤッとした経験があったので、記事に残しておこうと思います。
ちなみに、sedという名称は「Stream EDitor」の略称らしいです。

sedはgeditやvimのようにテキストファイルの内容を表示しながらリアルタイムで対話的に編集するのではなく、ファイルやパイプラインからの入力をコマンドラインのオプションで指定した指示に従いテキストを編集して出力します。
流れてくるテキストを編集するため、「ストリームエディタ」と呼ばれています。

## sedコマンドの使い方
まず、sedコマンドの基本的な使い方です。
「aaa, bbb, ccc」と記載されている以下のようなテキストファイルがあるとします。

```sh:
cat test.txt                                               
aaa, bbb, ccc
```
「aaa」と記載されている箇所を「ddd」という文字列に置換したい！という場合、sedコマンドを用いることで簡単に置換することができます。

```sh:
##　s"/置換前文字列/置換後文字列/"
cat test.txt | sed -e s"/aaa/ddd/"
##「aaa」が「ddd」に置き換わる！!
ddd, bbb, ccc
```
パイプラインで入力情報を置換することで見事に文字列が置き換わりましたね！

## sedで置換した結果をテキストファイルに出力
さきほどは結果をコンソール上に出力しただけでしたが、今度はtxtファイルに出力してみましょう。

```sh:
##置換結果を/tmp/after_test.textに出力
cat test.txt | sed -e s"/aaa/ddd/" > /tmp/after_test.text
##結果を出力すると・・・
cat /tmp/after_test.text
##変わってる！
ddd, bbb, ccc
```
文字列が置き換わっていることが確認できました。

さぁここからが本題です。

先ほどは出力するファイルを別ファイルにして出力しました。
今度は同じファイルに対して出力してみましょう。

```sh:
## >だけでは上書きできないため、>|で強制的に上書きする。
cat test.txt | sed -e s"/aaa/ddd/" >| test.txt
## 結果を出力。。。。ってあれ？？？
cat test.txt
```
catで結果を確認しようと思いましたが出てきませんね。。。
viコマンドで確認してみましょう。
<img width="1439" alt="スクリーンショット 2019-02-10 3.20.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/351026/41df4427-d1c9-fbcf-350c-1d867058e9cb.png">

消えた・・・・！？
え、なんでなんで？？？

なぜこんなことが起きてしまうのでしょうか。。。
今回のように一つのコマンド列で「ファイルを開く操作」と「ファイルに書き込む操作（同じファイルに対して）」を実行するとファイルが消失してしまうのです。。恐ろしや〜。。
※上書きの際はエラーが出る場合もあります。今回私が行なった操作で「>|」で強制的に上書きを実行しましたが、「>」だけだとエラーが発生します。今回はわざと事象を発生させたかったので強行しました。

sedコマンドに限った話ではないですが、テキストファイルを編集する際は必ず、バックアップを取っておきましょう。。

## まとめ
- sedコマンドを用いることで文字列の置換が簡単に行える
- 編集するファイルと出力するファイルが同一の場合、出力結果が空になるので注意
- テキストファイルをいじるときは極力バックアップを取るように心がける
utility-typesの$ShapeとFlowの$Shapeとの違い

https://github.com/piotrwitek/utility-types

utility-typesはTSの便利な型集(Omitなど常用するものが入っている)であるが、この`$Shape`の定義はflow v0.90以前とは異なっているの注意が必要。

https://github.com/piotrwitek/utility-types/blob/master/src/utility-types.ts#L67


```ts
export type $Shape<T extends object> = Partial<T>;
```

で、nullを許容しないが、v0.90までのFlowはnullableなのでflow→tsからの一時しのぎにutils-typesを導入すると型エラーが起きうる。
まあ、一瞬で`$Shape`から`Partial`にできるので現状とくにutils-typesの`$Shape`を使う意味はない。

flow v0.90以後は`Partial`と同等なので、こちらも純粋に`Partial`を使えばいい。
> Changed $Shape<> types to reject null and void as subtypes
https://github.com/facebook/flow/releases/tag/v0.90.0
JetBrains IDEで特定ファイルに拡張子が反映されなくなった状況への対処

# 問題
Intellij Ideaで開発していた所、特定のファイルのファイルブラウザ上の表示が`Text`になり、ハイライトや補完が効かない状態となりました。（サンプル画像では「`Main.java`」というファイルで問題を再現しています。）
<img width="382" alt="スクリーンショット 2019-02-10 3.15.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/280230/50260f77-4bf1-9ecf-529e-c7960195bef3.png">
<img width="791" alt="スクリーンショット 2019-02-10 3.06.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/280230/1fcd5c09-899b-cc75-b3d3-beb9571bf193.png">

# 原因
何のショートカットを踏んだかは不明ですが（調べきれなかったので教えていただけるとありがたいです）、`Recognized File Types`の`Text`の設定にそのファイル名が紛れ込んでました。
<img width="791" alt="スクリーンショット 2019-02-10 3.09.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/280230/95ed11ae-af26-e135-75f8-5ed3c6f3b97f.png">

# 対処
`Recognized File Types`の`Text`の設定からファイル名を抜けばOKです。

# 参考にさせていただいた記事
[IntelliJ IDEA 任意のファイル名または拡張子のファイルタイプを設定 \- 元フリーエンジニアライフ](http://takeyuweb.hatenablog.com/entry/2014/11/06/210330)
駆け出しJavaScriptエンジニアが見落としがちなスプレッド演算子と条件演算子

# この記事の対象
演算子と言っても関係演算子くらいは分かる人

Webエンジニアに転職して1ヶ月経ち、覚えたことをアウトプット

# スプレッド演算子
スプレッド演算子とは配列要素を「...」といったカンマ3つで表し、クローン配列を作ります。
以下に例を記します。

## 配列の場合
「...arr1」は「arr1」で作成した配列のクローン配列を作ります。
「arr2」では「arr1」と「7, 8, 9」をマージします。

```js
const arr1 = [1, 2, 3, 4, 5, 6];
const arr2 = [ ...arr1 , 7,  8, 9];

console.log(arr1); // [ 1, 2, 3, 4, 5, 6 ]
console.log(arr2); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
```

## オブジェクトの場合
基本的に配列と同様で、クローンオブジェクトを作ります。

```js
const obj1 = { a: "apple", b: "orange", c: "banana" };
const obj2 = { ...obj1 , d: "strawberry" };

console.log(obj1); // { a: 'apple', b: 'orange', c: 'banana' }
console.log(obj2); // { a: 'apple', b: 'orange', c: 'banana', d: 'strawberry' }
```

# 条件演算子
**比較式 ? trueの場合の処理 : falseの場合処理** のようにif文よりもスマートなコードで記述できます。

## if文から条件演算子の変換
例として、複数の文字列を含む配列a, bを用意します。
それぞれの配列が一致するかどうか、if文で一致すればtrue、しなければfalseの文字列を出力します。

```js
const a = ["a", "b", "c"];
const b = ["d", "e", "f"];

if(a === b){
    console.log(true);
} else {
    console.log(false);
}

// false
```

上記のif文を条件演算子に変換してみます。

```js
const a = ["a", "b", "c"];
const b = ["d", "e", "f"];

console.log(a === b ? true : false);

// false
```

## 詳しい記事の紹介

※[もっと詳しい記事](https://qiita.com/Nossa/items/e6f503cbb95c8e6967f8)があるので、掘り下げたい人は確認してみてください。
とあるエンジニアの問題意識 2019-02-09



# サイバーシティーは眠らない。

大人になるとゲームをする体力がなくなる。

#エンジニア でも、プログラミングには、体力が必要。

今日、睡眠不足の僕は、ほんの少しの作業でもごそっと体力を奪われる。

でも子供は実は、体力があるののではなく、ゲームが本当に面白くて、眠らない。 <https://t.co/l2zHU6V43B>

# 今いるアジャイル開発チームの哲学。

問題は個人のものじゃない。チームのもの。

これは何度口癖にしていても、いい足りないテーマ。

責任を属人化しない。

哲学と言えば、聞こえは良いが、ことあるごとに、口に出して確認しないと、人間はつい、自分も含め、個人を責める。

#エンジニア

# 今の日本で、プログラマーと聞いたら、何を思い浮かべるか。

昔のイメージは、コーディングの作業員。

今は少し、システムエンジニアに近づいただろうか。

言葉の定義の問題ではあるけれど。

プログラミングがアートとして認められるには、まだ少し時間がかかるだろうか。

#エンジニア

# 完全なアプリケーションは存在しない。

だがAPIや連携用ツールを使い、学習コストを支払えば、近いものが実現できる時代。

Twitterでつぶやくだけで、はてなブログにも、Medumにも、Slackにも、Evernoteにも、GoogleDocsにも、記録される。

接着剤スキルで、天国に近づく。

#エンジニア <http://twitter.com/YumaInaura/status/1094205431226888192>


# サイバーシティーは眠らない。

大人になるとゲームをする体力がなくなる。

#エンジニア でも、プログラミングには、体力が必要。

今日、睡眠不足の僕は、ほんの少しの作業でもごそっと体力を奪われる。

でも子供は実は、体力があるののではなく、ゲームが本当に面白くて、眠らない。 <https://t.co/l2zHU6V43B>

# 今いるアジャイル開発チームの哲学。

問題は個人のものじゃない。チームのもの。

これは何度口癖にしていても、いい足りないテーマ。

責任を属人化しない。

哲学と言えば、聞こえは良いが、ことあるごとに、口に出して確認しないと、人間はつい、自分も含め、個人を責める。

#エンジニア

# 今の日本で、プログラマーと聞いたら、何を思い浮かべるか。

昔のイメージは、コーディングの作業員。

今は少し、システムエンジニアに近づいただろうか。

言葉の定義の問題ではあるけれど。

プログラミングがアートとして認められるには、まだ少し時間がかかるだろうか。

#エンジニア

# 完全なアプリケーションは存在しない。

だがAPIや連携用ツールを使い、学習コストを支払えば、近いものが実現できる時代。

Twitterでつぶやくだけで、はてなブログにも、Medumにも、Slackにも、Evernoteにも、GoogleDocsにも、記録される。

接着剤スキルで、天国に近づく。

#エンジニア <http://twitter.com/YumaInaura/status/1094205431226888192>

# Twitterで賢者だって見つかる。

たとえばITで #フリーランス を目指す人は、@Seiver17808307 さんのツイートを全部読んだ方が良い。

全ての140文字に、知恵が凝縮されていおり、思索ここに極まれり。

ところで有名なスポーツ選手も、リアルで会うと、全ての発言が名言レベルだとか。

#エンジニア <https://t.co/b6dF110J0j> <http://twitter.com/YumaInaura/status/1094376932047675392>

# 人間インタプリタの量産なるか。

 #エンジニア <https://t.co/gFLy9ii332> <http://twitter.com/YumaInaura/status/1094379727962296320>

# 雪見だいふくTwitter。

Twitterのツイートは一瞬でフローして、雪のように消える。

理屈は分かるけど、不思議だった。

今思うにSNSなどのサービスでは、人間の注意関心のパイを分配する。

それがホットな今現在に、ほぼ集まるのがTwitter。

アテンションは有限のリソース。

#エンジニア #記録 <https://t.co/8RdCsRPXhs> <http://twitter.com/YumaInaura/status/1094396392057987072>

# <#CG3HYRLT1|twitter> の最大の弱点。

フローすぎて、ストックが弱い。もはや諦めの境地。

Google検索できない、数珠のツイートたちは、闇へ。

公式機能のモーメントもあるが、なんか違う。外部まとめサイトもコスト高。

僕は一個のツイートさえ、はてなブログと連携させて、橋をかけておく。

#エンジニア <https://t.co/8RdCsRPXhs> <http://twitter.com/YumaInaura/status/1094402423840329729>

# Twitterのツイートを、自動でブログ化。twilogより柔軟に。

ハッシュタグをつけたツイートを、1日分まとめて、はてなブログやmediumに自動投稿。

僕はつぶやくだけで良い。他はなにもしない。

この写真はGithub Issue のもの。IFTTT や Zapier 活用し、楽園の実現。

#エンジニア <#CG3HYRLT1|twitter> <https://t.co/JEzglZ6jZV> <http://twitter.com/YumaInaura/status/1094404353417334784>

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/572









<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Windows 10 Pro x64 + Excel2016 x86 VBA で GetOpenFilename でファイルを開く

#目的
[DTPicker](https://qiita.com/tabizou/items/9001ba288091ddd33901)を使える状態にするとCommonDialogも使えるのだけど
今回はGetOpenFilenameを試す
各パラメータについては[Application.GetOpenFilename メソッド (Excel)](https://msdn.microsoft.com/ja-jp/VBA/excel-vba/articles/application-getopenfilename-method-excel)を参照
##サンプルコード
```vb
Private Sub CommandButton1_Click()

    Dim strFile As String

    strFile = GetFileName

 Debug.Print strFile

End Sub

Function GetFileName() As String
'
    Dim FileFilter      As Variant
    '
    ' 定義はしているが今回は未使用
    '
    Dim Title           As Variant
    Dim FilterIndex     As Variant
    Dim MultiSelect     As Variant
    Dim fileToOpen      As Variant
'
    FileFilter = "テキストファイル (*.txt), *.txt,CSVファイル (*.csv), *.csv"
'
    fileToOpen = Application.GetOpenFilename(FileFilter)
'
    If fileToOpen <> False Then
        GetFileName = CStr(fileToOpen)
    Else
        GetFileName = Space(0)
    End If'
End Function
```
React の render で、なにかわからないエラーが出る

\<A> タグを使ったボタンを描画する JSX を書きました。すると、下記のエラーが発生しました。

```bash
ERROR in [at-loader] ./src/index.tsx:91:12 
    TS2322: Type '{ children: string; class: string; href: any; download: any; }' is not assignable to type 'DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>'.
  Property 'class' does not exist on type 'DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>'.
```

参考にしたソースコードは、 [AJAX and APIs - React](https://reactjs.org/docs/faq-ajax.html) です。例題では item の list を取得して描画させるようになっていましたが、私はボタンを出したかったので、JSX の部分を書き換えました。

はじめは、 href と download に渡す変数の型がわるいのかな？と思いましたが、そうではありませんでした。

[React not rendering classes on elements](https://stackoverflow.com/questions/39442184/react-not-rendering-classes-on-elements) を読んで、ハッ！と気が付きました。

たしかに、予約語だから使えるわけがない！ しかも、よくエラーをみると、 `Property 'class' does not exist` とあるし。エラーの一行目しか見ないのは悪いクセだ。

よくあるサンプルコードには、アトリビュートを付けているものはないし、エラーが発生して困っている記事もないので、見つけるのに苦労しました。

`class="button"` ではなく、 `className="button"` と書きましょう！

```typescript
class GetItemListButton extends React.Component<any, any> {
  constructor(props: any) {
    super(props);
  }

  handleClick() {
    DOM.render(<ItemList />, itemlist);
  }


  render() {
    return (
      <a className="button" onClick={this.handleClick}>Go!</a>
    );
  }
}
```

そういえば、とある JavaScript のライブラリは klass と使っていたのを思い出しました。
#Github issue を作成すると #Medium #API で新規ポストする自動連携の例。Zapierを利用。

#Github issue を作成すると #Medium #API で新規ポストする自動連携の例。Zapierを利用。

# 結果の例

タグも指定できている

なんと画像は自動的にコンバートされて、Mediumにホスティングしてくれている、すげえ、画像をポストするAPIを別途叩く必要がないみたいだ

![image](https://user-images.githubusercontent.com/13635059/52520046-ebe00b00-2ca7-11e9-9bee-33a04d62c491.png)

# Medium API の取得

Mediumユーザーの設定ページから
項目がなければサポートに連絡して有効化してもらう

# Github issue の作成がトリガー

![image](https://user-images.githubusercontent.com/13635059/52520050-fc908100-2ca7-11e9-8f46-456054281b2a.png)

# Code by Zapier の python 実行をアクションにする

title
content
url 

にそれぞれ Github issue のデータを入れる

token には直接 Medium API Application トークンを入れる


![image](https://user-images.githubusercontent.com/13635059/52520058-16ca5f00-2ca8-11e9-8283-84479f2c28fd.png)
![image](https://user-images.githubusercontent.com/13635059/52520062-2184f400-2ca8-11e9-983a-50d4f4419233.png)

# Script

なんと format を指定すると、markdownのままポスト出来る
最初は Zapier  の Formatter で Markdown to HTML 変換をしようと思ったが、必要なかった

タイトルのハッシュタグをパースして、Mediumのタグとして扱っている


```
# -*- coding: utf-8 -*-

import requests
import re

# Get me author id
me_api_url = 'https://api.medium.com/v1/me'

me_api_headers = {
 'Authorization': 'Bearer {}'.format(input['token'])
}

me_api_res = requests.get(me_api_url, headers=me_api_headers)
author_id = me_api_res.json()['data']['id']


# Post Story
# https://github.com/Medium/medium-api-docs#33-posts

url = 'https://api.medium.com/v1/users/{author_id}/posts'.format(author_id=author_id)

headers = {
 'Authorization': 'Bearer {}'.format(input['token']),
 'Content-Type': 'application/json',
}

# タイトルからハッシュタグを抽出してQiita API 用に整形
title_hashtags = re.findall(r'#([^\s]+)', input['title'])
medium_tags = []
for title_hashtag in title_hashtags:
    medium_tags.append(title_hashtag)

# タイトルでハッシュタグが見つからなかった時
if not medium_tags:
    medium_tags = []


json = {
  "title": input['title'],
  "contentFormat": "markdown",
  "content": input['content'],
  "canonicalUrl": input['url'],
  "tags": medium_tags,
  "publishStatus": "public"
}

res = requests.post(url, headers=headers, json=json)

output = res.json()
```



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/569








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
LaravelプロジェクトのコードをCircleCI上のPHPStanで静的解析してreviewdogにコメントしてもらう

# 個人開発でもCIがしたい
2016年6月に[SonarQubeでPHPのコードを静的解析する](https://qiita.com/kadoyau/items/70f4a403b42847e4ed00)という記事を書きました。
その中で、「静的解析の結果がGitHub上にコメントされることが修正には大事」だということも書きました。
2019年現在（というよりもう結構前から）、SonarQubeのPull Requestへのコメント機能は有償の機能の一部になっています。
個人開発で同じようなことができないかなーということで表題のような構成を試してみました。

なお、SonarQubeを完全に代替できるわけではありません。SonarQubeは過去からの推移がみられるダッシュボードがあったり、GUIで細かくルールが決められて便利。

# やったこと
[![Image from Gyazo](https://i.gyazo.com/0d814441414a2bd297143896c2514750.png)](https://gyazo.com/0d814441414a2bd297143896c2514750)
このような感じで、PRを出したら、変更点に対して静的解析の結果をコメントしてもらいたい。

# 登場人物
- PHPStan：静的解析ツール。
 - Larastan： PHPStanのLaravel向けラッパー。
- reviewdog： Gitのdiffと解析ツールの結果をまとめてGitHubに通知してくれる。今回はPHPStanの解析結果をGitHubにコメントしてもらうために使う。
- CircleCI： YAMLで設定を書くとコンテナ上で命令を（例えばテストを回すとか）実行してくれるプラットフォーム。今回はGitHubのリポジトリを引っ張ってきてPHPStanを実行し、結果をreviewdogに渡すために使う。
- Laravel： PHPのWAF。テスト対象のアプリケーションの例。

# やりかた
https://scrapbox.io/kadoyau/Larastan_+_reviewdog_+_CircleCI
自分の知っていることはすべてScrapboxに書き出しており、説明が楽なためにここからはScrapboxでみてください。Qiitaさん、ごめんなさい（ぺこり）
osmium export と Tippecanoe のパイプによるベクトルタイル生産の速度

# 高効率生産のための、パイプライン手法とは
国連ベクトルタイルツールキットのコミュニティ形成施策として、planet.osm.pbf からなるべくダイレクトにベクトルタイルを生産する手法を研究しています。

現在、次のステップで生産する方法の迅速化を研究しているところです。

1. osmium extract で z=6 のタイル範囲の塊（モジュール）にデータを分割する。
2. osmium export で GeoJSON Text Sequences に変換。
3. その GeoJSON Text Sequence を Tippecanoe に入れる直前に、地物単位でデータを加工。
4. Tippecanoe でモジュール単位の mbtiles を生産。

なお、生産したモジュール単位の mbtiles をホストするサーバの最新型は、[onyx](https://github.com/un-vector-tile-toolkit/onyx) です。

一時ファイルの読み書きのための領域と処理時間を節約し、パイプライン化の一般的な速度利益を享受するため、上記ステップの 2., 3., 4. をプロセス間のパイプで繋ぐコードである [produce-320](https://github.com/hfu/produce-320)を試作しました。

コミュニティ形成施策のために用意しているサーバのストレージ容量の制限のため、試作範囲はいわゆる Null Island を中心とする 320 モジュールに限定しています。

# 計測結果
この試作において、計測した生産速度を共有します。

- 以下の速度計測において、対象とするモジュールは [6-32-24](https://hfu.github.io/tapioca-six/#6.25/38.758/14.055)です。シチリア島全島と、いわゆるイタリアのつま先部分が含まれています。
- 使用した計算機は MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports), CPU 2.3GHz Intel Core i5, メモリ 8GB) です。
- osmium extract の開始から終了まで、7分4秒かかりました。
- osmium extract の終了から Tippecanoe の終了まで、7分38秒かかりました。
- 全体で、14分42秒かかったことになります。
- なお、全体のプロセスは２並列で処理するようにキューに入れているので、データセット全体を見たときに、モジュール生産所要時間の目安はこの半分程度ということになることになります。

今後、osmium extract もパイプラインに繋げることで、さらに速度が向上しないか試してみたいと思います。改造版は [produce-320neo](https://github.com/hfu/produce-320neo) という名前の別レポジトリで進めるつもりです。

## この手法の特徴として考えていること
国連ベクトルタイルツールキットが採用しているこの手法の特徴は、ソースデータをなるべくトラップすることなく、シリアルかつダイレクトに（つまり、ストリーム的に）ベクトルタイルに変換していくということですね。これまでの作業も含め、国連ベクトルタイルツールキットが目指す3つの価値というのは、次の3つではないかと考え始めています。

### 性能
ベクトルタイルのサイズを調整しやすい機構 (modify.js) を持ち、既存の vt-optimizer のような計測手段と組み合わせることで、画像タイルよりも高速性を確保することを支援する。
### 相互運用性
様々なウェブ地図ライブラリから利用できるよう、データのシンプルさを確保し、相互運用性を確保できるようなサーバ側の支援を行う。
### 透過性
原型データのデータ構造をなるべく崩さない形でベクトルタイルに持っていく方法を提供することで、ベクトルタイル提供の安定性を確保し、原型データの生産・管理の仕事との一体性を確保する。
楽天RSSで使えるオプション用証券コード最新版をサーバから抽出するスクリプト

#はじめに

楽天RSSを用いると（楽天証券の口座を持っている人は）、リアルタイムで株価や取引板情報等が取得できます。この時に必要なものは表示したい銘柄等の証券コードです。

株の証券コードは一般的に一度決まれば、ほとんど変更がありません。しかし、オプションはほぼ毎週、限月の違う新規銘柄が追加で新規設定されます。また、相場状況や市場関係者のリクエストに応えてオンデマンドで追加設定される場合もあります。

　残念ながら、オプションのコード体系は利用者が皆不幸せになるような、極めてわかりにくいものになっています。

　こちらのページでは、最新のオプションのコード一覧表、およびそのデータを作成したスクリプトをメモ代わり＋自分用に載せておきます。

#最新版データ(2019 feb 22)
最新版のデータのみが欲しい方はこちら：

[オプション用証券コード最新版（CSV）](https://raw.githubusercontent.com/zaq9/nk225_list/master/op_code/op_code_list.csv)


※形式（CSV）

| lb      |    CODE |   
|:-----------------|------------------:|
|03/C8000          |     144158018 |  
|03/C9000         |    194039018|  



#最新版をサーバから抽出するスクリプト
 [実行できるcolab上のノートブック](https://colab.research.google.com/github/zaq9/nk225_list/blob/master/op_code/op_code_list.ipynb)

取引所サーバから最新の「清算値」ファイルを読込
コード関連データを抽出　⇒　使いやすい形に加工　⇒　CSV保存　という流れです。

```py
import pandas as pd
import requests
from bs4 import BeautifulSoup

sv = 'https://www.jpx.co.jp'


def latest_csv_path():
	"""
	:return: str
		JPXサーバ内にある最新の清算値CSVファイルへのPATH
	"""
	req = requests.get(sv + "/markets/derivatives/jnet-derivative/index.html")
	soup = BeautifulSoup(req.content, 'html.parser')
	return soup.find(class_="component-file").a.get('href')


def csv_to_df(csv_path, max_maturity_day=90):
	"""
	清算値CSVファイルをDataFrameに変換
	Parameters
	----------
	csv_path : str
	max_maturity_day :  int , default 90
		最大、SQ期日が何日後までのデータを取得するか（規定値９０日後）
	Returns
	-------
	DataFrame

	"""

	colName = ("CODE", "NAME", "TYPE", "MATURITY", "STRIKE",
	           "PRICE", "TPRICE", "NK", "IV", "R", "TIME", "BASE")
	df = pd.read_csv(sv + csv_path, skiprows=3, encoding="SHIFT-JIS", names=colName)
	df = df.query(
		'BASE=="日経225"').query(
		f'TIME<={max_maturity_day} ').dropna()
	df = df.assign(
		PRICE=df.PRICE.astype(int),
		STRIKE=df.STRIKE.astype(int),
		lb=df['MATURITY'].astype(str).str[4:] + '/' + df.TYPE.str[0] + \
		   df['STRIKE'].astype(int).astype(str)).set_index(
		'lb')[["CODE", "PRICE", "TYPE", "STRIKE", "MATURITY", "IV"]]
	return df


csv_path = latest_csv_path()
df = csv_to_df(csv_path)
df[['CODE']].to_csv('op_code_list.csv')

```
DockerでWindowsを操作できるAnsibleコンテナを構築する

#CentOS7のDockerイメージを取得

```docker
$ docker pull centos:centos7
centos7: Pulling from library/centos
a02a4930cb5d: Pull complete
Digest: sha256:184e5f35598e333bfa7de10d8fb1cebb5ee4df5bc0f970bf2b1e7c7345136426
Status: Downloaded newer image for centos:centos7
```
イメージが取得できました。

```docker
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              centos7             1e1148e4cc2c        2 months ago        202MB
```

#コンテナを作成して起動する
```docker
$ docker run -it -d --name ansible centos:centos7
7e7004684726b5e5cb2269c39a4ae0c727f723c74a9ea4ccdecc40bf6b2fc716
```

正常に起動しています。

```docker
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7e7004684726        centos:centos7      "/bin/bash"         46 seconds ago      Up 44 seconds                           ansible
```

#コンテナに入る
```docker
$ docker exec -it ansible /bin/bash
[root@7e7004684726 /]#
```

#sshをインストール
```docker
[root@7e7004684726 /]# yum install -y openssh-server openssh-clients sshpass
```

#pywinrmをインストール
AnsibleでWindowsを操作するにはpywinrmが必要です。
まずはpythonのバージョンを確認。

```docker
[root@7e7004684726 /]# python --version
Python 2.7.5
```

Python 2.7.5はpipが付属していないので、以下のコマンドでpipをインストールします。

```docker
[root@7e7004684726 /]# curl https://bootstrap.pypa.io/get-pip.py | python
[root@7e7004684726 /]# pip --version
pip 19.0.2 from /usr/lib/python2.7/site-packages/pip (python 2.7)
```

最新版のpipがインストールできたので、pywinrmをインストールします。

```docker
[root@7e7004684726 /]# pip install pywinrm
[root@7e7004684726 /]# pip list | grep pywinrm
pywinrm             0.3.0
```

#Ansibleをインストール
```docker
[root@7e7004684726 /]# yum install -y epel-release
[root@7e7004684726 /]# yum install -y ansible
[root@7e7004684726 /]# ansible --version
ansible 2.7.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
```

Windowsを操作できるAnsibleコンテナが完成しました！
bunderについてごちゃごちゃしてきたので一度まとめようと思う

# 最初に
budlerについてコマンドやコマンド毎の動きがごちゃごちゃになってきたので一度整理のために記事を書こうと思います。

# そもそもbundlerってなに？
bundlerはgemのパッケージ管理ツールである。
### もうちょっと細かく
gemはRubyでつかうライブラリをgemという形式にしたもので、bundler(これもgemの一種)を使ってインストール、アンインストールできるようになる。「gem A」を使うのに「gem B」が必要な場合がある。これを**依存関係**という。bundlerはこの依存関係を考慮してgemをインストールしてくれる。
簡単に言うとbundlerがgem同士の関係を良くして使える状態にしてくれるということ。

# gemfileとgemfile.lock

### gemfileとは
gemfileは自分が使用したいgemの一覧を記述しておく場所です(バージョン指定もできる)。bundlerは基本的にこのファイルを参考にgemをインストールします。(設計図みたいな感じ)

### gemfile.lock
gemfile.lockはgemfileを参考にbundlerがgem同士の依存関係を考慮した結果を記述してくれる。gemfile.lockがあることで実際にどんなgemがインストールされたのか、gemのバージョンが何なのかがわかるため、開発環境や本番環境、複数人での開発の際に環境を合わせることができます。

# bundle installとbundle update
### bundle install
・gemfileにgemが追加された場合
gemfileに追加されたgemとそのgemと依存関係にあるgemをインストールされ、gemfile.lockにそれらのgemが更新される。
・gemfileに変更が無い場合
gemfile.lockに従いgemがインストールされる。gemfileは参照されず、gemfile.lockは更新されない。

### bundle update
gemfile.lock内のバージョンは無視して、gemfile内のgemのバージョンを依存関係を考慮しながら、指定したバージョンもしくは最新のバージョンをインストールする。そしてgemfile.lockに新しいバージョンが記述される。gemfile.lockの中身を新しくしてくれる。

### 性質の違いによる使い方
gemfile.lockに記述されているgemでbundle installしなおせば、他の環境でもgemのバージョンを揃えることができる。複数人との開発でも環境を共有できる・

### 参考URL
bundle installとbundle updateの違いについて
https://qiita.com/lasershow/items/1a048d03ddaaba98171e
bashでランダムに同階層のファイル名を1つ取得する

# 同階層の全ファイル中からランダムでファイル名を1つ取得
## スクリプト
以下に実際のスクリプトを載せます.

```bash
# ファイル数の取得
file_num=$( ls -F | grep -v / | wc -l )

# 取得するファイル番号の決定
let select_num=RANDOM%file_num

# ファイル名の取得
choiced_file_name=$(
ls -F | grep -v / | 
while read file_name
do
  if [ $select_num -eq 0 ]; then
    echo $file_name
  fi
  let select_num--
done )
```

これらをいくつかの部分に分解して説明していきます.

## ファイル数の取得
```bash
file_num=$( ls -F | grep -v / | wc -l )
```
`ls -F`でファイルやフォルダを出しますが, `-F`があるのでフォルダ名の後ろに`/`が付きます.
それを`grep`に渡し, `-v`オプションで`/`を含まないようなものを列挙させます.
そして`wc`でその行数を数え, それを`file_num`へ格納します.

## 取得するファイル番号の決定
```bash
let select_num=RANDOM%file_num
```
bashでは特別な変数`$RANDOM`に$0\sim32767$の間の値がランダムで格納されています.
それを先ほど取得したファイル数で剰余演算した結果を`select_num`へ格納します.

こうすることで`select_num`には$0\sim(ファイル数-1)$内の範囲にあるランダムな格納されることになります.
厳密にいえばすべての値が一様の確率で出てはいないですが…

## ファイル名の取得
```bash
choiced_file_name=$(
ls -F | grep -v / | 
while read file_name
do
  if [ $select_num -eq 0 ]; then
    echo $file_name
    break
  fi
  let select_num--
done )
```
流れ的には
1. ファイル名の一覧を出す
2. 一行読みだし, `$file_name`へ格納する
3. `select_num`が0なら`$file_name`を出力し, ループから抜け出す
4. `select_num`の値を1つ減らす
5. 2へ戻る
という感じです.

# 同階層のある条件にあうファイル名をランダムで1つ取得する
## スクリプト
以下に実際のスクリプトを載せます.

```bash
# ファイル数の取得
file_num=$( ls *.txt -F | grep -v / | wc -l )

# 取得するファイル番号の決定
let select_num=RANDOM%file_num

# ファイル名の取得
choiced_file_name=$(
ls *.txt -F | grep -v / | 
while read file_name
do
  if [ $select_num -eq 0 ]; then
    echo $file_name
  fi
  let select_num--
done )
```
`ls`の後ろに条件を書くだけです.
RustでDI(依存注入)する

ちょっとした気づきがあったのでメモ

# dyn Traitを用いたDI

アプリケーションを設計する上でClean ArchitectureなどDIを多用するケースがありますが、Rustで実装するにあたり構造体フィールドに対して `dyn Trait` を用いた動的ディスパッチのみが実現方法だと私は勘違いしていました。

```rust
struct UserInteractor {
    user_repository: Box<dyn UserRepository>,
}

impl UserInteractor {
    fn get_all_user(&self) -> Vec<User> {
        self.user_repository.get_all_user()
    }
}
```

# Genericsを用いたDI
一方でGenericsを用いたDIも可能だったようで、コードに起こすと以下のようになります。

```rust
struct UserInteractor<T>
where
    T: UserRepository,
{
    user_repository: T,
}

impl<T: UserRepository> UserInteractor<T> {
    fn get_all_user(&self) -> Vec<User> {
        self.user_repository.get_all_user()
    }
}
```

Genericsを用いた構造体定義が可能なものとは理解していたのですが、この場合のメソッド定義方法が分からず頓挫していました。
今思うと`impl`キーワードにTrait境界を記述するだけでした。

以下はClean Architecture風の雑な一連のコードです。

```rust
#[derive(Debug)]
struct User {}

trait UserRepository {
    fn get_all_user(&self) -> Vec<User>;
}

struct MockUserRepository {}

impl UserRepository for MockUserRepository {
    fn get_all_user(&self) -> Vec<User> {
        vec![User {}]
    }
}

struct UserInteractor<T>
where
    T: UserRepository,
{
    user_repository: T,
}

impl<T: UserRepository> UserInteractor<T> {
    fn get_all_user(&self) -> Vec<User> {
        self.user_repository.get_all_user()
    }
}

fn main() {
    let user_repository = MockUserRepository {};
    let user_interactor = UserInteractor { user_repository };
    let users = user_interactor.get_all_user();
    println!("{:?}", users);
}
```

*Rust ver 1.32.0*
AWS CloudFormationでできない設定

# はじめに
AWSのインフラ構築をする際に手でポチポチすることもできますが、
CloudFormationを使うと無料で自動で構築できます。

利点は以下になると考えています。

- テンプレートを作成しコード化すると同じ構成を作成しやすい
- 変更したスタックのみを更新できる
- バージョン管理ができる

しかし、CloudFormationでAPI GatewayのWAFの設定はできませんでした。

# API GatewayのWAFの設定
CloudFormationでAPI Gatewayに設定できるリソースは↓です。
[Amazon API Gateway リソースタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-reference-apigateway.html)

2018年11月にAPI GatewayにWAFを有効化できるようになったばかりなので、
まだCloudFormationに対応していないのかもしれません。

## 手で設定
AWSのコンソールのAPI Gatewayの画面でデプロイしているステージから設定タグを開きます。
WAFを設定する項目があるので、デプロイしているWAFを選びます。
<img width="607" alt="select_waf.png" src="https://qiita-image-store.s3.amazonaws.com/0/356260/07dc605a-1359-b24b-f162-02bbb93b8ae9.png">

# おまけ
re:Invent 2018で発表されたDynamoDBオンデマンド(従量課金)をCloudFormationで指定する方法です。

```yml:template_dynamo.yml
TextDynamoDB:
  Type: AWS::DynamoDB::Table
  Properties:
    AttributeDefinitions:
      - AttributeName: table_key
        AttributeType: S
    KeySchema:
      - AttributeName: table_key
        KeyType: HASH
    BillingMode: PAY_PER_REQUEST
    TableName: table_name
```
`BillingMode: PAY_PER_REQUEST`と書くとオンデマンドになります。

# 最後に
CloudFormationで設定できない項目が他にもあるかもしれないので、
ご存知の方はコメントいただけると嬉しいです！