OmniAICreator/Qiita-1.07M huggingface dataset:
Qiitaにポートフォリオの内容を書いてみる（随時更新）

# はじめに
2018/10/1からフリーランスエンジニアになりました。NARIと申します。
ポートフォリオがないので、Qiitaに内容を書き出してみます。

* ポートフォリオできました： https://naritech.dev/

# できること
①Web制作（Webサイト、Webサービス）
②フロントエンド開発（HTML / css / less / javascript / jQuery / Google Closure)
③バックエンド開発　(Java / PHP)
④DB設計 (SQL / firebase)
⑤要件定義
⑥プロダクトのグランドデザイン
⑦UI設計
⑧ディレクション/チームマネジメント
⑨コードレビュー、教育
⑩その他：イベント企画

基本的に自力で設計して実装する力はあります。
スピード感もって完成させることが強みです。

# 現状できないこと
①インフラ構築
②wordpress構築

# 実績（個人開発）

##■[LINE Bot]コスパごはん：位置情報から食べログ3.5以上を検索できるBot ★Qiitaトレンド入り★
https://qiita.com/NARI_Creator/items/f29112e6f604c86b3c0d

初回リリース：開発期間2日
1ヶ月で3000人の登録突破

J-Castに取り上げられました▼
https://www.j-cast.com/trend/2018/08/13336051.html

##■Coder-100Days：#100DaysOfCode をしてる人を見やすいタイムラインで見れます
URL: https://coder-100days.herokuapp.com/

note: [最速リリース]Coder 100Days作った
https://note.mu/narith/n/n2bd8e32a40d0
開発期間：4.5時間


##■質問するゾウ：LINEから匿名で質問ができる（Twitterへ連携して回答が見れる）
https://twitter.com/NARI_Creator/status/1012489777243754496

開発期間：3日ほど

##■遊び場さがし:イベント情報検索LINE Bot
https://qiita.com/NARI_Creator/items/8071c19503869b1185ee

開発期間：5時間ほど

##■入江開発室ポートフォリオ (チーム開発)
URL: https://irie-dev.co/

企画と開発としてプロジェクトを進行して1ヶ月でフルリモートで完成。

##■Chrome拡張機能：Chatworkの拡張機能
https://note.mu/narith/n/n216482a35efd

# 実績（業務開発）
##■AWANAI賃貸サービス（受託開発）

管理用のCRMとLINE Botを開発
https://awanai.com/

言語：PHP, firabase(Real Time Database), jQuery, LINE Bot Framework
環境：heroku

##■TEAMKIT（リニューアル開発／メイン開発）

プロジェクトメンバー募集プラットフォーム
https://teamkit.jp/

言語：Laravel, Vue.js, MySQL
環境：AWS

# スキル
【スキル/言語】
フロント　： HTML, css, less, Javascript(jQuery/Google Closure/Vue.js)
バックエンド： Java, PHP/Laravel
データベース： SQL, Cassandra, firebase, MySQL
ツール：　Adobe XD、Git, SVN
コミュニケーション： Slack, Chatwork
サーバー： heroku, AWS

# キャリア
ベンダー会社でERPパッケージの開発エンジニア (8年)
　ー フルスタック型としてフロントからバックエンドまで開発経験あり
　ー 多拠点による大規模／チーム開発（海外拠点と開発）
　ー 開発リーダーとしてメンバーの教育／レビュー／スキルアップ
　ー 新規プロダクトのグランドデザインから実装まで
　ー 保守開発／運用改善

事業会社でメディアのWebディレクターを経験

元々COBOL + Delphi + Oracleで3年くらい開発
 -> Web化に伴いJava(Spring) + Google Closure + Cassandraにて開発

(開発量としてはcommitは5000回以上？分からん)

#コンタクト
TwitterにてDMください▼
https://twitter.com/NARI_Creator

ーーーーーーーーーーーーーーーーーーー
ポートフォリオとしては実績が弱い気がする。
”サービスを作った”ことと数値実績をもちたいところ。
どんな課題を解決できるのか？についても加える。

＊完全に自分向けのメモですが、何かあればコメントください。
unsigned char('x') で関数形式の明示的型変換 Explicit type conversion (functional notation) が出来ない理由

型名に `()` をつける関数スタイルのキャストで、MSVC でビルドできていた次のコードが gcc でエラーになると質問を受けました。

なぜコンパイルエラーになるのか即答できなかったので規格にあたりました。

```cpp
#include <iostream>

int main()
{
        char c = 'a';
        auto uc = unsigned char(c);

        std::cout << uc << std::endl;
        return 0;
}
```

```shell-session:
$ g++ -std=c++14 temp.cpp
temp.cpp: In function ‘int main()’:
temp.cpp:6:12: error: expected primary-expression before ‘unsigned’
  auto uc = unsigned char(c);
            ^~~~~~~~
```

# 結論

gcc が正しい。 MSVC は規格通りの挙動をしていない。

# 関数形式の明示的型変換

そもそも `int x = int(0);` のように `型名()` の形式でキャストすることを関数形式の明示的型変換（Explicit type conversion (functional notation)）と規格で呼んでいます。

C++14規格書(N4140) の 5.2.3 Explicit type conversion (functional notation) を見ると、

    [C++11: 5.2.3/1]: A simple-type-speciﬁer (7.1.6.2) or typename-speciﬁer
    (14.6) followed by a parenthesized expression-list constructs a value of 
    the speciﬁed type given the expression list. 

とあり型名には simple-type-speciﬁer か typename-speciﬁer が使えると書いています。

typename-speciﬁer は `typename` キーワードを使うのでここでは関係ありません。

つまり `unsigned char` は simple-type-speciﬁer かどうかが焦点になります。

simple-type-speciﬁer とは何かを調べてみると 7.1.6.2 に定義があります。

    [C++11: 7.1.6.2/1]: The simple type speciﬁers are 
    simple-type-speciﬁer: 
        ...(省略)...
    type-name:
        ...(省略)...
    decltype-speciﬁer:
        ...(省略)...

省略した定義部分には `unsigned char` はありません。また 7.1.6.2 の Table 10 - simple-type-speciﬁers and the types they specify には単数形ではない simple-type-speciﬁer(**s**) の例として `unsigned char` が書かれています。

つまり `unsigned char` や `long long` は simple-type-speciﬁer(**s**) であり simple-type-speciﬁer ではないため関数形式の明示的型変換では使えません。

エラーになる gcc が正しいです。MSVC は妙な Microsoft 拡張をしてるんでしょう。

# 結局どうすれば？

~~MSVC を使わない~~

そもそも関数形式の明示的型変換を使わず static_cast を使う。

# 参考

cppreference: Declarations
https://en.cppreference.com/w/cpp/language/declarations

C++11の文法と機能(C++11: Syntax and Feature)
5.5.3 関数形式の明示的型変換（Explicit type conversion (functional notation)）
http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml#expr.type.conv
Ruby ローカル環境でファイル実行

###結論
処理のみを記述したrubyファイルと与えられる入力値を入れたテキストファイルを作成して

```terminal
$ ruby 実行ファイル.rb < 入力値ファイル.txt
```

##あらすじ
正直な話「[Paiza.io](https://paiza.io/projects/XxGAFs-Ji3DF_Y8tVKTfMA)を使えばいいじゃん」で終わってしまう内容なのですが、数時間ほどググってもやりかたを記載している記事やサイトが見つからなかったので作りました。

##提出するコード（を記述する）ファイルを作成
適当に`sample.rb`などとして保存。editorで開いたあと、処理を記述。

```sample.rb
loop do
  x = gets.split.map(&:to_i)
  break if (x[0] == 0) && (x[1] == 0)

  puts x.sort.join(' ')
end
```

##与えられる入力値のファイルを作成
今回はこちら"[AOJ](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_3_C&lang=jp)"の問題を例に

```text.txt
0 1
1 0
10 10
5758 6838
7515 113
5627 1051
7419 3010
4086 6212
2767 2749
2060 9084
7543 2225
1183 5089
5566 5137
4978 6966
311 495
54 1367
3145 7031
5736 9882
8505 524
2102 8394
0 0
```

##ターミナルにて実行

```terminal
$ ruby sample.rb < text.txt
```
以下が実行結果

```terminal
0 1
0 1
10 10
5758 6838
113 7515
1051 5627
3010 7419
4086 6212
2749 2767
2060 9084
2225 7543
1183 5089
5137 5566
4978 6966
311 495
54 1367
3145 7031
5736 9882
524 8505
2102 8394
```

あんなに調べたのにたったこれだけだなんて・・。
なんでFile.open系の記事ばかりなの・・。
TouchDesigner Group SOPで番号による範囲指定

TouchDesignerのSOPにあるGroup SOPのRangeがよくわからなかったのでメモ。
Rangeパラメーターは、SOPのPrimitiveやPointの番号によるグルーピングが可能になります。

#Primitiveの場合
Group SOPは単体では機能しません。
その前に何らかのSOPが必要なので、そのSOPとノードを繋ぎます。

今回は**Box SOP**と**Group SOP**を繋いでいます。
<img width="474" alt="スクリーンショット 2018-10-02 15.11.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/31194/16b36a85-7c26-6a57-458c-dcf303c4088d.png">

そして上のスクリーンショットではGeometryに番号が付いていますが、Display Optionを表示（SOPをプレビューモードにしてPを押せば出ます）し、**Primitive Numbers**にチェックを入れると表示されます。
![do.png](https://qiita-image-store.s3.amazonaws.com/0/31194/cf3eb14b-3823-d1fb-5bad-92ef66220230.png)

そして次にパラメータの設定です。
![prim.png](https://qiita-image-store.s3.amazonaws.com/0/31194/77db03b5-22d9-abc3-8dc4-6440d3456a52.png)

**1.Entity**
PrimitiveのGroupなので**Primitive**にします。
（デフォルトではPrimitive）

**2.Use Number**
番号による範囲指定をするために**ON**にします。
（デフォルトではOFF）

**3.Operation**
範囲指定のためGroup by Rangeを選択します。
選択肢は下記の3つです。
- Group by Pattern
- Group by Range
- Group by Expression

**4.Start / End**
StartからEndで指定された範囲のPrimitiveがGroupの対象になります。
Endには下記のようなパラメータが入っていますが、これはデフォルトで入っているものです。
意味としては**このGroup SOPへの入力0番目のPrimitiveの数**となります。

```
len(me.inputs[0].prims)
```
今回はBox SOP1つしか繋いでいないのでBox SOPのPrimitiveの数ですね。
Startが0で、EndがPrimitiveの数なので全てのPrimitiveが対象になります。

**5.Select_of_**
これは**何個おきに何個選ぶか**を指定します。
この画像では2個おきに1個選ぶことになります。
つまり、このBox SOPで各Primitiveの番号は「0 1 2 3 4 5」と振られています。
2個に1個なので「0 2 4」と偶数が選択されることになります。

#Pointの場合
基本は一緒です。
今回はBoxではなくGridにしています。
<img width="893" alt="スクリーンショット 2018-10-02 15.39.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/31194/2dd38dc6-7117-ae63-ca33-af3685d6eb70.png">

さらに**Add SOP**を繋いでいますがGrid SOPがPolygonなので、Add SOPでGeometryを削除してPointだけにしています。
![del.png](https://qiita-image-store.s3.amazonaws.com/0/31194/54cd528f-f419-cba6-9c01-7fa0205966f9.png)

そしてパラメータです。
![points2.png](https://qiita-image-store.s3.amazonaws.com/0/31194/92b3ba19-ecf5-d54b-70eb-8188194bdff1.png)


**1.Entity**
Pointsに変更します。

**2.Start / End**
さっきと似ていますが、primsではなく**points**にします。

```
len(me.inputs[0].points)
```

より理解を深めるためにStartを10、Endを上記のパラメータから10引いて90としています。
これで10番目から90番目のPointが選択の対象になりました。

さらにSelect_of_を2と5にしてみました。
これは**5個おきに2個選択**という意味なので、10番目のPointから始めて最初の2個を選択、その後は5個おきに2個ずつ90番目のPointまで選択ということになります。

こういったグルーピングができると、あるGeometryの特定のPrimitiveやPointをTransformなどで動かすことができますね:smiley::raised_hands:
GitExtensions, SourceTreeでVisualStudioをDiffツールに使用する

VisualStudioにGitSourceControlProviderをインストールし、ツリーからdiffを見るためにGitExtensionsを設定してみたが、そのままでは違うエディタが開いてしまう。エディタが違うとソースがパッと頭に入ってこないのでVisualStudioのdiffが出るようにします。

## GitExtentionのdiffツールの設定
設定 -> グローバル設定 -> マージツール & Diffツール -> vsdiffmergeを選択


![2018-10-02_15h25_30.png](https://qiita-image-store.s3.amazonaws.com/0/66405/d1499281-e9a3-f445-21d7-539ad5779558.png)


マージツール

```
"C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/vsDiffMerge.exe" /m "$REMOTE" "$LOCAL" "$BASE" "$MERGED"
```

Diffツール

```
"C:/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/vsDiffMerge.exe" "$LOCAL" "$REMOTE"
```


またここでファイルのエンコードを変更すると、FileHistoryの画面のDiffの画面でSHIFT-JISになり、文字化けを最初から回避できます。

![2018-10-02_15h27_38.png](https://qiita-image-store.s3.amazonaws.com/0/66405/422e760a-adb5-dcff-abb8-9c340745ad5d.png)


## SourceTreeのdiffツールの設定

ツール -> オプション -> Diff -> カスタムを選択

```
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe
-Diff $LOCAL $REMOTE
```

## VisualStudioからdiffを起動

![2018-10-02_15h16_51.png](https://qiita-image-store.s3.amazonaws.com/0/66405/ddcad80f-bf04-0bf8-fffb-cbbd517ba2eb.png)

![2018-10-02_15h43_19.png](https://qiita-image-store.s3.amazonaws.com/0/66405/76235634-c2a0-5953-3129-e175776f3cf6.png)

いいですね。diffとソースエディタのスタイルが同じ方が見やすいです。
TwilioのコールログをCSVに書き出す

:::note alert
2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
:::

# はじめに

この記事では、TwilioのコールログをCSVファイルに書き出すプログラムについて記述しています。
Twilioのコールログ（通話ログ）は、管理コンソールからもダウンロードが可能なのですが、大量のデータをダウンロードすることができません。
そこで、APIを利用してログを書き出すプログラムが必要になります。

## 準備

以下の準備が必要です。
・Twilioアカウント（アップグレードしてなくてもOK）
・Node.jsの実行環境（バージョンは8以上）
・エディタ

## プログラムのダウンロードと初期設定

```console
$ git clone https://github.com/mobilebiz/twilioLogs.git
$ cd twilioLogs
$ npm install
$ cp .env.sample .env
```

- コピーした.envファイルをエディターで開いて、ご自分のTwilioのAccountSidとAuthTokenの値に書き換えます。
- デフォルトでは、すべてのコールログを取得するようになっていますが、もし日付範囲を指定して取得したい場合は、getLogs.jsファイルをエディターで開いて、以下の部分を変更してください。

```javascript
const startTime = moment('2000-01-01T00:00:00+09:00');
const endTime = moment('2200-12-31T23:59:59+09:00');
```

それぞれの日付はJST（日本時間）で指定できるようにしてあります。

## 実行

```console
$ node getLogs.js
```

出力されるCSVファイルは、同じディレクトリのlogs.csvとなります。
出力される項目は以下の通りです。

項目番号|項目名|説明
--:|:--|:--
1|start_time|発信、もしくは着信が開始した時刻（日本時間）
2|end_time|終話した時刻（日本時間）
3|duration|通話時間（秒）
4|from|発信者番号（E.164形式）
5|to|着信番号（E.164形式）
6|status|通話状態（正常終了はcompleted）
7|price|通話料金（円）

Enjoy! Twilio.
【JavaScript】Cookieの取得・追加・削除をメソッド化

最近よくcookieを利用するので、再利用できるようにコードをメソッド化しました。
今のところエラーは出てないので大丈夫なはず・・・

```javascript:script.js
var COOKIES = COOKIES || {
    /*
     指定したcookieの値を取得して返す関数
     第1引数=取得したいcookiename
    */
    getCookie: function(cName) {
        var cookie_name = cName;
        if(cookie_name == '' || cookie_name == null) {
            console.log('COOKIES.getCookie：引数に値を代入してください。');
        } else {
            var set_replace = '(?:(?:^|.*\s*)' + cookie_name + '\s*\=\s*([^;]*).*$)|^.*$';
            var cookie_value = document.cookie.replace(new RegExp(set_replace), '$1');
            return cookie_value;
        }
    },
    /*
     指定したcookieを追加する関数
     第1引数=追加するcookiename;第2引数=追加するcookievalue;第3引数=cookieの有効期限(day)
    */
    setCookie: function(cName, cValue, cTime) {
        var cookie_name = cName;
        var cookie_Value = cValue;
        var cookie_domain = location.hostname;
        var cookie_time = cTime ? (60 * 60 * 24) * cTime : '';
        if(cookie_name == '' || cookie_name == null) {
            console.log('COOKIES.setCookie：第1引数に値を代入してください。')
        } else {
            document.cookie = cookie_name + '=' + cookie_Value + ';domain=' + cookie_domain + ';max-age=' + cookie_time;
        }
    },
    /*
     指定したcookieの値を削除する関数
     第1引数=削除したいcookiename
    */
    deleteCookie: function(cName) {
        var cookie_name = cName;
        if(cookie_name == '' || cookie_name == null) {
            console.log('COOKIES.deleteCookie：引数に値を代入してください。');
        } else {
            COOKIES.setCookie(cookie_name, '', 0);
        }
    }
};
```

cookie値を取得したい場合

```javascript
// cookiename'hoge'の値を取得して変数get_cookieに代入
var get_cookie = COOKIES.getCookie('hoge');
```

cookieを追加する場合

```javascript
// cookiename'hoge'値'hogehoge'を30日間保持
COOKIES.setCookie('hoge', 'hogehoge', 30);
```

cookieの値を削除する場合

```javascript
// cookiename'hoge'の値を削除
COOKIES.deleteCookie('hoge');
```

短くしたやつ

```javascript:script.js
var COOKIES = COOKIES || {
    getCookie: function(cName) {
        if(cName != '' || cName != null) {
            var set_replace = '(?:(?:^|.*\s*)' + cName + '\s*\=\s*([^;]*).*$)|^.*$';
            return document.cookie.replace(new RegExp(set_replace), '$1');
        }
    },
    setCookie: function(cName, cValue, cTime) {
        var time = cTime ? (60 * 60 * 24) * cTime : '';
        if(cName != '' || cName != null) {
            document.cookie = cName + '=' + cValue + ';domain=' + location.hostname + ';max-age=' + time;
        }
    },
    deleteCookie: function(cName) {
        if(cName != '' || cName != null) {
            COOKIES.setCookie(cName, '', 0);
        }
    }
};

```
SSH設定(Mac)

一度設定すると暫く使わなくて、また忘れてしまうので備忘録用に投稿。

## SSHって？
リモートサーバとセキュアな通信ができる仕組み。セキュアがミソ。
TELNETとかFTPはパスワードを平文で送受信しているのでセキュリティ的によろしくない。
SSHはこの後説明するパスワード認証方式と公開鍵認証方式により安全な通信を実現している。

### パスワード認証方式
サーバーに登録したパスワードで通信する。パスワードは暗号化されてる。しかし、当たり前だけど、パスワードが盗まれたら簡単にアクセスされてしまう。

### 公開鍵認証方式
クライアント（パソコン）に秘密鍵を置いて、サーバーには公開鍵を置く。それぞれの鍵は対になってるので、秘密鍵を持ったパソコンでしかアクセスできない。
さらに、秘密鍵へのアクセスにパスフレーズも必要なので万が一パソコン盗まれてアクセスされそうになっても安心。
パスフレーズは秘密鍵へのアクセスに必要なパスで、サーバーへのログインパスではないぜ！

#### 秘密鍵と公開鍵の作成
具体的なMacでの鍵の作り方を解説する。実行すると下記２つの鍵ができる。

- id_rsa　　 （秘密鍵）・・・ クライアントPCに配置
- id_rsa.pub （公開鍵）・・・ 接続対象サーバに登録

オプションについて

- `-t` : 暗号化方式の指定。`rsa`が一番強いので基本これでいい。他に`dsa`とかある。
- `-b` : 鍵の長さ。長ければ長いほど堅牢。でもデフォルトのままでも充分だと思う。
- `-C` : 鍵のコメント。自分のメールアドレスを書いて置くと、`cat`とかした時に分かりやすい。
- `-f` : 秘密鍵のファイル名。

```
$ cd ~/.ssh

$ ssh-keygen -t rsa -b 4096 -C "hoge@example.com" -f ~/.ssh/id_rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):  <-- パスフレーズを入力（任意）
Enter same passphrase again:  <-- もう一度、パスフレーズを入力（任意）
Your identification has been saved in id_rsa.
Your public key has been saved in id_rsa.pub.

$ ls ~/.ssh
id_rsa  id_rsa.pub
```
新しい計算機環境にPython環境整える時の備忘録

# はじめに
Pythonの環境をいろんなマシンに構築する時の方法を統一しておきたかったので、備忘録としてメモ。
それぞれのことについてより詳しく書いている記事も散見されるので参考にさせていただいたリンクも貼っておきます。

##  pyenvを入れる


```bash
$ cd
$ mkdir env
$ cd env
$ git clone https://github.com/yyuu/pyenv.git 
```

## PATHを通す

`.bashrc`とかに以下のように記述を挿入

```bash
export PYENV_ROOT=$HOME/env/pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init --path)"
```

ref : https://qiita.com/SonoT/items/091d2748deb16fb03653

2022/01/15 に更新しました
ref : https://qiita.com/myy/items/a526bdb43982cf82f96a

## Pythonをバージョンを指定してpyenvで入れる

```bash
$ pyenv install -l
Available versions:
~~省略~~
  3.6.4
  3.6.5
  3.6.6
  3.7.0
  3.7-dev
  3.8-dev
~~省略~~
$ pyenv install 3.6.6
Downloading Python-3.6.6.tar.xz...
-> https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tar.xz
Installing Python-3.6.6...
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
WARNING: The Python sqlite3 extension was not compiled. Missing the SQLite3 lib?
Installed Python-3.6.6 to /home/hiroki11x/env/pyenv/versions/3.6.6
```

## インストールしたPythonを全体で使えるように設定

```bash
$ python --version
Python 2.7.15rc1
$ pyenv global 3.6.6
$ python --version
Python 3.6.6
```

ref : https://qiita.com/nsas454/items/c5bd3a535205d434234e


## virtualenvを入れる

```bash
$ pip install virtualenv
Collecting virtualenv
  Downloading https://files.pythonhosted.org/packages/b6/30/96a02b2287098b23b875bc8c2f58071c35d2efe84f747b64d523721dc2b5/virtualenv-16.0.0-py2.py3-none-any.whl (1.9MB)
    100% |████████████████████████████████| 1.9MB 6.8MB/s
Installing collected packages: virtualenv
Successfully installed virtualenv-16.0.0
```



## virtualenvで環境を用意
今回は `wbai` という名前にしておく

```
$ cd workspace/
$ python -m virtualenv wbai
Using base prefix '/home/hiroki11x/env/pyenv/versions/3.6.6'
New python executable in /home/hiroki11x/workspace/wbai/bin/python
Installing setuptools, pip, wheel...done.
```

#### [参考]virtualenvで使うPythonを指定

```bash
$ python -m virtualenv wbai --python=$HOME/env/pyenv/versions/3.7-dev/bin/python3.7
```

ref : https://www.lifewithpython.com/2015/01/python-select-python-interpreter-on-virtualenv.html

## virtualenv環境をActivate

```bash

hiroki11x@titanv:~/workspace$ cd wbai/
hiroki11x@titanv:~/workspace/wbai$ source bin/activate
(wbai) hiroki11x@titanv:~/workspace/wbai$ pip install Pillow
Collecting Pillow
```

ref : https://qiita.com/niwak2/items/5490607be32202ce1314 



## Poetryを使う
ref ; https://python-poetry.org/docs/
新人リーダーが意識すべき５つのこと

#最初に
ある現場に優秀なチームリーダーがいました。
そのリーダーのチームはいつも素晴らしいパフォーマンスを上げていました。
しかし、ある日、そのリーダーがメンバーの一人に言いました。
「来月から育休休暇を一年取得する。お前が次のチームリーダーだ、頼むぞ。」

こんな感じで、プログラマーとしてバリバリやってきた人も、急にチームリーダーを
任されることもあるんじゃないでしょうか？ないでしょうか？

新人プログラマーのひとはこちらをどうぞ。
[新人プログラマーが意識すべき５つのこと](https://qiita.com/nyao/items/f0e58f69735060f903ca)

若手プログラマーのひとはこちらをどうぞ。
[若手プログラマーが意識すべき５つのこと](https://qiita.com/nyao/items/1a855a56b02a0039ea01)


#リーダーが意識すべきこと
急にリーダーになった場合、どうすればいいのかわからないと思うが、以下のことを意識すること。

###１．チームメンバーの管理
チームリーダーはメンバーの状況を常に把握する必要がある。
メンバーの進捗管理は当然として、技術レベル、現在の作業内容、タスク一覧、課題一覧等も把握しておく。

###２．チーム内の問題管理
メンバーの進捗管理をして、技術的フォローを行っていたとしても、チーム内では数々の問題が発生する。
進捗の遅れ、技術的困難、勤怠、人間関係など、問題が発生した場合はできるだけ早く把握し、対応する。
発生した問題が解決できない場合は、プロジェクトマネージャーや上司に打ち上げる。
（解決した場合も報告は上げておく）

###３．チーム外との調整
いちメンバーとして作業していた場合はあまり気にする必要はなかったかもしれないが、チームリーダーは顧客や他チーム（他機能、他システム）との調整が必要になる。
他機能との結合やら、他システムとのデータ連携（フォーマット、連携テスト日程）など調整が必要な項目が多々あり、できるだけ早めに調整しておく必要がある。
またリーダーであればシステムの全体像を把握しておく必要がある。

###４．自分の作業
現場によってはリーダーになっても、メンバーと同じように1人月分の開発作業があったりする。自分の作業がおろそかにならないようにする必要がある。

###５．技術レベルの向上
メンバーを技術的にフォローしたり、様々な作業をこなしつつ開発するためには常に
自分の技術レベルを向上させていく必要がある。


#最後に
チームリーダーでも次の問題解決のプロセスは役立つとおもいますので覚えておきましょう。

プロジェクトとは「コスト」と「納期」と「品質」から成り立ちます。
問題が起きた場合は、そのいずれかを犠牲にするのが一般的です。

コスト → メンバー増員
納期　→　リリース日延期
品質　→　機能削減（品質自体を落とすのはNGですよ！）

私はこれだけ覚えて「プロジェクトマネージャ（情報処理技術者試験）」を一発合格しました。
PINRemoteImageで取得する画像を角丸&影をつける

## 画像を角丸にして影をつける

PINRemoteImageで取得した画像を角丸にして影をつけて表示する処理を実装する機会があったのでその方法を記録します。
角丸にして影をつける処理では、Viewを2つ重ねるサンプルをよく見かけたのですが、Imageで角丸にするやりかたにしました。

(前提) PINRemoteImageをPod等で導入済

1. UIImageViewを配置

storyboardで配置し、outletをつけておきます
![スクリーンショット 2018-09-28 19.25.35.png](https://qiita-image-store.s3.amazonaws.com/0/71946/e0822572-7dbb-43c2-3614-4c68514a8286.png)

2. UIImageViewに画像URLを設定し、画像を角丸に。UIImageViewに影を設定

```
@IBOutlet var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        imageView.pin_updateWithProgress = true
        let imageSize = imageView.frame.size
        imageView.pin_setImage(from: URL(string: "https://upload.wikimedia.org/wikipedia/commons/9/9a/Gull_portrait_ca_usa.jpg"), processorKey: "rounded") { (result, unsafePointer) -> UIImage? in
            guard let image = result.image else {
                return nil
            }
            // 角丸にする処理
            UIGraphicsBeginImageContext(imageSize)
            UIGraphicsBeginImageContextWithOptions(imageSize, false, 0.0)
            let rect = CGRect(origin: .zero, size: imageSize)
            UIBezierPath(roundedRect: rect, cornerRadius: 5).addClip()
            image.draw(in: rect)
            let clippedImage = UIGraphicsGetImageFromCurrentImageContext()

            UIGraphicsEndImageContext()
            return clippedImage
        }

        // 影をつける処理
        imageView.layer.masksToBounds = false
        imageView.layer.shadowColor = UIColor.black.cgColor
        imageView.layer.shadowOffset = CGSize(width: 2, height: 2)
        imageView.layer.shadowRadius = 5
        imageView.layer.shadowOpacity = 0.3
    }
```

<img width="237" alt="スクリーンショット 2018-10-01 10.46.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/71946/5d235bdb-31fc-b79e-2b9a-042a089aa1f0.png">

3. ちなみに

PINRemoteImageを利用しないでローカル画像を利用する場合は以下のようなかんじ

```
if let image = UIImage(named: "kamome.jpg") {
            // 角丸にする処理
            UIGraphicsBeginImageContext(imageView.frame.size)
            UIGraphicsBeginImageContextWithOptions(imageView.frame.size, false, 0.0)
            let rect = CGRect(origin: .zero, size: imageView.frame.size)
            UIBezierPath(roundedRect: rect, cornerRadius: 5).addClip()
            image.draw(in: rect)
            let clippedImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            imageView.image = clippedImage
            
            // 影をつける処理
            imageView.layer.masksToBounds = false
            imageView.layer.shadowColor = UIColor.black.cgColor
            imageView.layer.shadowOffset = CGSize(width: 2, height: 2)
            imageView.layer.shadowRadius = 5
            imageView.layer.shadowOpacity = 0.3
        }
```
Python3 + Pipenv環境をMacに作る


macOSの調子が悪かったので、OSを入れ直した。
ひさしぶりにmacOSにpythonの環境構築をしたので手順をメモしておく。

出来るだけツールの公式が示している手順でインストールを行っていくようにしてある。

## 環境

* macOS High Sierra
* XCode install済み

## 手順

### Homebrewインストール
* macOSのパッケージマネージャーであるHomebrewをインストール。
* 参照: https://brew.sh/index_ja

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

### Python3インストール

brewでインストール。

```bash
$ brew install python3
```

バージョンを確認してみる。3.7.0が入った。

```bash
$ python3 -V
Python 3.7.0
```

### Pipのインストール

* Pythonのパッケージ管理ツールであるpipをインストールします。
* https://pip.pypa.io/en/stable/installing/

色んなインストール方法があるけど、経験的には、pypaに掲載されているget-pip.pyを使った方法が安定してる気がする。

```bash
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python3 get-pip.py
```

入った。

```bash

$ pip -V
pip 18.0 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)
```

### Pipenvのインストール

* pipが管理してくれるよりももう少し幅広い管理をしてくれるpipenvをインストールする。
* 参考: https://pipenv-ja.readthedocs.io/ja/translate-ja/

brewで入る。

```bash
$ brew install pipenv
```

```bash
$ pipenv --version
pipenv, version 2018.7.1
```

## 確認

```bash
$ pipenv install --python 3.7 pandas
$ pipenv shell
$ python -c "import pandas; print(pandas.__version__)"
0.23.4
```

できた。
Node.js/Ruby/Pythonのバージョン管理は-env系で統一

仕事上、メインの API サーバは Ruby on Rails、Lambda やマイクロサービス的な小さいサーバは Node.js、一部 DevOps 関連のスクリプトを Python で書いてたりする。

各種プログラミング言語を使うときは言語自体のバージョン管理が必要となるが、`-env` 系のバージョン管理ツールで統一するとコマンドがいっしょなので便利。  
そして Mac でも Linux でも使える（これ超大事）。

* Node.js - [nodenv](https://github.com/nodenv/nodenv)
* Ruby - [rbenv](https://github.com/rbenv/rbenv)
* Python - [pyenv](https://github.com/pyenv/pyenv)


## Mac へのインストール方法

```
$ brew install nodenv
$ brew install rbenv
$ brew install pyenv
```


## 基本的なコマンド

### インストール可能なバージョン一覧

```
$ rbenv install -l
```

### インストール

```
$ rbenv install 2.5.1
```

### インストール済のバージョン一覧

```
$ rbenv versions
```

### アンインストール

```
$ rbenv uninstall 3.6.5
```

### インストールしたバージョンをシステム上でグローバルに利用する

```
$ rbenv global 3.6.5
```

### インストールしたバージョンを現在のディレクトリだけで利用する

```
$ rbenv local 3.6.5
```

カレントディレクトリに `.ruby-version` ファイルが生成されるので `rbenv` はこれを参照して指定のバージョンを利用する仕組み。

## fish shell によるパス設定

bash を使ってる場合 `~/.bash_profile` を編集する『パスを通す設定』が煩わしい。でも fish shell ならプラグインをインストールするだけ。

* [zshは諦めてたけどfish shell導入したら捗った](http://jnst.hateblo.jp/entry/2016/11/10/005018)


```
$ fisher install rbenv
$ fisher install pyenv
$ fisher install oh-my-fish/plugin-nodenv
```

自分で設定ファイルを `vi` とかで修正する必要がない。

## Node.js のバージョン管理ツールいろいろ

余談。`nodenv` の存在に気づくまでは [nodebrew](https://github.com/hokaccha/nodebrew) を使っていた。  
だいたい同じだけど、カレントディレクトリだけ特定のバージョンを利用する機能はない。  
（あと nodebrew は指定バージョンのインストールで `v10.11.0` みたいに `v` を付けるが、nodenv 系は付けない点に注意。）

```
$ nodebrew ls-remote
$ nodebrew install-binary v10
$ nodebrew ls
$ nodebrew use v10
$ nodebrew uninstall v10
$ nodebrew selfupdate
```

`nodenv` と同じ env 系のバージョン管理ツールとして [ndenv](https://github.com/riywo/ndenv) というものもあるが、こっちはもうメンテナンスされてないので使わない。  
[nodeenv](https://github.com/ekalinin/nodeenv) という一文字違いの紛らわしいものもあるが、まったくの別系統のようだ。ちなみに Node.js を最初に使い始めた 5 年くらい前は [nvm](https://github.com/creationix/nvm) を使っていた気がする。
FireMonkey のレイアウトコンポーネントの種類と使いどころ

FireMonkey には、コンポーネントをグループ化して表示・処理するためのレイアウトコンポーネントがあります
レイヤーを重ねるように画面設計を行なうこともできますし、レイアウトコンポーネントを使って、グループ化することによって、たとえば、レイアウトコンポーネント上のコンポーネントの表示/非表示を同時に行なったり、画面の大きさや回転が行なわれても、常に同じ位置にグループ化したコンポーネントを表示することができます

レイアウトコンポーネントには次のような種類があります（クリックするとドキュメントページに飛びます）

- [TLayout](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.Layouts.TLayout)
- [TScaledLayout](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.Layouts.TScaledLayout)
- [TScrollBox](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.Layouts.TScrollBox)
- [TFlowLayout](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.Layouts.TFlowLayout)
- [TGridLayout](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.Layouts.TGridLayout)
- [TGridPanelLayout](http://docwiki.embarcadero.com/Libraries/Tokyo/ja/FMX.Layouts.TGridPanelLayout)

## TLayout
ノーマルなレイアウトコンポーネント

TLayout を使ってグルーピングされたコンポーネントは、まとめて操作することができます
まとめて、表示 / 非表示の操作を行なう例です
この実行時の例では、スイッチの On/Off が TLayout.Visible と連動します
![layout01.gif](https://qiita-image-store.s3.amazonaws.com/0/164551/9b9dd47e-8d1e-caaa-7f06-25ea23465d52.gif)

TLayout を Anchors で固定した例です
デフォルトは Top と Left ですが、これを Top と Right の固定に変更しています
レイアウトごとで扱われていることが分かるかと思います
![layout02.gif](https://qiita-image-store.s3.amazonaws.com/0/164551/39021522-78d3-410b-a027-0dc59c0a3a47.gif)

## TScaledLayout
拡大縮小の担当
レイアウト上のコンポーネントは拡大されても縮小されてもちゃんと機能しまっせ
この例では、TScaledLayout の Align を Client に設定しています
![scale01.gif](https://qiita-image-store.s3.amazonaws.com/0/164551/bf59c320-4c50-cc8c-af59-5e9debf15b93.gif)

## TScrollBox
スクロール担当
レイアウト上のコンポーネントがレイアウト枠を超えて配置されている場合に、レイアウト内でスクロールさせることができる
レイアウト枠が小さくなると、スクロールバーが現れます
![layout03.gif](https://qiita-image-store.s3.amazonaws.com/0/164551/cc4fb1bb-0ce8-c7a8-61a6-08a1dea86995.gif)

## TFlowLayout
配列系レイアウトトリオのひとつ
配列系のレイアウトは、たとえば電卓のように同じ配分でコンポーネントを並べる際に使うと便利
レイアウトの大きさが変わった場合でも、レイアウト内の枠内に入るように整列してくれる
![layout04.gif](https://qiita-image-store.s3.amazonaws.com/0/164551/97187f2a-22b7-d562-58c2-87ab28b9d3b6.gif)

## TGridLayout
配列系レイアウトトリオのひとつ
グリッドのような縦横のマス内をつくり、その中にコンポーネントを配置することができる
マス目の大きさは、ItemHeight と ItemWidth プロパティの値で決まる (デフォルト64)
TFlowLayout と同様に、レイアウトの大きさが変わった場合でも、レイアウト内の枠内に入るように整列してくれる
![layout05.gif](https://qiita-image-store.s3.amazonaws.com/0/164551/c949e430-f9b2-058d-e307-9e5be7cc6a79.gif)

## TGridPanelLayout
配列系レイアウトトリオのひとつ
TGridLayout と似ているけど、こちらは複数のマス目にまたがってコンポーネントを配置することができる
レイアウトの大きさが変わった場合の動作は、上の２つとは違う動きになるので注意（整列しない）
動画 gif の実行時の画面は、分かりやすいように TRectangle を使ってマス目の色分けを行っています
![layout06.gif](https://qiita-image-store.s3.amazonaws.com/0/164551/e7df4e71-7d17-b737-30ec-7f9a511aa150.gif)

## 参考：

- [FireMonkey のレイアウト戦略](http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/FireMonkey_%E3%81%AE%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E6%88%A6%E7%95%A5)
- [FireMonkey コントロールの配置](http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/FireMonkey_%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%AE%E9%85%8D%E7%BD%AE)
TypeScriptでFunction.bindを使うのはよくない


# 追記
TypeScript 3.2 RC にてBind周りに変更が入りました

詳細については以下の記事を参考にしてください！
https://qiita.com/vvakame/items/79557e00cfe6d3c612cd

# はじめに

みなさんご存知かと思いますが、
JavaScriptの`this`は他の言語では考えられない動きをします。
そこで`this`を固定するために`.bind`関数を使うことが一般的ですが、
TypeScriptの場合はそうはいきません。

# 何故なのか
まずはbindがどういう定義になっているのか見てみましょう

```typescript
 Function.bind(this: Function, thisArg: any, ...argArray: any[]): any
```

はい。
色々と`any`です。

せっかくの型を大事にする言語なのにこれでは台無しです。

# じゃあどうすれば？
マイクロソフト公式がthisの扱いについてページを作っているので
ここを元に解説していきます。[公式](https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript)

## Use Instance Functions

TypeScriptのクラスとしてデフォルトのプロトタイプメソッドではなく、
インスタンスにアロー関数を生やす形で定義します。

```typescript
class MyClass {
    private status = "blah";
    
    public run = () => { // <-- note syntax here
        alert(this.status);
    }
}
var x = new MyClass();
$(document).ready(x.run); // SAFE, 'run' will always have correct 'this'
```

### いい点
- 使用する人が`this`ついて処理漏れが起きません
- 型安全です
- 関数にパラメータがある場合は、追加作業は必要ありません

３つ目についてはどういったメリットなのかはあまり汲み取れていません…
**どなたか分かる方コメントなどでおしえていただけると嬉しいです**

### 悪い点
- そのクラスを継承した際に、派生クラスから`super.XXX`でアクセスすることができません
- そのメソッドは事前にバインドされ、型安全ではないコントラクトがクラスとコンシューマの間で追加されることはありません
    - 原文: The exact semantics of which methods are "pre-bound" and which aren't create an additional non-typesafe contract between the class and its consumers

正直２つ目はよく意味がわかりませんでした…(ダメダメだ
**どなたか分かる方コメントなどでおしえていただけると嬉しいです**(２度目)

### いい点 かつ 悪い点
この方法だと、クラスインスタンスを作るたびに、クロージャが作成されてしまいます。
もし普通のインスタンスメソッドとしてしか実行しなのであれば、この実装方法は過剰すぎます。
ただし、このメソッドをコールバック関数としてよく使うのであれば、
その都度クロージャを作るよりもこのほうが良いでしょう

## Local Fat Arrow
その都度クロージャを作ってあげるパターンです。

```ts
var x = new SomeClass();
someCallback((n, m) => x.doSomething(n, m));
```

### いい点
- これは100%型安全です！
- ECMAScript3でも動きます
- インスタンス名の記述が１度いいです

### 悪い点
- パラメータを２度記述しないといけません
- 可変長引数可変長引数を利用する場合動作しません

### いい点 かつ 悪い点
パフォーマンス/メモリついてはインスタンス関数と比較すると正反対です
(こちらの方がメモリは使わないが、少しパフォーマンスが悪い)

# まとめ
一応元記事には`Function.bind`についての記載もあったのですが、
現時点で型安全ではないので、採用はないかなと思います。
GOOGLE CLOUD CERTIFIED Professional Cloud Architectへの道 ～その２．トレーニングコースを受ける～

#前回の模擬試験
GCPサービスを知らない状態で模擬試験を受け、惨敗（当たり前）
Google Cloud Platformとして用意しているPCA取得ステップに従って、学習を進めることを決意。

#トレーニングコースの受講

トレーニングコースを受講してみる。下記サイトにアクセス。
[トレーニングプログラム(インフラ）](https://cloud.google.com/training/cloud-infrastructure?hl=ja)

アーキテクトトラックとしてステップが3つほど。
　ステップ1． Google Cloud Platform Fundamentals: Core Infrastructure
　ステップ2． Architecting with Google Cloud Platform: Infrastructure
　ステップ2a．Introduction to Cloud Identity
　ステップ3． Architecting with Google Cloud Platform: Design and Process

　※受講目安の期間も記載されていました。ステップ2aが1週間。。

実際に受講しようとすると、、
![GCP3.png](https://qiita-image-store.s3.amazonaws.com/0/297179/79a2c137-33f2-4416-10e8-45a2e02a76fa.png)

無料でお試し可能だけど、フルアクセス期間が7日間限定。
集中して勉強できる時間を作らないと、ボリュームがハマらなそう。。

![GCP4.png](https://qiita-image-store.s3.amazonaws.com/0/297179/4a715934-7103-f50c-5550-98abc8ceb1c1.png)


トレーニング受講はシラバス形式になっていた。
あと、トレーニングは全編英語。。。字幕も英語。。。
（英語に対して不安視しているけれど、学習を継続してみて結果を載せてみようっと）
JavaScriptの日付処理でLuxonを使う

今までは [Moment.js](https://momentjs.com/) 使ってたけどモダンに再設計された [Luxon](https://moment.github.io/luxon/) を使うことにした。

## 🤔 なぜ Luxon がつくられたか

[Why does Luxon exist?](https://moment.github.io/luxon/docs/manual/why.html) に書いてある。

* 作者は Moment.js のメンテナー
* Moment.js を改善するアイデアを持っていたが良いコードベースではなかった
* より明示的な API にしたかった
  * `moment(Number)` -> `DateTime.fromMillis(Number)`
  * `moment(Date)` -> `DateTime.fromJSDate(Date)`
* 追加のデータファイルなしでタイムゾーンを扱いたかった
* [Intl API](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl) を使って国際化の仕組みを再考したかった

## ⏰ Moment.js に劣っていること

* 最新ブラウザの機能を使うと古いブラウザのための互換性対応をしなければならずコードが煩雑になる
* 国際化された文字列をコードベースに保持してない故にブラウザが対応するまでその機能を待たなければいけない可能性
* Intl API のいくつかはブラウザ依存のため Luxon の動作もそれに依存する

特に Intl API は古いブラウザでは動作しないので、そこに対応する必要性の有無が Moment.js を使うか Luxon を使うか否かの分岐点。  
Node.js で使うなら問題にならなそうだ。

## 🛠 インストール

```bash

$ yarn add luxon @types/luxon
```

## 🗞 TypeScript サンプルコード

```typescript

import {DateTime} from 'luxon';

// now (string)
DateTime.local().toString();  // => 2018-09-20T14:13:12.954+09:00
DateTime.utc().toString();    // => 2018-09-20T05:13:12.961Z

// now (unixtime)
DateTime.local().toMillis();  // => 1537420392961
Date.now();                   // => 1537420392961

// format
const dt = DateTime.fromISO('2020-07-24T20:00:00');
dt.toUTC().toString();                 // => 2020-07-24T11:00:00.000Z
dt.toString();                         // => 2020-07-24T20:00:00.000+09:00
dt.toISO();                            // => 2020-07-24T20:00:00.000+09:00
dt.toHTTP();                           // => Fri, 24 Jul 2020 11:00:00 GMT
dt.toFormat('yyyy-MM-dd HH:mm:ss z');  // => 2020-07-24 20:00:00 Asia/Tokyo
dt.toSQL();                            // => 2020-07-24 20:00:00.000 +09:00
dt.toSQLDate();                        // => 2020-07-24
dt.toSQLTime();                        // => 20:00:00.000 +09:00
```
awslogsはpython2系依存なのでgolang実装のcwをつかう

AWS の Lambda や ECS の需要が増えたことにより、CloudWatch Logs の需要も増えてると思う。  
でも AWS コンソールから CloudWatch Logs はとても見にくい。そこで [awslogs](https://github.com/jorgebastida/awslogs) を使ってる人が多いと思う。


## 🌋 awslogs の問題点

Python2系への依存、これが非常にだるい。自分の場合 Python は [pyenv](https://github.com/pyenv/pyenv) 経由で 3 系をデフォルトで使ってるし。

```
$ brew info awslogs
awslogs: stable 0.10 (bottled), HEAD
Simple command-line tool to read AWS CloudWatch logs

==> Dependencies
Required: python@2 ✔
```


## 🐾 Golang 実装の  [cw](https://github.com/lucagrulla/cw)

```
$ brew info cw
lucagrulla/cw/cw: stable 1.7.2
The best way to tail AWS Cloudwatch Logs from your terminal
```

* [lucagrulla/cw](https://www.lucagrulla.com/cw/)

バイナリ配布が得意な Golang 実装なので依存関係なし。最近（2018年10月下旬）は Windows 対応までしてくれた。


## 📝 使い方

Mac の場合、Homebrew からインストールできる。

```
$ brew tap lucagrulla/cw
$ brew install cw
```

`-p` で `~/.aws/credentials` のプロファイルを指定可能。`tail -f` でリアルタイム監視できる。その後ろの第1引数で `ロググループ名`、第2引数で `ログストリーム名` を指定。第3引数で日時指定を UTC で指定できる。

```
$ cw -p <my_aws_profile> tail -f <my-log-group> <my-log-stream-prefix> <start-time>
```

```
$ cw -p jnst tail -f /ecs/my-server ecs/my-server/**** 2018-10-01T08:10:10 
```

一番シンプルな使い方はデフォルトのプロファイルを使い、ロググループ名だけを指定するやり方。

```
$ cw tail -f /ecs/my-server
```
Mac のローカルの git ブランチを master 以外消去するコマンド

こんにちはみなさん

リリース前の追い込み時にバグ修正などの細かいブランチが大量にできることがあり、鬱陶しいのでとっとと消したくなることがあります。
私の開発では、基本的に master からブランチをきり、PRやMRで master にマージすると言う方法を取るので、master にマージし終わったブランチは基本不要です。

そんなわけで、やたらと増えてしまった git ブランチを master 以外バッサリ削除するために、たまに投げるコマンドを備忘録代わりに書いておきます
Macでのみ使ってますがLinuxでも使えると思います。
windowsでは使ってません。

```
git branch | grep -v master | xargs git branch -d
```

今回はこんなところです。

いや、短い記事を書いてみたくなったんですよ。
rakeについて

記事を移転させました。
→　[【投稿】rakeについて](https://pick-up-tech.com/blog/rails%E3%81%A7%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8Brake%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
ScanSnap IX500 で指定した保存先にファイルが保存できない（OneDrive\ScanSnap下に保存されてしまう）

ScanSnap IX500で指定した保存先にファイルが保存できない事象がありました。
メーカーのQ&Aサイトには同様の事象は存在せず、サポートに問い合わせて解決しました。
デフォルトの設定だと同じ事象が発生するので、同じく困っている人の参考になれば。。

# 事象

指定した保存先にファイルが保存できない。
C:\Users\＜ユーザ＞\OneDrive\ScanSnap下に保存されてしまう。

# 原因

「クイックメニューを使用する」にチェックが入っているとこのような動作になるそうです。

![](https://i.gyazo.com/bc051377ef915cececf47387aef2303f.png)

# 対処

以下の手順で解決します。

- タスクトレイ内のScanSnap ManagerのSアイコンを右クリックして設定画面を表示
- 「クイックメニューを使用する」のチェックを外す(*1)
- 「アプリ選択タブ」を選択
- 「アプリケーションの設定」で、「起動しません」とか「Acrobat」とかを指定

(*1)「クイックメニューを使用する」のチェックを外すとそれまでの設定がクリアされるので全タブの設定をやり直す必要があります。

![](https://i.gyazo.com/3dbc72dc46b4d0199ac190d04211bd15.png)

![](https://i.gyazo.com/36be3c2b17ca3994b5e7ca3c14bb4285.png)
Fargateの「コマンドの上書き」でのオプションの設定方法

AWSのコンソール画面でFargateのタスクを実行する際に
「コマンドの上書き」でオプションを付与したかったが、少しハマったのでメモ。

# やりたいこと

下記は実行したいコンテナのDockerfileの一部

```dockerfile

ENTRYPOINT ["python", "index.py"]
CMD ["--date", ""]
```

Fargateでのタスク実行時に

```

--date 20181002
```

という感じのオプションを付与したい。

# 「コマンドの上書き」の記載方法
結論から言うと
タスク実行の設定画面の「コマンドの上書き」欄に

```
--date,20181002
```
と記載するだけであった。

<img width="708" alt="スクリーンショット 2018-10-02 14.11.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/210767/ace01565-5eaa-2a99-4dde-be5db248abb9.png">


カンマの後ろに余計な空白があるとその空白もオプションの一部として認識されてしまったので注意。
macosを再インストール時「復旧サーバに接続できませんでした」問題の解決方法

#復旧サーバに接続できませんでした問題とは
macosを再インストールするときに出る場合がある

##原因１　wifi等のネットワークに接続していない
これは、wifi等のネットワーク環境に接続すればよい

##原因２　localの時刻のずれによるもの
mac本体の時刻と、復旧サーバの時刻のずれが大きいとおきてしまう問題

###解決方法
terminalを起動してdateコマンドを実行する

date 月日時分西暦の順番で入力

入力例
2018年1月2日3時4分の場合

```bash
date 010203042018
```
上記を入力したあとにmacOS再インストールを実行するとうまくはずです
firebase functionsをwebpackでビルドデプロイする

何も考えずにwebpackでビルドしてそのままfirebase functionsにデプロイしようとしたらエラーになったのでメモ

## 問題
firebase functionsにデプロイする際はモジュールをnodeランタイムとしてビルドする必要がある
webpackで何も指定せずにビルドするとブラウザ用にビルドされる
今回自分が作ったモジュールにはPhaserが入っていたのでデプロイ時にエラーった


```error
Module not found: Error: Can't resolve 'fs' in
```

## よくない対応
以下のようにwebpackに追記するとエラー回避はでき、ブラウザ向けビルドは完了するが
モジュールが正常に動くかは保障できない

```webpack.conf.js
node: {
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty',
  },
```

## よい対応
nodeランタイム用にinstall

```
npm install --save-dev webpack-node-externals
```

```webpack.conf.js
// 追記
var nodeExternals = require('webpack-node-externals');

module.exports = {
    entry: './src/index.ts',
    output: {
        filename: 'index.js', 
        libraryTarget: 'this' // 追記
    },
    target: 'node', // 追記
    module: {
        // 割愛
    },
    resolve: {
        extensions: [ '.tsx', '.js' ]
    },
    externals: [nodeExternals()] // 追記
};
```
GOOGLE CLOUD CERTIFIED Professional Cloud Architectへの道 ～その１.5．今の実力を知る～

#認定試験ガイドは読んだ

なるほど。ガイドだけではよく分からない。
Google Cloud Platformのサービスも理解していないし。。。

**たらればのお話し**
Google Cloud Platformはまだ触ったことがないけれど、AWSは業務で触ったことがあるから、
ひょっとしたら今の段階でもそこそこ点数が取れるんじゃないか？

ということで、現状を知ろうと思う。

#GCPの知識レスで模擬試験を受けてみる

模擬試験の受け方は[こちら](https://qiita.com/sakuraya27/items/8b3b1da19db6b66a9d96#google-cloud-architect-%E6%A8%A1%E6%93%AC%E8%A9%A6%E9%A8%93%E3%81%AE%E5%8F%97%E3%81%91%E6%96%B9)

![GCP01.png](https://qiita-image-store.s3.amazonaws.com/0/297179/e21c94a4-fdd7-80ef-f705-c6faf9f200b1.png)

結果：20問中7問正解。（うち3問は勘のため、実質4問正解）

そりゃそうだ。
VPCとかIAMなど、AWSと似ている用語が出てくる設問や、ロードバランサ―の知識を問う問題だけ正解。あとは全滅。

#結論
GCPのサービスを一通り学習してから、また模擬試験を受けてみよう。
Grafana で Stackdriver のグラフを表示する

## 概要

5.3.0-beta2 で Stackdriver データソースがサポートされたので試してみる。

- Stackdriver: Support for Google Stackdriver Datasource [#13289](https://github.com/grafana/grafana/pull/13289)


## Grafana インストール

grafana 5.3.0-beta2 インストール

```
$ sudo yum install https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-5.3.0-beta2.x86_64.rpm
```

## GCP Service Account 作成

1. GCP Project の [認証情報](https://console.cloud.google.com/apis/credentials) に移動

2. `認証情報を作成` から `サービスアカウントキー` を選択
![01.png](https://qiita-image-store.s3.amazonaws.com/0/105824/46b5befe-c08e-ceac-737d-ffbbbe81cb0e.png)

3. `サービスアカウント` から `新しいサービスアカウント` を選択
![02.png](https://qiita-image-store.s3.amazonaws.com/0/105824/cd30df70-00b4-3153-6838-a3cad878c1b2.png)

4. `サービスアカウント名` を入力して、`役割` は `モニタリング閲覧者` を選択して `作成` をクリック
![03.png](https://qiita-image-store.s3.amazonaws.com/0/105824/ce9e16aa-4d46-3365-90e3-87e7592c1a10.png)

5. サービスアカウントキーがダウンロードされるので保管しておく

## Grafana の設定

1. DataSource 追加画面から Stackdriver 選択

2. 名前を入力して、ダウンロードしたサービスアカウントキーをアップロード
![04.png](https://qiita-image-store.s3.amazonaws.com/0/105824/71ae3b21-8d51-06ad-c171-d315828a586c.png)

## ダッシュボード作成

追加した DataSource を選択して Metric を選択
![05.png](https://qiita-image-store.s3.amazonaws.com/0/105824/4eff9c8f-aa53-a000-1b32-8785940ff08b.png)

※Alerting も対応
![06.png](https://qiita-image-store.s3.amazonaws.com/0/105824/bb27d8c4-9fd8-9298-aa21-f7a736de42dd.png)
既存の PDF ファイルに加筆する (python3)

```py:pdf_overwrite.py
#! /usr/bin/python
#
#	pdf_overwrite.py
#
#						Oct/02/2018
#
# ------------------------------------------------------------------
import sys
from pdfrw import PdfReader
from pdfrw.buildxobj import pagexobj
from pdfrw.toreportlab import makerl
from reportlab.pdfgen import canvas
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.pdfbase import pdfmetrics

# ------------------------------------------------------------------
sys.stderr.write ("*** 開始 ***\n")
file_in = sys.argv[1]
file_out = sys.argv[2]
sys.stderr.write(file_in + "\n")
sys.stderr.write(file_out + "\n")
#

cc = canvas.Canvas(file_out)
fontname_g = "HeiseiKakuGo-W5"
pdfmetrics.registerFont (UnicodeCIDFont (fontname_g))
cc.setFont(fontname_g,16)

page = PdfReader(file_in,decompress=False).pages
pp = pagexobj(page[0])
cc.doForm(makerl(cc, pp))

cc.drawString(100,600,"こんにちは")
cc.drawString(150,500,"本日は晴天なり。")
cc.drawString(100,400,"Hello World")
cc.showPage()
cc.save()
#
sys.stderr.write ("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行方法

```bash
./pdf_overwrite.py template.pdf out01.pdf
```

参考ページ
[既存の複数ページの PDF ファイルに加筆する (python3)](https://qiita.com/ekzemplaro/items/0d2536f2cbf11f186bd9)
Paypal決済ページのエラー

以下のページの解説が正解でした。htmlを弄ってパラメタを足したりしている例もありましたが、それらでは解決しないように見えます。

[PayPal決済ページのエラー：データが入力文字セットまたはデフォルトのエンコーディングに一致しません。](https://ja.stackoverflow.com/questions/25023/paypal%E6%B1%BA%E6%B8%88%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC-%E3%83%87%E3%83%BC%E3%82%BF%E3%81%8C%E5%85%A5%E5%8A%9B%E6%96%87%E5%AD%97%E3%82%BB%E3%83%83%E3%83%88%E3%81%BE%E3%81%9F%E3%81%AF%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AB%E4%B8%80%E8%87%B4%E3%81%97%E3%81%BE%E3%81%9B%E3%82%93)

一応、こちらでも解説。Paypalの「購入」ボタンを導入して貼り付け、実際にクリックすると以下のようなエラーが出てしまう場合の対処法です。

```
Invalid Regular period. You must specify valid values for the A3, P3 and T3 parameters for a subscription.
```

ログイン後、「アカウント->個人設定->販売ツール」と遷移し、「PayPalボタンの言語コード化」というリンクをクリックします。以下のような設定画面が表示されますので、エンコード方式を、ボタンを設置したサイトと合わせます。今回、デフォルトがShift_JISとなっていたので、UTF-8に変更しています。

![Screen Shot 2018-09-30 at 23.38.08.png](https://qiita-image-store.s3.amazonaws.com/0/50780/e796fdfe-a3e4-f180-f430-6534de27354e.png)
iOS 12 のショートカットを使って Google フォームを日付を入力した状態で Chrome で開く

# この記事は？

iOS 12 で [ショートカット](https://itunes.apple.com/jp/app/workflow/id915249334?mt=8) というアプリが登場しました (デフォルトではインストールされていないので App Store からインストールする必要があります) 。

これを使い、[Google フォーム](https://www.google.com/intl/ja_jp/forms/about/) の日付欄にデフォルトで現在日付が入力された状態でフォームのページを開く方法を紹介しています。

# 困ったこと

僕は Google フォームでお小遣い帳を作り、日々の収支を管理しています。

フォームの中には日付欄があります。Mac の Chrome で日付を入力する場合、カレンダー型の日付コントロールが開き、日付を簡単に入力することができます。

![ss01.png](https://qiita-image-store.s3.amazonaws.com/0/6697/ad2d2f03-0bc1-971e-230e-be28e5d68c88.png)

しかし、iPhone の Chrome で日付を入力する場合は日付コントロールは開きません。手で打つしかないです :sob:

![ss02.png](https://qiita-image-store.s3.amazonaws.com/0/6697/a4b0df89-06b0-40c0-3c7e-ca618712cabe.png)

せめて日付欄に現在日時が入力された状態でフォームを開くことができれば便利なのですが…。

# 任意の日付が入力された状態でフォームを開く方法

Google フォームの URL に特定のクエリパラメータを追加すると、特定の入力欄を値を入力した状態で開けることが分かりました。

日付を入力された状態にするには、まず対応する `input[type=hidden]` 要素の name 属性を調べておきます。

![スクリーンショット 2018-10-02 11.50.57.png](https://qiita-image-store.s3.amazonaws.com/0/6697/e06e1ee9-7f01-3d9f-b5bf-fb3fac15ffd0.png)

この場合 `entry.1944875312_year`, `entry.1944875312_month`, `entry.1944875312_day` ですので、例えば

`?entry.1944875312_year=2018&entry.1944875312_month=10&entry.1944875312_day=02` 

というクエリパラメータを Google フォームの URL に追加すれば、日付欄に `2018/10/02` が入力された状態で開けます。

# iOS 12 のショートカットでクエリパラメータを生成し、Chrome で開く

iOS 12 のショートカットを使えば、前述のクエリパラメータを作成した上で URL に追加し、さらに Chrome で開くところまでを自動化できます。なお、クエリパラメータには本日の日付を指定します。処理の流れを Ruby プログラムで表すと以下のような感じです。

```rb
list = Time.now.strftime('%Y/%m/%d %H:%M').split(%r{\s|/})[0..2]

year, month, day = list
url = 'Google フォームの URL'
id = 1944875312 # input[type=hidden] 要素の name 属性に含まれる整数値

# これを Chrome で開く。
"#{url}?entry.#{id}_year=#{year}&entry.#{id}_month=#{month}&entry.#{id}_day=#{day}"
```

これをショートカットで実装したのが以下です。

![ss03.png](https://qiita-image-store.s3.amazonaws.com/0/6697/cccadad0-dff2-b599-e8eb-5815d86bf102.png)

このショートカットを実行することで、本日の日付が入力された状態でフォームを開くことができました :tada:

![ss04.png](https://qiita-image-store.s3.amazonaws.com/0/6697/5669c122-ee46-a3ae-edeb-32c5d6e63299.png)

# 感想

iOS 12 のショートカットですが、ちょっととっつきづらさはあるもののパーツを組み合わせてプログラムを完成させていくのは工作みたいで面白かったです。おかげで変数やリストの使い方も分かったので、今後もショートカットを積極的に活用していきたいです :muscle:
ローカルPCからFirestoreのデータにアクセスする

Python用Googleクライアントライブラリーを使ってFirestoreのデータへアクセスする。
そのためにはサービスアカウントを作成して鍵（jsonファイル）を準備する必要がある。


### GCPのコンソールからサービスアカウントを作成する方法

* GCPコンソール->IAMと管理->サービスアカウントで作成する
* 鍵（jsonファイル）が作成されるのでローカルPCへダウンロードする
* pipコマンドでライブラリをインストールする

```shell
$ pip install google-cloud-firestore
```

実際に取得してみる

```python
from google.cloud import firestore
# 上で作成したjsonファイルを読み込ませる
client = firestore.Client.from_service_account_json('/key.json')
# 「/A/docid」のドキュメントを受信する
client.collection('A').document('docid').get().to_dict()
> {u'foo': u'bar'} # 取得できた
```


### Firebaseのコンソールからサービスアカウントを作成する方法
GCPコンソールに行かなくてもFirebaseコンソールからサービスアカウントを作成できる。

* Firebaseコンソール->ギアアイコンをクリック->プロジェクトの設定->サービスアカウントへ移動
* Admin SDK 構成スニペットでpythonを選択して「新しい秘密鍵の生成」ボタンをクリック
* 鍵（jsonファイル）がPCへダウンロードされるのを確認する

このやり方だと
 　アカウント名：firebase-adminsdk
 　role: 編集者
でサービスアカウントが作成される。

* pipコマンドでライブラリをインストールする

```shell
$ pip install firebase-admin
```

実際に取得してみる

```python

import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

cred = credentials.Certificate('/key.json')
default_app = firebase_admin.initialize_app(cred)
db = firestore.client()
# 「/A/docid」のドキュメントを受信する
db.collection('A').document('docid').get().to_dict()
> {u'foo': u'bar'} # 取得できた
```
Ubuntu 18.04 LTSにインストールしたVSCodeで日本語が入力できない時にした事

僕は英語がわからないので**Ubuntu 18.04 LTS**に**VSCode**をインストールしたら、まずは表示設定を**日本語**に変更しないと使えないのですが、初回起動時に**「言語パック」のインストール**を案内されたので簡単にインストールすることができました。  

- **案内されない場合は下記の方法でインストールできます。**  

1. **VSCode**を起動し左側にある[Activity Bar]から[Extentions]アイコンをクリックするか、**[ctrl]+[shift]+[X]**を押して「EXTENTIONS:MARKETPLAYCE」を開きます。
2. 検索窓に**「japan」**と入力し、おそらく一番上にある**「Japanese Language Pack for VS Code」**をインストールして**VSCode**を再起動します。

VSCodeを**再起動**すると**表示言語が日本語**に変わってたのでこれで日本語化が完了したと思ってたら、もっと肝心なところが日本語に対応できてませんでした。

それは、**日本語入力ができない**という、僕にとっては致命的なことで**「あ」**と書きたくても**「a」**としかならず、**[半角/全角]**キーを押してもマウスで**入力モード**を切り替えても変わらないのに、他のアプリ(テキストエディタ等)では正常に切り替わる状態でした。

ここは無い知恵を絞って考えるより**google先生**に頼ったほうが早いだろうと、検索したらすぐに次の記事が見つかりました。
[UbuntuのVScode上にて日本語入力が出来ない](https://teratail.com/questions/121986)

結論は[Microsoft公式](https://code.visualstudio.com/download)から**deb**をダウンロードしてインストールし直すというもので、すぐに試したら見事に一発でなおりました。

ターミナルからaptコマンドでインストールしました。

```:Terminal
$ sudo apt install ./code_1.60.1-1631294805_amd64.deb
```
外部キー制約の指定コマンド

## 項目ごとに指定する方法
```sql
CREATE TABLE テーブル名 (
    列名 型 REFERENCES 参照元テーブル名 (参照先列名)
    :
)
```

## CREATE文の最後にまとめて定義する方法
```sql
CREATE TABLE テーブル名 (
    :
    FOREIGN KEY (参照元列名) REFERENCES 参照先テーブル名 (参照先列名)
)
```
Botoを使用してPythonからAWSを操作する（S3編）

#はじめに
BotoはPython用のAWSのSDKである。Botoを使用することで、Amazon S3やAmazon EC2をPythonから操作することができる。今回は、Botoを使用してAmazon S3を操作する際のTipsをまとめた。

#準備
以下の「準備」までしておく。
[Botoを使用してPythonからAWSを操作する（入門編）](https://qiita.com/oliverSI_/items/919acba8cf789b03ff70)

#Tips
###バケットの作成

```
import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('[バケット名]')
bucket.create()
```
バケット名がすでに存在している場合には、botocore.errorfactory.BucketAlreadyExistsエラーが返ってくる。

###バケットの削除
```
import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('[バケット名]')
bucket.delete()
```
バケット名が存在しない場合には、botocore.errorfactory.NoSuchBucketエラーが返ってくる。


###すべてのバケットを取得
```
import boto3

s3 = boto3.resource('s3')
for bucket in s3.buckets.all():
    print(bucket)
```
実行結果

```

s3.Bucket(name='[バケット名1]')
s3.Bucket(name='[バケット名2]')
...
```

###バケット内のすべてのオブジェクトを取得
```
import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('[バケット名]')
for object in bucket.objects.all():
    print(object)
```
実行結果

```
s3.ObjectSummary(bucket_name='[バケット名]', key=u'[ファイル名１]')
s3.ObjectSummary(bucket_name='[バケット名]', key=u'[フォルダ名1]/')
s3.ObjectSummary(bucket_name='[バケット名]', key=u'[フォルダ名1]/[ファイル名2]')
...
```
###バケットのサイズを取得する
```
s3 = boto3.resource('s3')
bucket = s3.Bucket('[バケット名]')
bucket_size = 0
for object in bucket.objects.all():
    bucket_size	+= object.size

print('Bucket Size: {} bytes'.format(bucket_size))
```
実行結果

```
Bucket Size: [サイズ] bytes
```
###ファイルをダウンロードする
```
import boto3

s3 = boto3.resource('s3')
s3.Object('[バケット名]', '[ファイル名(S3)]').download_file('[ファイル名（ローカル）]')
```

###ファイルをアップロードする
```
import boto3

s3 = boto3.resource('s3')
s3.Object('[バケット名]', '[ファイル名(S3)]').upload_file('[ファイル名（ローカル）]')
```

###署名付きURLを生成する
```
import boto3

s3 = boto3.client('s3')
presigned_url = s3.generate_presigned_url(
  ClientMethod = 'get_object',
  Params = {'Bucket' : '[バケット名]', 'Key' : '[ファイル名]'},
  ExpiresIn = [有効期間（秒）],
  HttpMethod = 'GET')
print(presigned_url)
```
得られたURLからファイルをダウンロードすることができる。
[iOS] メインWindowの上に新しくUIWindowを作成する方法

#Github
https://github.com/TakanobuSano/CreateNewUIWindow
![CreateNewUIWindow.gif](https://qiita-image-store.s3.amazonaws.com/0/82835/6106d53e-a982-631c-a269-86666ca65e10.gif)

#メインWindowを作成
```swift

        window = UIWindow(frame: UIScreen.main.bounds)
        if nil != window {
            let viewController = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MainID")
            window?.rootViewController = viewController
            window?.makeKeyAndVisible()
        }
```

#新しくUIWindowを作成
チュートリアルなどを作成する際に新しくUIWindowをオーバーレイさせて実装するときに利用します。

```swift

        newWindow = UIWindow(frame: UIScreen.main.bounds)
        if nil != newWindow {
            let viewController = UIStoryboard.init(name: "NewWindow", bundle: nil).instantiateViewController(withIdentifier: "NewWindowID")
            newWindow?.rootViewController = viewController
            newWindow?.makeKeyAndVisible()
        }

```

#新しく作成したUIWindowを削除
このとき、メインWindow側の「viewWillAppear」などはコールされませんので、
チュートリアルなどアプリの動作に影響せずに独立した形で動作するのに適しています。

```swift

self.view.window?.isHidden = true
```