OmniAICreator/Qiita-1.07M huggingface dataset:
[Dart] type 'List<dynamic>' is not a subtype of type 'List<xxxx>' in type cast の対処方法

jsonから読み込んだファイルを処理している時、次のようなエラーが出ることがあります。

```dart
final allSentences = widget.assets['sentences'];
final thisSentence =
        allSentences[widget.sentenceNo - 1] as Map<String, dynamic>;
// ↓ここでエラーが出る
final thisWordsNums = thisSentence['words'] as List<int>;
```

```
type 'List<dynamic>' is not a subtype of type 'List<int>' in type cast
```

こうしたときは、 `.cast<int>()`でint型へキャストすることで、エラーを回避できます。

```dart
final allSentences = widget.assets['sentences'];
final thisSentence =
        allSentences[widget.sentenceNo - 1] as Map<String, dynamic>;
// .cast<int>()を追加
final thisWordsNums = thisSentence['words'].cast<int>() as List<int>;
```

int型でなく次のような場合も同様に`.cast<Map<String, dynamic>>()`で対処できます。

```
type 'List<dynamic>' is not a subtype of type 'List<Map<String, dynamic>>' in type cast
```


## 参考
[cast method - List class - dart:core library - Dart API](https://api.dartlang.org/stable/2.7.0/dart-core/List/cast.html)
[dart - type ‘List<dynamic>’ is not a subtype of type ‘List<int>’ where - Stack Overflow](https://stackoverflow.com/questions/50245187/type-listdynamic-is-not-a-subtype-of-type-listint-where)
webpackerでmp3を使う場合 (audio_tag) Railsで音を鳴らす方法

# 実行環境
- macOS
- Ruby 2.6.5
- Rails 6.0.1
- ts 3.7.3
    - es2019

# 使う場合
- `app/assets/audios` にmp3ファイルを置く
- webpackerの設定ファイルを変更する

## サンプルコード
- `app/assets/audios/test.mp3` を配置

```config/webpacker.yml
  static_assets_extensions:
    # 以下の項目を追記する
    - .mp3
```
webpackerをdevelopment環境で使う場合に拡張子を追加しておく

```app/assets/config/manifest.js
//= link_tree ../audios
```
audiosファイルをmanifestにつなげる

```app/views/top/index.html.haml
= audio_tag('test.mp3', id: 'test-audio')
```

```app/javascript/packs/test.ts
const audio = document.getElementById('test-audio');
if (audio !== null) {
  (<HTMLMediaElement>audio).play().then(() => alert('音が鳴ったよ'));
}
```

## 気になったこと
以下のエラーが発生する時があるらしい

```.js
Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.
```
https://stackoverflow.com/questions/49930680/how-to-handle-uncaught-in-promise-domexception-play-failed-because-the-use
HTMLとCSS

HTMLとCSSについて学びました。

やっぱり
モノゴトの仕組みを知るのは面白い。
（反面、すぐ理解できないこともありました。。）

HTMLは本体で、CSSはそれを装飾するものらしいです。

日本文だと動詞がメインに使われるので動詞＝HTML、
それを装飾する副詞＝CSS、みたいなイメージでしょうか。

英文だと名詞＝HTML、
形容詞＝CSS、になりますね。

プログラミングにも色々な言語があるので、
共通する仕組みや個々の言語の仕組みを徐々に学んでいければより面白そうだなと思っている次第です。

実際のコードを模写してみた結果、CSSの方が長くなっていたのでそれに驚きました。

floatという単語が出てきて、
親要素、子要素が何ちゃら〜、
説明の動画内の概念図では断面の絵が出てきて、

ちょっと何言ってるかわからなかったです！！！

終わり。
走ってるpythonの特定のやつをまとめてkill

もっといい方法はあるはずなんだけど。

killしたいコマンドがこれ

```
$ ps aux
root     163622  0.0  0.3 229392 28852 ?        S     2019   0:00 /usr/bin/python3.5 imap.py
```

`pgrep -a` で process を引数付きで抽出できる

```
$ pgrep -a python3.5 
125033 /usr/bin/python3.5 var.py        <---- 関係ない python3.5 は除きたい
125034 /usr/bin/python3.5 imap.py
125035 /usr/bin/python3.5 foo.py
```


grepで引数にヒットするものだけにする

```
$ pgrep -a python3.5 | grep imap.py
125034 /usr/bin/python3.5 imap.py
```


それをpidだけにする

```
$ pgrep -a python3.5 | grep imap.py | awk '{print $1}'
125034
...
```


それをまとめてkill

```
kill $(pgrep -a python3.5 | grep imap.py | awk '{print $1}')
```

もっといい方法はあるはずなんだけど。
「config」のセットアップ&使い方(TypeScript)

## 「config」とは？

`NODE_ENV` の値によって設定を動的に切り替えるライブラリです。

## 用途

- 開発環境と本番環境で設定を変更したいとき

## 環境

- Node.js：v12.14.0
- npm：6.13.4
- config：0.0.36

## セットアップ

### configのインストール

npmからインストールします。

```shell-session
$ npm install @types/config config
```

TypeScriptの場合は `@types/config` もインストールします。
`@types/config` のみだと、 `cdk deploy` 時に `Cannot find module 'config'` エラーが発生しました。

## 使い方

### 設定ファイルの作成

設定ファイルを作成します。
`config` フォルダ内に `NODE_ENV` と同名で作成する必要があります。

```bash
# 「config」フォルダを作成する
$ mkdir config
$ cd config

# 「default.ts」を作成する
# 全環境に共通で読み込まれる設定ファイル
$ touch default.ts

# 「NODE_ENV」の値と同名のファイルを作成する
$ touch production.ts
$ touch development.ts
```

### 設定ファイルの編集

AWS CDKで設定ファイルを作成する例です。

全環境共通の設定として、リージョンとAWSアカウントを持たせています。

```ts:default.ts
export = {
  region: '{リージョン名}',
  account: '{AWSアカウント名}'
}
```

本番環境の設定です。
タイムアウトする秒数とメモリサイズを持たせています。

```ts:production.ts
export = {
  lambda: {
    {Lambda関数名}: {
      timeout: 30,
      memorySize: 256
    }
  }
}
```

開発環境の設定です。
本番環境よりスペックを落とし、コストを削減します。

```ts:development.ts
export = {
  lambda: {
    {Lambda関数名}: {
      timeout: 5,
      memorySize: 128
    }
  }
}
```

### 設定ファイルの読込

`config.get()` で設定ファイルから値を取得します。
`NODE_ENV` の値から自動で設定ファイルを選択して読み込みます。

```ts
import config = require('config')
import cdk = require('@aws-cdk/core')
import lambda = require('@aws-cdk/aws-lambda')

function createLambdaFn (scope: cdk.Construct): lambda.Function {
  return new lambda.Function(scope, '{Lambda関数名}', {
    runtime: lambda.Runtime.NODEJS_12_X,
    memorySize: config.get('lambda.{Lambda関数名}.memorySize'),
    timeout: cdk.Duration.seconds(config.get('lambda.{Lambda関数名}.timeout')),
  })
}
```

### プログラムの実行

`NODE_ENV` を設定し、プログラムを実行するのみです。

```shell-session
$ export NODE_ENV=development
$ cdk deploy
```

`NODE_ENV` は大文字小文字を区別するので気をつけてください。

```shell-session
$ export NODE_ENV=Development
$ cdk deploy
WARNING: NODE_ENV value of 'Development' did not match any deployment config file names.
WARNING: See https://github.com/lorenwest/node-config/wiki/Strict-Mode
…
```

## おわりに

簡単に実装することができました！
if文を使わずに、環境ごとに設定を切り替えられるので便利です。

## 参考リンク

- [lorenwest/node-config: Node.js Application Configuration](https://github.com/lorenwest/node-config)
pythonを使用したwebサイトの変化監視

あるサイトの変化を監視したいと思い作ってみました。現在は私の自己紹介文を監視していますがurlとclass_nameを変更すると他サイトでも使えます。
20秒毎にページデータを取得し、前回の取得時とデータが異なるかを表示しています。

```Python
import requests
import time

from bs4 import BeautifulSoup


url = "https://qiita.com/sssssssiiiiinnn"
class_name ='div.newUserPageProfile_info_body.newUserPageProfile_description'
file = "elems_text.txt"


def is_not_changed(old_elem, new_elem):
    return old_elem == new_elem


def set_old_elems():
    try:
        f = open(file)
        old_elems = f.read()
        print(f'{"old_elem":10} : {old_elems}')
    except:
        old_elems = ''
    return old_elems


def set_new_elems():
    response = requests.get(url)
    response.encoding = response.apparent_encoding
    bs = BeautifulSoup(response.text, 'html.parser')
    new_elems = str(bs.select(class_name))
    print(f'{"new_elem":10} : {new_elems}')
    return new_elems


def display_result(old_elem, new_elem):
    if not is_not_changed(old_elems, new_elems):
        f = open(file, 'w')
        f.writelines(new_elems)
        f.close()
        print("Change is detected!!")
    else:
        print("not changed...")


if __name__ == '__main__':
    try:
        while(1):
            print("="*100)
            new_elems = set_new_elems()
            old_elems = set_old_elems()
            display_result(old_elems, new_elems)
            time.sleep(20)
    except KeyboardInterrupt:
        print("Interrupted by Ctrl + C")
```
Spin CLIでGoogle認証する


gcloudコマンドでログイン

```
$ gcloud auth login
```

アクセストークンを表示

```
$ gcloud auth print-access-token
```

リフレッシュトークンを表示

```
$ gcloud auth print-refresh-token
```

`~/.spin/config`に以下を記入。なければ作成。

```~/.spin/config
gate:
  endpoint: http://spingate.xxxx #アクセスしたいspingateのエンドポイントを記入
auth:
  enabled: true
  oauth2:
    tokenUrl: https://www.googleapis.com/oauth2/v4/token
    authUrl: https://accounts.google.com/o/oauth2/v2/auth
    scopes:
    - email
    - profile
    cachedToken:
      accesstoken: #先程表示したアクセストークンを記入
      refreshtoken: #先程表示したリフレッシュトークンを記入
```

## 参考
[Install and Configure Spin CLI - Spinnaker](https://www.spinnaker.io/setup/spin/)
WordPress サイトを構築するときに確認したい項目

WordPress でサイトを運営する・している場合にセキュリティ観点として確認したい項目

# 最新バージョン
利用している WordPress の世代・バージョンを確認。
WordPress は、最新バージョンの利用を推奨しています。2020年1月8日現在の最新バージョンは、「5.3.2」となっています。

公式サイトから確認できますので把握しておきましょう
[リリース &#124; WordPress.org 日本語](https://ja.wordpress.org/download/releases/)

# 管理画面

### wp-admin へのアクセス制限
誰もが管理画面にアクセスできる状態になっていないかを確認。
4G回線から "サイトURL/wp-admin"　にアクセスください。
そのままログイン画面が表示される場合、アクセス制限がない可能性があります。

### admin アカウント
アカウントに "admin"や "administrator"がないかを確認。
乗っ取りのターゲットになり易いアカウントは、利用しないようにする。

### ログインURLの変更
デフォルトのログインページURLを変更し、ログインページへのアクセスを防ぐ


# 出力情報

### wordpress 情報
* wp_generator
    * 利用中のWordPress バージョンが <meta name=”generator”>に出力されます。
    * バージョン情報を出力しないようにします。
* rsd_link、xmlrpc、wlwmanifest
    * 外部ツールとの連携URLが出力されます。
    * 出力されないようにします。

# その他

### プラグインの脆弱性を確認
利用するプラグインに脆弱性が存在しないか「脆弱性対策情報データベース」で確認
[脆弱性対策情報データベース 検索キーワード「WordPress」](https://jvndb.jvn.jp/search/index.php?mode=_vulnerability_search_IA_VulnSearch&lang=ja&useSynonym=1&keyword=WordPress)
深刻度のレベルを合わせて確認ください。

### Rest Api を無効化
Rest Apiの利用が無い場合は、無効化しましょう
[【WordPress】特定のプラグインが動作するようにREST APIを無効化する方法](https://takayakondo.com/rest-api-invalid/)

# 参考

[WordPressのfunctions.phpにとりあえずコピペしておくべきコード](https://webty.jp/staffblog/uncategorized/post-1679/)
[WordPressのログインページURL変更は一番効果のあるセキュリティ対策のひとつ](http://tanweb.net/2019/01/12/25093/)
[WordPressのセキュリティ対策！自分でできる対策方法まとめ](https://cybersecurity-jp.com/security-measures/22048#WordPress19)
インタフェースとアブストラクト

インタフェース。。メインルーチンなど、呼び出し側のロジックを共通化しやすくするための仕組み。引数と返却値を定義して実現する。

アブストラクト。。呼び出される側の内部処理を共通化しやすくするための仕組み。処理を定義して実現する。

Qiitaをググれば記事はいくらでも出てくるんだけど、自分の頭を整理するために書いてみた。

たとえば、郵便局の荷物出荷アプリケーションを考えてみる。

荷物を出荷するには、出荷明細が必要だ。この作成処理は、荷物をどう送るかに関わらず共通の処理をしていそうだ。

荷物を数える、種類ごとに分類する、など。

ならば、アブストラクトで共通化しよう。

いっぽう、荷物の出荷方法はどうか？パック便、冷凍便、メール便、通常便など、送る方法は色々ある。

けれども、「宛名」「送り主」「出荷料金」など、荷物を送る側が用意する情報は一緒になりそうだ。

であれば、インタフェースで統一化しよう。

こんな感じで考えている。しかし、Javaをまともに使ったことがないので、実際のところ曖昧な理解のままだ。
FlutterのDEBUGバナーのようなバナーをお手軽に表示する

Flutterをdebugモードで起動すると出てくる右上のアレみたいなバナーを表示するコード。割と使えそうなので備忘録に残しておく。

### 見た目
![Simulator Screen Shot - iPhone 11 - 2020-01-08 at 16.06.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34515/55e2c645-f15d-fd06-a3ad-d099fe205a14.png)

###ソースコード

```dart

class WithButtonWidget extends StatelessWidget {
  const WithButtonWidget({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 56.0,
      decoration: BoxDecoration(
          color: Theme.of(context).primaryColor,
          borderRadius: BorderRadius.circular(8.0),
          boxShadow: [BoxShadow(color: Colors.grey[400], blurRadius: 3.0, spreadRadius: 0.0)]
      ),
      child: Row(
        children: <Widget>[
          Container(
            width: 70.0,
            height: 56.0,
            child: ClipRect(
              child: CustomPaint(
                painter: BannerPainter(
                  message: "with",
                  textDirection: Directionality.of(context),
                  layoutDirection: Directionality.of(context),
                  location: BannerLocation.topStart,
                  color: const Color(0xFF0099FF),
                ),
              ),
            ),
          ),
          Text("痴漢をさせない・見逃さない"),
        ],
      ),
    );
  }
}
```
CustomPaintのpainterにBannerPainterを使うとDEBUGバナーと同じ斜めのバナーを表示してくれる。そのままだと端っこがかっこ悪いので、ClipRectで囲って親のContainerに収まってくれるように調整する。
ヘッドレスCMSについて

##ヘッドレスCMSについて
- ビュー（表示する画面）がないCMS
- CMS外で自作する


## CMSのビュー（見た目）には以下の三種類がある
- サービス固有の画面(Qiita,Note,Mediumなど）
- テンプレートを選択できるもの(WoerPress,はてなブログなど）
- 自由に作成可能なもの(WordPress)


## ヘッドレスCMSのメリット
- コンテンツをWeb、iOSアプリ、Androidアプリなど複数のデバイスに表示できる



## CMSアーキテクチャの基本
- CMSのバックエンド・・・コンテンツが管理される方法
    - 製品の選択、配置、付随する看板等 
- CMSのフロントエンド・・・コンテンツが配信される方法
    -  物流、看板の作成、在庫の保管、店舗まわりでの製品の移動管理など

    - 以下のようなものが基本的なwebサイトのバックエンドに含まれる
    

        - コンテンツを作成するための簡単なインターフェース
        - デジタルアセットを格納するためのデータベース
        - デザインのフレームワークを作成・適用するためのアプリケーションレイヤー
【超初心者】JavaScript学習（めも）

#本日の学習
今日からスタート。
本により学習してます。わすれないようにメモ書きです。

###ダイアログボックス作る/prompt()メソッド
変数名=(window).prompt("ダイアログに出るメッセージ","デフォルト値");
※(window)は省略可能

###選択ダイアログ/confirm()メソッド
変数名=(window).confirm("表示するメッセージ");
(例)

```js
otoko=confirm("あなたは男ですか？");
if(otoko){
// 男の人の処理
}else{
// 女の人の処理
}
```

※(window)は省略可能

###文字列を数値にする/parseInt()関数
（例）seireki=parseInt(heisei)+1998;



###イベントハンドラをつかってみる

```html
<script>
window.onload=init;  // onloadイベントハンドラの実行
function init(){
document.form1.btn1.onClick=clickCheck;  // 関数呼び出し（イベントハンドラ設定)
}
var count=0;
function clickCheck(){
count++
}
</script>

<body>
 <form name="form1">
  <input name="btn1" type="button">
</body>
```
必ずwindowがロードされたら、クリックイベントができるようにする

###文字列から指定した位置の文字を操作　/chartAt()メソッド

引数は、文字の位置を指定

###ランダムな数を表示

```html

/1~10のランダム/
<script>
MAX=10;
var num;
for(i=0;i<MAX;i++){
 num=Math.floor(Math.random()*(Max+1));
 document.write(num,"<br>");
}
</script>

```
※0~9の場合は、
`num=Math.floor(Math.random()*Max);`
【Python】for文

#for文
for文は繰り返し処理を行いたいときに使う。
書き方等は後述するが、一つのfor文に対して一方向の繰り返し処理が行われる。
例えば、エクセルファイル等の行と列があるような場合で、
すべてのセルに対して処理を行いたい場合は
一方向の繰り返し処理では対応できない。
そのような場合は、for文中にもう一度for文を用いることで
二方向での繰り返し処理を行うことが出来る。

#記述方法
**for 繰り返し変数 in オブジェクトの集合:**
がfor文の記述方法である。

**オブジェクトの集合とは、リストのような一つの変数名で複数のデータが入ってる変数をいう。**
この複数のデータを一つづつ取り出して、そのデータに対してfor文内の処理が適用される。
for文中では取り出されたデータは**繰り返し変数**として扱われる。

```python:for.py
list=[1,2,3,4,5]
for element in list:
    print(element)
>>>1
>>>2
>>>3
>>>4
>>>5
```

#for文中のfor文
次にfor文中でfor文を記述することを考える。
今回はその例として九九を出力することを目指す。
以下が九九を出力するプログラムである。

```python:for.py
list1=[1,2,3,4,5,6,7,8,9]
list2=[1,2,3,4,5,6,7,8,9]
for m in list1:
    for n in list2:
        print("{0}×{1}={2}".format(m,n,m*n))
>>>"1×1=1"
>>>"1×2=2"
>>> ...
>>>"1×9=9"
>>>"2×1=2"
>>>...
```
外側のfor文では繰り返し変数がｍである。
内側のfor文では繰り返し変数がｎである。

まず最初に外側のfor文が実行され、ｍにlist1から一つ目の要素である１が格納される。
次に内側のfor文が実行され、ｎにlist2から一つ目の要素である１が格納される。
そして内側のfor文中の処理であるprint文が実行され、結果が出力される。

**内側のfor文中の処理が完了した後、内側のfor文の繰り返し処理が始まる。**
したがって、ｎにlist2から二つ目の要素である２が格納され、for文中の処理が行われることになる。

この操作が繰り返されるといずれ、
ｎにlsit2の最後の要素である９が格納されfor文中の処理が実行される。
この最後の要素でfor文中の処理を完了した時、内側のfor文は終了する。

内側のfor文の処理が終了後、次に外側のfor文の繰り返しが始まる。
要するにｍにlist1の二つ目の要素である２が格納され、
そしてもう一度内側のfor文が実行される。

#繰り返し回数（計算回数）
先にみたように、for文中にfor文を記述する(外側のfor文と内側のfor文が存在する)ことで、
繰り返し中の繰り返しを行うことが出来る。
外側のfor文の繰り返し回数がNであり、内側のfor文の繰り返し回数がnであると、
繰り返し回数はN×n回となる。

#よく使う繰り返し処理（指定回数繰り返し）
プログラムを組んでいくと、５回この処理を実行したい、１０回この処理を実行したいなど
特定の回数分繰り返し処理を行いたい場合がある。
この場合の一つの方法として、range関数を使う方法がある。

```python:for.py
for i in range(5):
    print(i)
>>>0
>>>1
>>>2
>>>3
>>>4
```
このrnage関数の代わりに、エクセルなどの最大行数をとってくる.max_row()メソッドなど指定することで全ての行に対する処理や、全ての列（.max_column()）に対する処理を行うことが出来る。
build.gradleの中身を学べた話

<h1>自分のスキルについて</h1>
学生。インターン中。
普段はWebアプリ開発でPHP(Laravel)とかJSとか触ってます。
あと研究用にPythonやってます。
Kotlinの実務経験は０。でもゆくゆくはAndroidエンジニアになりたかったり？
<h1>参考教材</h1>
https://codelabs.developers.google.com/codelabs/kotlin-android-training-images-compat/index.html?index=..%2F..android-kotlin-fundamentals#5

https://developer.android.com/studio/build/shrink-code?hl=ja

<h1>build.gradleで指定できること</h1>

モジュールレベルのbuild.gradle

```build.gradle

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.example.kotlinstudy"
        minSdkVersion 15
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

```
それぞれが示す意味を見ていく。

```
compileSdkVersion 29
```
自分が開発してるアプリが対応しうる最新のAndroidのバージョン。

```
minSdkVersion 15
```
自分が開発してるアプリが対応しうる最も古いのAndroidのバージョン。この数値を高くすると新しいバージョンにのみ対応したアプリができる。逆に低くすれば幅広いバージョンに対応できる。

```
targetSdkVersion 29
```
自分が最近ビルドした時に対応したAndroidのバージョン。

```
buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
　　　　　　　releaseCompile ''
    　　　　debugCompile ''
        }
    }
```

buildTypesでビルド時にどこにあるソースをビルドするか決めることができる。デフォルトでビルドされるのはsrc/mainのソースだが、buildTypeがreleaseならsrc/releaseのソースもビルドされる。また、`dependencies`ディレクティブにそれぞれの場合のコンパイルを指定することができる。
また、`minifyEnabled`はビルド時のコードの圧縮化を行うかどうかを指定できる。圧縮化のほかにも最適化、難読化、リソースの圧縮化の指定ができる。

<h1>最後に</h1>
Product Flavorに関してはまた今度話したいです
意識低いけどセパレートキーボードで肩こりを直したい

#肩が破滅

ぷろぐらま歴１５年、もはや肩が限界である　給料とマッサージ料金が釣り合ってしまう

マッサージで僧帽筋を押しながら「おかしいですねーここ骨ないんですけど」って言われる

もうむりだ、しぬしかない

#一縷の望み、セパレートキーボード

だがいちるののぞみ

「せぱれーときーぼーど」とかいうやつをつかうと肩こりがマシになるらしい、そして意識たかたかエンジニア界隈でとっても流行ってるらしい

#自作したくない

ちょっと調べてみると、基盤買ってきて自作するのが流行ってるらしい　さすがにそれはちょっとっていうか半田ごてとか中学以来２０年触ってないのでちょっと既製品がいいですね

あと、自作のやつとか、海外の意識高い系左右分割キーボード、配列が意識高すぎる、普通の配列がよい　あと価格も意識と比例して高すぎる、5万とか普通にする　1～2万くらいでなんとかしたい

いっしょうけんめいぐぐったところ、既製品だとMISTELとかいうメーカーのBAROCCOとかいうやつが比較的買える値段かつイケてるらしい、しかし人気で発売即完売、中古がちょろちょろ出回っているがどれもUS配列、JP配列が売りに出てるのを見かけることは皆無

Kinesis Freestyle2ってやつもあり、中古だとかなり安いんだけど、フットプリントがでかそうなんだわ　惜しい　試したくはある

#US配列は微妙

うーん、まあぶっちゃけUS配列でも全然使えるんだけど、キー1個たりない、半角アンスコどうすんねん問題っていまいちクールな解決方法がないよね

HHKとか使ってたので、US配列でも60%でも使おうと思えば使えるけど、やっぱり86サイズが使いやすい（自宅でも使ってるし、職場で与えられてるのもRealforce86）

#最終解決策

ということで、右手にRealforce86, 左手にBAROCCO 660L（そのときメルカリにこれしかなかった）を設置してみたところ、これがかなりイケてる

##良い点

・肩こりが軽減された（ゼロにはなっていないが、明らかに軽減した）
・自作とかしなくていい、メルカリでポチるだけ
・BAROCCO US配列であれば、常にメルカリに２，３の出品がある　相場も1万～1.5万くらいと、キーボードにこだわりたいプログラマであればポチれる範囲
・日本語配列で使える、左手はUS配列でもあんまり問題ない、なお、BAROCCOはキーアサインの変更が可能で、私が買った個体は左CAPS LOCKが全角／半角になっていたが、右手に設置したRealforce86の左端に全角/半角があるので問題ない

##微妙な点

・買える範囲とはいえ1.5万は高い、もっと安くほしい
・BAROCCOは右だけなら単体でも使えるんだけど左だけ単体では使えない、左を使うなら右もつないどかないといけない
・左CAPSによる全角/半角切替がなぜかintelliJで動かない時がある　これは謎

#結論

BAROCCOを買って、テンキーレス日本語キーボードと合わせて使おう

1.5万とポチる勇気だけで、高い意識も半田ごてスキルも組立時間もUS配列・60%キーボードに慣れる努力もせずに簡単にセパレートキーボードの恩恵を受けよう

そして肩こりを多少軽減させて明日もなんとか生き延びようぜ

#その後

結婚したら嫁が毎日マッサージしてくれるようになりました。
コードレビュー指針

# 概要
本ドキュメントでは、コードレビューをする上での指針を以下3点について述べる。

- コードレビューを行うタイミング
- コードレビューの観点
- レビューコメントをする上での注意点

また、本ドキュメントは以下の文献を参考にしている。
https://google.github.io/eng-practices/review/
https://google.github.io/eng-practices/review/reviewer/
https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c103.html
https://employment.en-japan.com/engineerhub/entry/2018/04/03/110000

## コードレビューを行うタイミング
原則コードレビューはモジュール1つの実装完了時、もしくはissue1項目対応完了時に行う。

## コードレビューの観点

### 設計
コードが適切な設計をなされているかどうかを議論する。具体例として、以下の項目を示す。

- モジュール分割が十分細かく行われていること
- ひとつの関数の行数が多過ぎないこと
- Assertが記述されていること:詳細は[こちら](https://qiita.com/katsuNakajima/items/5dd96e9e9dc7c1fcc13b)を参照のこと。
- ループが有限回数で停止すること
- 再起呼び出しが有限の深さで停止すること
- 外部から取り込むデータすべてに入力検査を施していること
- 並列プログラムである場合、競合状態やデッドロックにならないこと
- [DRY原則](https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3%82%A4/DRY%E5%8E%9F%E5%89%87/)を満たすこと
- [SOLID原則](https://postd.cc/solid-principles-every-developer-should-know/)を満たすこと
- その他ソフトウェア設計の原則に従っていること:[リーダブルコード](https://www.amazon.co.jp/dp/4873115655
)、[97のこと](https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/)を読むとよい。
- 複雑すぎず、別の開発者や未来の自分たちが簡単に理解し、使用、改修を行うことができること

### 機能性
書いたコードは開発者の意図通りに動作するか、ユーザーにとっての使い心地はどうかを議論する。
原則、レビュイーはコードレビューを依頼する前にテストと動作確認を済ませておく。
レビュー時に問題を発見した場合には、レビュアーはコードをレビュイーに差し戻す。

### テスト
レビューされるコードには、原則テストコードを合わせて記述し、テストが通ることを確認する。
テストコードに対しても、コードレビューとテストの妥当性検証を合わせて行う。レビュアーは考慮漏れやエッジケースを提案できると望ましい。
ソフトウェア開発におけるテストについては[こちら](https://t-wada.hatenablog.jp/entry/clean-code-that-works)を参考にするとよい。

### 命名
変数、関数などの各種アイテムが何であるか、何を行うかが明確にわかるような名前がつけられているかを議論する。
一般的な命名規則については、[リーダブルコード](https://www.amazon.co.jp/dp/4873115655)を参照するとよい。プログラミング言語またはプロジェクトで命名規則が明示されている場合にはそれに従う。

### コメント
適切なコメントが適切な箇所に加えられているかを議論する。
コードを読めば自明な処理についてはコメントを記載する必要はない。数学、通信などの専門技術を要する処理、複雑なアルゴリズム、正規表現などには適宜コメントを記載する。

### スタイル
プロジェクトでコーティング規約が定められている場合はそれに従う。そうでない場合はチームでコーティング規約を定めるか、プログラミング言語や開発環境で推奨されるコーティング規約に従う。例:[Googleのスタイルガイド](http://google.github.io/styleguide/)
コーティング規約に沿ったコードフォーマッタや静的解析ツールをチーム内で共有する。開発用のリポジトリにあげておくとよい。例:[editorconfig](https://editorconfig.org/)、[ClangFormat](https://clang.llvm.org/docs/ClangFormat.html)などの各種フォーマッタ、各種lint。

### ドキュメント
コードに合わせて、ドキュメントも更新しているかどうかを確認する。
開発環境、テスト、デプロイ、実行方法についてREADMEに記載する。
必要に応じて[Doxygen](http://www.doxygen.jp/)等のドキュメント出力ツールを用いる。

## レビューコメントをする上での注意点

- 意図がわからないコードについて質問する。
- 指摘箇所に対するコメントには指摘理由を明確かつ丁寧に述べる。
- 必要に応じてより良いコードを書くためのガイダンスやアドバイスを提示する。
- 良いところに関してもコメントするようにする。
[PlayCanvas]横へのリサイズ時に配置したモデルなどが隠れてしまう件について

PlayCanvasのコンテンツを作るときですが、画面サイズやアス比が固定されていれば…
と、常々考えてしまうことがあります。

例えば、PlayCanvasのロゴをドーンとでっかく見せるコンテンツ

![スクリーンショット 2020-01-08 14.55.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/d48eeae0-36e0-65e9-9509-d04aa33b7d0c.png)

縦へのリサイズはFill ModeをFill Windowにしているし、
![スクリーンショット 2020-01-08 14.58.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/f8ce78ef-a2a6-3969-5cca-d788bf9df49a.png)

縦へのリサイズ時はカメラがズームアウトしてくれるので
ちゃんとコンテンツが映りますね
![スクリーンショット 2020-01-08 14.55.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/2c393138-b7dc-d035-1d2f-274d7a960c39.png)


では横はどうだろうかと…

あれま
コンテンツが隠れてしまいました。
![スクリーンショット 2020-01-08 14.55.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/779dd9ce-fb47-5a5b-02a5-d8d970d34c0b.png)


意外とこの問題にぶつかる人は多い気がします。

これを解決するには以下のスクリプトをアクティブカメラに付与してあげます。

```js
let ResizeCameraFov = pc.createScript('resizeCameraFov');

ResizeCameraFov.prototype.initialize = function() {
    let self = this;
    let onWindowResize = function () {
        self._checkAspectRatio();
    };
    window.addEventListener('resize', onWindowResize, false);
    self._checkAspectRatio();
};

ResizeCameraFov.prototype._checkAspectRatio = function () {
    let height = this.app.graphicsDevice.height;
    let width = this.app.graphicsDevice.width;

    this.entity.camera.horizontalFov = height > width;
};
```

これで横にリサイズしてもコンテンツが表示されました。
![スクリーンショット 2020-01-08 15.05.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/1611b2a1-17a3-5645-9583-e96ca3cff24d.png)

---

実はこれ、
PlayCanvasの新規プロジェクト作成時のテンプレートにある「Model Viewer Starter Kit」にある
![スクリーンショット 2020-01-08 15.06.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/131de99f-7c95-82d2-5c44-4addd1bd3e6a.png)
`orbit-camera.js`で使われています。
![スクリーンショット 2020-01-08 15.06.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/3d6ad375-1cbe-8de8-f7c8-3c02ac714477.png)

このorbit-camera.jsをこのまま使うことがありますが、状況に応じて使わないこともありますからリサイズは気をつけたいですね。
NEM Catapultで使えるQRコードとニーモニックを生成する

NEM catapultで利用できるQRコードとニーモニックの作成方法です。

QRコードの出力には[symbol-qr-library](https://github.com/nemtech/symbol-qr-library)を、ニーモニックの出力には [symbol-hd-wallets](https://github.com/nemtech/symbol-hd-wallets)を利用します。
今回はブラウザ上で表示させるために、私が公開している[browserify版](https://github.com/xembook/symbol-sdk-browserify)を利用します。


##### ライブラリの定義と表示エリアの準備
```html
<script src="https://xembook.github.io/nem2-browserify/symbol-sdk-pack-1.0.0.js"></script>

<body>
<h3>QR Code</h3>
<div ><img id="item1"></div>
<h3>ニーモニック</h3>
<div id="item2"></div>
</body>

```
今回新たに、2021年3月段階で最新版の symbol-sdkを利用します。
QRコードをitem1 に 日本語対応のニーモニックを item2に出力します。


##### jsスクリプト

```js
$(function() {

const hd = require("/node_modules/symbol-hd-wallets");
const qr = require("/node_modules/symbol-qr-library");
const nem = require("/node_modules/symbol-sdk");

const mnemonic = hd.MnemonicPassPhrase.createRandom('japanese');
const exportMnemonic = new qr.MnemonicQR(mnemonic, "password", nem.NetworkType.MIJIN_TEST, 'no-chain-id');

const base64 = exportMnemonic.toBase64()
.subscribe(x=>{
	$('#item1').attr('src',x);
	$('#item2').text(mnemonic.plain);
});

})

```

`MnemonicPassPhrase.createRandom`でニーモニックを作成します。引数に"japanese"を指定するとひらがなで作成されます。対応しているのは以下の言語

```
chinese_simplified
chinese_traditional
english
french
italian
japanese
korean
spanish
```


jpapaneseはUTF8-MACで出力されるのでWindowsのテキストエディタにコピーなどでの運用を検討されている方は文字化けにご注意ください（濁点が文字化けます）。ちなみにこのライブラリはbitcoinjsのbip39のワードリストを使用しているので、他のブロックチェーンでも同じ現象が発生しているはずです。

MnemonicQR で作成したニーモニックに対応するQRコードを生成します。その後 toBase64() をサブスクライブすると画像データが`data:image/png;base64` 形式で出力されるのでjQueryなどでそのままブラウザに表示させることができます。


# 実行結果

無事出力されました。少し大きいQRコードですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29187/d904efb0-c9a3-11c5-ab19-ed944c174ed3.png)

”ぜんら”とかあります。だれがリストしたんでしょうね。他にも調べてみると「でぬかえ」とか意味不明な語もあります。ここらは金田一先生など集めて早急に理想的なワードリストを作ってほしいものです。

他にもsymbol-qr-libraryでは、トランザクションのリクエストを要求するQRコードを作成することも可能です。
いろいろと試してみてください。
SourceTreeを用いたバージョン管理についてまとめてみた

## はじめに
チーム開発でバージョン管理に利用されているSourceTree。
今回はバージョン管理をする上で必要な基本的な知識やSourceTreeの使い方をまとめてみました。

## 対象読者
・GitやSourceTreeをこれから使おうとしている方

## SourceTreeとは
Atlassianが無料で提供しているGitを用いたバージョン管理ツールです。
SourceTreeで用いるBitBucketはGitHubと同じような機能を持っています。
コマンドでバージョン管理することもできますが、SourceTreeはGUIで表現されているため、視覚的にわかりやすい点が特徴です。

ここでアプリの使い方の前に、Gitについて簡単な説明をします。
## Gitとは
OSS（Open Source Software）の分散型バージョン管理システムの一つです。
バージョン管理とは、プロジェクトの中で更新されていく様々な成果物の変更の履歴を成果物そのものも含めて記録することです。

例えば一つのプロジェクトを複数人で扱っている場合、編集箇所を更新していく必要があります。
複数で同時に編集箇所を更新すると一方の編集箇所が保存できない可能性があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422993/81ee7d88-8608-78cc-d4df-5922b96ae43d.png)


バージョン管理を行えば、いつ、誰が、どの箇所を何のために変更したかのログを作成することができ、上記のようなトラブルを回避することができます。
また、ログを作成することで前回のバージョンを確認したり変更の差分を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422993/56feee4a-6b8b-1486-bff0-6ab7491e17ee.png)

Gitは分散型バージョン管理システムです。
複数のリポジトリを設けるので分散型と言います。
例えば開発者Aによる変更がある場合は以下の流れで変更をリモートリポジトリに反映します。
AさんはAさんのローカルリポジトリにCommit
⬇︎
リモートリポジトリにPush
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422993/c9452fa0-2318-ce1f-3520-b600616f8f43.png)


リポジトリとは
>英語で「貯蔵庫」「収納庫」の意味。
>アプリケーション開発の際に、システムを構成するデータやプログラムの情報が納められたデータベースのことを指す。>また、ソフトウェア開発および保守における各工程のさまざまな情報を一元管理する意味でも用いられる。
>引用元：https://www.otsuka-shokai.co.jp/words/repository.html


バージョン管理に関してさらに詳しく知りたい方は[こちら]((https://eng-entrance.com/git-vesion-control))を参考にしてください。

## ファイルコミットの流れ

基本的なファイルコミットの流れを見ていきましょう。

1.ステージング
まずはローカルブランチからリモートブランチへ変更箇所のあるファイルを加える必要があります。
変更のあるファイルは下図の箇所に表示されます。
コミットするファイルにチェックを入れるとステージングされコミットする準備ができます。
表示されていない場合は.gitignoreに記述されている可能性があります。
![スクリーンショット 2020-01-07 21.07.20 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422993/5bb7abe9-005a-9590-0f29-7f036e017c89.png)


チェックを入れると下図のようにステージング済みのファイルに追加されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422993/8cf4d41e-56e1-d140-fe7f-8e9dd40efb74.png)

SourceTreeのステージングはGitコマンドの```git add```と同じ役割です。

2.commit
上図の下部にあるコミットメッセージを入力しコミットボタンを押します。
コミットメッセージはプロジェクトにより書き方が統一されている場合があるので、書き方はそちらを遵守してください。

2.push
作業環境であるローカルリポジトリからリモートリポジトリへ変更を反映します。
![スクリーンショット 2020-01-07 21.07.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422993/e5122c5f-ee80-e641-5f31-54d88c6959b8.png)

いかがでしたか。
Gitにはさらに便利な機能があるので、それらに関する記事も作成していきたいと思います！
🍰【CakePHP2】配列で指定した値に対してINまたはNOT INの複数件アップデートを行う

## 環境
PHP 7.2.21
CakePHP 2.10.18
MySQL 5.7.27

## やりたいこと
CakePHP2のupdateAll()を用いると条件式や任意のSQLにてbulk updateができますが
配列になっている値をカラム指定してINやNOT INで指定してupdateを行う方法を試したい

## やったこと
updateAll()の第一引数は配列にて「'カラム名' => 値」のSET句を指定
INの第二引数は「'カラム名' => 更新対象」を指定する
NOT INの場合は'NOT' => の配列にして条件を一段ネスト

尚、modifiedは自動で更新されないのでこちらも必要に応じて第一引数に追加してやります

### 更新するテーブル(Hogehoge)

|id|content|del_flg|modified|
|:------:|:------:|:------:|:------:|
|1|'test'|0|'2020-01-08 10:00:00'|
|2|'neko'|0|'2020-01-08 11:00:00'|
|3|'hoge'|0|'2020-01-08 12:00:00'|
|4|'🐈🐈🐈'|0|'2020-01-08 13:00:00'|
|5|'くぃいた'|0|'2020-01-08 14:00:00'|

### IN

```HogeController.php
    // 対象のIDをINで更新するパターン
    private function updateByIdIN() {
        $updateIdArray = ['1', '2', '3'];

        $this->Hogehoge->updateAll(
            [
                'del_flg'  => 1,
                'modified' => 'NOW()',
            ],
            [
                'id' => $updateIdArray
            ]
        );
    }
```

### NOT IN

```HogeController.php
    // ↑とは逆に対象のIDのNOT INで更新するパターン
    private function updateByIdNOTIN() {
        $updateIdArray = ['1', '2', '3'];

        $this->Hogehoge->updateAll(
            [
                'del_flg'  => 1,
                'modified' => 'NOW()',
            ],
            [
                'NOT' => [
                    'id' => $updateIdArray
                ]
            ]
        );
    }
```

## 結果

それぞれ配列内のIDが対象に更新される

### IN

|id|content|del_flg|modified|
|:------:|:------:|:------:|:------:|
|1|'test'|1|'2020-01-08 17:00:00'|
|2|'neko'|1|'2020-01-08 17:00:00'|
|3|'hoge'|1|'2020-01-08 17:00:00'|
|4|'🐈🐈🐈'|0|'2020-01-08 13:00:00'|
|5|'くぃいた'|0|'2020-01-08 14:00:00'|

### NOT IN

|id|content|del_flg|modified|
|:------:|:------:|:------:|:------:|
|1|'test'|0|'2020-01-08 10:00:00'|
|2|'neko'|0|'2020-01-08 11:00:00'|
|3|'hoge'|0|'2020-01-08 12:00:00'|
|4|'🐈🐈🐈'|1|'2020-01-08 17:00:00'|
|5|'くぃいた'|1|'2020-01-08 17:00:00'|
URLで絞ってGoogle Analyticsを見る

例では、QiitaのGoogle Analyticsを使用しています。
注意としては、作成したビューは削除しても30日間保持されます。
そのためテストでやる場合は、変な名前をつけないように気をつけて下さい。

## ビューの作成

Google Analyticsの管理ボタンから、ビューの作成を押す。

![アナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/65771d1d-de96-6097-e998-cfcbb50a5356.png)

![アナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/49346d60-daa0-574e-4dc4-84ec381dcec9.png)

名前は、英語で絞りたかったので英語という名前にしました。

![アナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/61fd011f-3d48-0d6e-00a5-05efd5985d0a.png)

## フィルタでURLを絞る

英語のビューのフィルタを選択してフィルタの追加を押す。

![アナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/c6d206d2-5edd-17d9-bf93-7e9993faf5cb.png)

サブディレクトリのトラフィックを選択して、希望するURLでフィルタリングする。
除外などもできます。また、ドメインで絞ったりIPアドレスで制限したり出来ます。

![アナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/7e9fa943-efd9-52e1-9b41-629dedc48508.png)

## 確認する

ビューを選択して見てみると、作成したばかりだと0件になります。
ビューを作成してからのデータが蓄積されますので、計測前にビューを作成する必要があります。

![アナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/024d28bd-8fb9-e1bc-e8c0-ad9c6b6d4387.png)
IE互換表示の微妙さとXMLHttpRequestの罠

##やりたいこと
* HTTPヘッダをjsで取得したい

##前提
* IE11を使うが、互換表示を強制的にかけられるのでIE5相当のjsしか使えないハズ
* ならばXMLHttpRequestも無理か…と思ってたら微妙に使えた

##結論
* 互換表示でもXMLHttpRequestは叩ける。本来IE5にはないはずなんだが。
* String.trim()はIE5にはないって言ってくる。
* addEventListenerはIEにはないらしい。

この一貫性のなさ！！納得できねぇ～！

AddEventListenerのページに、IEでのイベントの拾い方書いといてもらえたらなぁ
https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/loadend_event

ここ見ないとわからんかった
https://www.javadrive.jp/ajax/http/index5.html

##実装例
```js:ActiveX版。本来これしか動いたらあかんと思うのだが
// ActiveX読み込み
var httpReq = new ActiveXObject('Msxml2.XMLHTTP.6.0');
httpReq.onreadystatechange = cons;
httpReq.open('get', location.href, true);
httpReq.send(null);

function cons(e){
    if((httpReq.readyState == 4) && (httpReq.status == 200)){
        console.log(httpReq.getAllResponseHeaders());
    }
}

```

```js:なおActiveXObjectのバージョンはどっちの指定でもいけた
ActiveXObject('Msxml2.XMLHTTP.6.0');
ActiveXObject('Microsoft.XMLHTTP');
```

```js:なんとXMLHttpRequestも叩ける
var httpReq = new XMLHttpRequest();

// でもaddEventListenerはない
httpReq.onreadystatechange = cons;
httpReq.open('get', location.href, true);
httpReq.send(null);

function cons(e){
    if((httpReq.readyState == 4) && (httpReq.status == 200)){
        console.log(httpReq.getAllResponseHeaders());
    }
}

```
Dataprocでmecabを利用できるようにする

# はじめに
Dataprocでmecabを利用する際のメモ
以下のいずれかの方法で実現

- mecabインストール済のカスタムイメージを作成し、クラスタ生成時にカスタムイメージを指定する
- 初期化アクションでmecabをインストールする

なお、カスタムイメージは60日で期限切れになっていまう。
（期限切れのカスタムイメージを使用するクラスタを作成する方法は存在する）

イメージを持っておきたいなどの理由がない限りは初期化アクションのほうが楽かもしれない。

## mecabインストール用のスクリプトを作成
いずれの方法でもインストール用のスクリプトを作成しておく必要がある。
ついでにTimeZoneをJSTにしておく。
コマンドは使用するOSに合わせて適宜変更する。

``` create_mecab_image.sh
#!/bin/sh
timedatectl set-timezone Asia/Tokyo

# prepare
echo "prepare start."
sudo apt-get update
sudo apt-get -y install aptitude
sudo aptitude -y install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file
echo "prepare end."

# git clone
echo "git clone start."
git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
echo "git clone end."

# install
echo "install mecab start."
cd mecab-ipadic-neologd
./bin/install-mecab-ipadic-neologd -n -y
echo `mecab-config --dicdir`"/mecab-ipadic-neologd"
echo "install mecab end."
```

## カスタムイメージの作成
カスタムイメージを作成する場合、以下を参考にして実行
初期化アクションでmecabインストールする場合、この手順は不要。
https://cloud.google.com/dataproc/docs/guides/dataproc-images?hl=ja

```
python generate_custom_image.py \
--image-name mecab-image \
--dataproc-version "1.3.45-ubuntu18" \
--customization-script "./create_default_image.sh" \
--zone asia-northeast1-c \
--gcs-bucket gs://dataproc/custom_image/mecab \
--no-smoke-test
```

bashのversion違いによりrun.sh実行時にエラーが出る場合がある。
https://github.com/GoogleCloudPlatform/dataproc-custom-images/issues/35

成功するとGCEのイメージに上で指定したイメージが作成されている。

また、`--no-smoke-test` は推奨されていないが、つけないとsmoketest時にエラーになってしまったためとりあえずつけている

## クラスタの作成
1. カスタムイメージを使用する場合
クラスタ作成時に上で作成したカスタムイメージを指定して作成

2. 初期化アクションでmecabをインストールする場合
`create_mecab_image.sh` をGCSにアップロードしておき、初期化アクションで指定して作成

## 確認
作成したクラスタのVMインスタンスから、マスターノードのサーバーにSSH接続
mecabがインストールされていること（とTimeZoneがJSTになっていること）が確認できる

```
user@cluster-m:~$ date
Wed Jan  8 14:19:45 JST 2020
user@cluster-m:~$ which mecab
/usr/bin/mecab
```
Mac版のSourcetreeのウィンドウをタブ表示にする方法

sourcetreeはMac版Windows版と両方対応しているので個人的に好きで使っていますが、
Mac版のSourcetreeはWindows版のようにタブ表示でなく、リポジトリ毎にアプリ毎のウィンドウが表示されます。
これをタブ表示にする設定です。

<img width="1272" alt="スクリーンショット 2020-01-08 14.11.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/97361e1e-dfa3-9734-d687-dc8e01104016.png">

このようにウィンドウが複数の状態から

<img width="330" alt="スクリーンショット 2020-01-08 14.14.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/2fd36e00-8f2e-9bce-f065-79a40f4758f1.png">

「メニュー」→「ウィンドウ」→「すべてのウィンドウを結合」

<img width="1394" alt="スクリーンショット 2020-01-08 14.15.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/98f7611a-b58f-54cb-88d3-0c57bd791ec1.png">

これで全てのウィンドウが結合されてWindowsのようにタブ表示されます。


ただし！

アプリ再起動にこの設定が解除されてまた複数ウィンドウ立ち上がります。
デフォルトの設定にできないものでしょうか…

現状ver3.2でも探してますが見つけられておりません。
どなたかご存知の方がいたら教えてください。
Stripeの請求書メールを日本語化する

システム上で Stripe を使っていますが、個別対応で請求書を発行するとき、メール内容をどこから日本語化するのか分かりづらく困ったので、同じような人がいれば役立つかもしれないのでメモしておきます。

以下の順で見ていくと、日本語化できました。

- 左メニューの設定をクリック

<img width="250" alt="スクリーンショット 2020-01-08 14.15.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558863/ec888fe0-5164-65ec-1170-a3acef1df7b8.png">

- 設定クリック後に表示されるメール領収書をクリック

<img width="1098" alt="スクリーンショット 2020-01-08 14.15.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558863/1eba019d-d836-7602-aa86-fb5060d6ba6a.png">

- デフォルトの言語を日本語に設定

<img width="1097" alt="スクリーンショット 2020-01-08 14.15.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558863/fd5e772e-5b37-a084-6344-1e068a2b19c6.png">

お役に立てば幸いです。
Adobe産物まとめていきます

#この記事は何？
AfterEffectsをいじってて、いつかどこかで何かに使えそうな物をアップしていく記事

#ファイル
###[AE]カラフルでスピード感があるやつ　
![colorful speed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178061/0223ad93-ff3c-3e44-45da-8f06fc03df9d.png)

####ファイルのダウンロード
http://www.timetoedit.net?download=685
【Windows10】VPNに接続できない or 接続試行中 【L2TP IPSec】

#はじめに
現場のPCで開発環境に接続できなくて困った話し。
手順書通りにVPNを設定したのに。。。

今回だけではなく、また起きそうな事象だった為、
備忘録に書きます。

##対象になる人
アダプターの設定が下記の人。
◾︎VPNの種類
  L2TP/IPSec

上記の種類で現場の環境に合わせて設定しても、
接続試行中のままだったりする人。

##対処法
※レジストリを弄るため、自己責任でお願いします！

Win + Rキーで「regedit」
管理者として、実行！

HKEY_LOCAL_MACHINE
 ∟SYSTEM
  ∟CurrentControlSet
   ∟Services
    ∟PolicyAgent

メニューの編集→新規→「DWORD(32ビット)値」
      

追加された「新しい値#1」を右クリック
→「名前の変更」
下記にする。
AssumeUDPEncapsulationContextOnSendRule

変更したそれをダブルクリックし、
値のデータを数値の「2」に変更する。
※カギカッコは、間違えても入力しないこと。

PCを再起動すると設定が有効になる。

##終わりに

自分は、現場で繋がらなくて焦りました。
下記のサイトのお陰でなんとかなりました。
自分の復習と備忘録を兼ねて今回、書きました。

以上です。


https://www.cup.com/staticip/manual/win10_l2tp.html
Centos7でswapファイルを作成する

#はじめに

AWS のCentOS7ではswap領域が確保されていないため、手動でswap領域を作成する

# swapファイルの作成

ddコマンドを使って100MBの空ファイルを作成する

```
# ionice -c3 dd if=/dev/zero of=/100MB.img bs=1M count=100 oflag=direct
```

100MBの空ファイルを使用してして、I/O負荷を少なく8GBのswapファイルを作成する

```
# for i in $(seq 1 82); do ionice -c3 cat /100MB.img >> /swapfile; sleep 5; done
```

実行属性を付加します。

```
# chmod 600 /swapfile
```

swap領域を作成します。

```
# mkswap /swapfile
```

swap領域を有効にします。

```
# swapon /swapfile
```

スワップ領域が有効であることを確認する。

```
# free -m
# swapon -s
```

# OS再起動時のswapファイルマウント設定
OS再起動時にスワップ領域が有効になるように、/etc/fstabに下記を追加します。

```
# for swap
/swapfile                                 swap                    swap    defaults        0 0
```

# OSがswapを極力使わない設定

/usr/lib/tuned/virtual-guest/tuned.confのvm.swappinessを1に変更する

```
#vm.swappiness = 30
vm.swappiness = 1
```

設定を反映させる

```
# systemctl restart tuned
```

設定を反映された事を確認する

```
# sysctl vm.swappiness
```

/etc/sysctl.confにvm.swappiness = 1を追記する

```
vm.swappiness = 1
```

設定反映

```
# sysctl -p
```

設定確認

```
# sysctl -a | grep swappiness
```
IntelliJでjavadocを自動生成するショートカット

# コマンド
メソッドのすぐ上で`/**`と打った後、Enterを押すとjavadocが生成される。

# 例

下記のメソッドがあったとする。

```java

    private Integer add(Integer first, Integer second){
        return first + second;
    }
```

`/**`と打ち

```java
    /**
    private Integer add(Integer first, Integer second){
        return first + second;
    }
```

エンターを押すと

```java
    /**
     * 
     * @param first
     * @param second
     * @return
     */
    private Integer add(Integer first, Integer second){
        return first + second;
    }
```

javadocが挿入される。
リンクのクリック範囲を広げたい #CSS

## やりたいこと
　スマホサイズでもクリックしやすいように、リンクのクリック範囲をもう少し広げたい。
　例えば下の例だと、そのまま記述した場合 **aタグ** の「詳細はこちら」の文字の範囲のみ、リンクに飛べるようになっている。これを、親要素である **divタグ** 全体までクリック範囲を広げ、 **h1タグ** や **imgタグ** でもリンクに飛べるようにしたい。

```HTML:sample.html
<div class="div">
  <img src="img.png">
  <h1>タイトル</h1>
  <a href="#">詳細はこちら</a> <!-- 普通はリンクに飛べるのはこの箇所だけ -->
</div>
```

## 解決方法
CSSの、positionプロパティで解決する。
[positionプロパティを忘れた時はこちら、をいつか追加します。きっと。](http://...)

#### 基本的な考え方
**aタグ** の範囲を、**divタグ** の左上を基準とし(①〜④)、そこから幅100%(⑤)、高さ100%(⑥)とすることで、 **divタグ** 全体までクリック範囲を広げる。

こうすることで、`aタグの範囲 = divタグの範囲`となる。
イメージとしては、**divタグ** の上に、 **aタグ** がぴったり重なっている感じ。 

```CSS:sample.css
.div {
  position: relative; /* ① */
}

.parent a{
  position: absolute; /* ② */
  top: 0; /* ③ */
  left: 0; /* ④ */
  width: 100%; /* ⑤ */
  height: 100%; /* ⑥ */
}
```
<br>
#### あれ、でも思うてたのとちょっと違う
　確かに **h1** タグや **img** タグもクリックできるようになってるけど、**aタグ** の「詳細はこちら」という文字が画像の上に表示されてる！なんで？？

> イメージとしては、**divタグ** の範囲の上に、 **aタグ** の範囲がぴったり重なっている感じ。 

　そう、「詳細はこちら」というテキストを”含む” **aタグ** が、**divタグ** の上に重なっているから。
　解決するには、まず「詳細はこちら」という文字列を削除しちゃう。そのあとで、aタグ**以外**のタグで文字列を書く。aタグっぽくしたいなら、CSSでcolorやtext-decolationなどのstyleを追加すると○。

```HTML:sample_2.html
<div class="div">
  <img src="img.png">
  <h1>タイトル</h1>
  <span>詳細はこちら</span> <!-- 適当なタグを追加する -->
  <a href="#"></a> <!-- この中の文字列を削除 -->
</div>
```


### 補足（見ても見なくてもどっちでもいいもの）
- 今回は親要素がdivタグだったが、ulやliなどでもできる！<br>ただしブロック要素。Float要素の場合は重なり順で注意が必要。
- 広げたリンク範囲の中にさらに**別のリンク**を追加したい場合も基本は一緒！<br>別のリンクに飛ぶaタグをクラス名をつけて追加し `<a href="#2" class="inline">`、そのpositionをrelativeにすればOK!　`.div a.inilnk{position:relative; z-index:3}`
Unreal Engine 4の長さの単位はcm

# 概要

物理演算を使ったシステムを作るためにライセンスの関係でUnreal Engine 4(UE4)を使うことになったんですが長さの単位に悩まされたのでその解説をします。
>企業の開発や研究等で似たようなことを検討している場合、メートル基準で設計されているUnityを使ったほうが平和だと思います。APIの分かりやすさやPhysX 4.1をサポートしている点から見てもUnityをおすすめします。

## UE4の長さの単位はcm

3DCGはただの3次元デカルト座標系の数学の世界なので`1`という長さに対して、これがm表記なのかcm表記なのかmm表記なのかそもそもmじゃなくてヤードポンド法なのか...といった明確な規定は一切存在しません。なので通常長さの`1`は1mmのことです!とソフトウェア毎に規定することでユーザーはそれに合わせて数値を入力や読み取りができます。また、物理演算を行うときに`1`という長さの単位が何を示しているかを把握しておかないと、概算に対して$10^2$~$10^6$倍くらいの数値差が出てきて首を傾げることになります(なりました)。

> かの有名なUnityは多分m基準で作られていて、今回触るUE4はcm基準、CADソフト等の機械工学の世界ではmmが基準が多いです。単位の間違いはいつでも起こりえます。

それで表題にもある通り、UE4で扱っている長さの単位(unreal unit: uu)は暗黙的に`cm`が基準になっているのですが、これが物理演算に関連するパラメータにどういう影響を与えるかを次に示します。

|単位名|SI単位|UE4での値|SI単位→uuの倍率|
|:---|:---|:---|:---|
|長さ|m|cm|$10^{2}$|
|面積|$\mathrm{m^2}$|$\mathrm{cm^2}$|$10^4$|
|体積|$\mathrm{m^3}$|$\mathrm{cm^3}$|$10^6$|
|速度|m/s|cm/s|$10^{2}$|
|加速度|$\mathrm{m/s^2}$|$\mathrm{cm/s^2}$|$10^{2}$|
|力|N($\mathrm{kg\cdot m/s^2)}$|$\mathrm{kg\cdot cm/s^2}$|$10^{2}$|
|トルク|$\mathrm{N\cdot m}\(\mathrm{kg\cdot m/s^2 \cdot m}\)$|$\mathrm{kg\cdot cm/s^2 \cdot cm}$|$10^4$|

ニュートン(N)やトルクといった普段mを使って表記しない組立単位に対して多大な影響を与えていることが分かると思います。私はこれを忘れていて引っかかりましたw

## 物理以外の影響

* CGモデルをメートル基準で作ると巨大になる。スケールを使った修正は大変な目に遭うのでやめたほうがいい(インポート設定でどうにかできるかは知らない)。
* 座標情報をUE4以外のシステムで使って計算したい場合メートル基準で作られていることが多いので、値の変換を前処理として入れる必要がある。逆もしかり
Slack API: channels/groups/im/mpim から conversations への移行

「[Slack API の最新情報をチェックしよう 📝](https://qiita.com/seratch/items/0e30fddd84e5779e9b9a)」でご紹介したように [Recent changes to the Slack platform](https://api.slack.com/changelog) の RSS フィードを購読されている方はすでにお気づきかもしれませんが、以下のアナウンスが出ております。

**Deprecating early methods in favor of the Conversations API（英語）**
https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api

`channels.*`, `groups.*`, `im.*`, `mpim.*` の Slack API が ~~2020 年 11 月 25 日をもって提供終了~~ **2021 年 2 月 24 日をもって提供終了** となります。これらの API で可能だった処理は [`conversations.*`](https://api.slack.com/docs/conversations-api) （すでに 2017 年から長期的移行を視野に提供されてきた API です）にて全て可能となっています。

**Conversations API（英語）**
https://api.slack.com/docs/conversations-api

[`conversations.*`](https://api.slack.com/docs/conversations-api) へ移行することで、これら 4 種類のリソースを一つの API コールで取得したり、共有チャンネルに適切に対応できるという新たな利点があります。

また、上記のアナウンスにもあります通り、`groups.*` につきましては 11 月の全面廃止よりも前のタイミングで新しく作られた private channel の操作に対応しなくなる可能性があります。この記事投稿時点で、提供停止までまだ 10 ヶ月以上ありますが、なるべく早いタイミングでの [`conversations.*`](https://api.slack.com/docs/conversations-api) への移行をおすすめします。

API のレスポンス構造などが大きく変わるものではないので、移行は比較的容易に行っていただけるはずですが、お手数をおかけします。何卒よろしくお願いします。:bow:
教育用小型ドローンTELLOを用いた追従機能の開発

ー初めての投稿ー
初めまして，現在大学四年生です。
私は，TELLOを用いて追従機能の開発（といってもそんなに立派なものではありませんが...）をしています。
担当の教授の専門分野が電子回路系で，プログラムのことを聞けずお手上げ状態です。
至らぬ点もございますが，どうかお助けください。


ー開発環境ー
---windows10
---python


ープログラミングの中身ー


import socket
import threading
import cv2
import numpy as np

event = threading.Event()

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

cap = cv2.VideoCapture(0)


width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

X = width//2
Y = height//3

W = width//2
H = height//2

x = width//2
y = height//3

w = width//2
h = height//2



gain_vx = 3
gain_vy = 3

gain_bf = 0.0022


gain_x_1 = 0.15
gain_y_1 = 0.1

gain_x_2 = 0.0003
gain_y_2 = 0.00005

dx = X - x
dy = Y - y





sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
sock.bind(("", 9000))

tello_address = ("192.168.10.1", 8889)


def send_command(msg):
    print(msg)
    msg = msg.encode(encoding="utf-8")
    sock.sendto(msg, tello_address)
    event.wait()
    event.clear()



def recv():
    while True:
        try:
            data, server = sock.recvfrom(1518)
            print(data.decode(encoding="utf-8"))
            event.set()
        except Exception:
            break
recvThread = threading.Thread(target=recv)
recvThread.start()




def tracking(dx,dy,vx,vy):



    if 5 < dx <= 150:
        print('right')
        drone.right(gain_x_1*dx + gain_vx*vx)

    if -150 <= dx < -5:
        print('left')
        drone.left(- gain_x_1*dx - gain_vx*vx)

    if dx > 150:
        print('right')
        drone.right(gain_x_2*dx*dx + gain_vx*vx/2)

    if dx < -150:
        print('left')
        drone.left(gain_x_2*dx*dx - gain_vx*vx/2)

    if dy > 5:
        print('down')
        drone.down(gain_y_2*dy*dy + gain_vy*vy/2)

    if dy < 5:
        print('up')
        drone.up(gain_y_2*dy*dy + gain_vy*vy/2)

    else:
        print("___ERROR___")





def main():
    try:
        send_command("command")
        send_command("streamon")
        send_command("takeoff")


        cap = cv2.VideoCapture("udp://0.0.0.0:11111")

        while True:
            ret, img = cap.read()
            cv2.rectangle(img, (X, Y), (X+W, Y+H), color=(0,0,255),thickness= 4)


            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray, 1.3, 5)
            for (x,y,w,h) in faces:
                cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
                roi_gray = gray[y:y+h, x:x+w]
                roi_color = img[y:y+h, x:x+w]
            cv2.imshow('img', img)

            tracking(dx,dy,vx,vy)


            if cv2.waitKey(1) & 0xFF == ord('q'):
                break




    except Exception as ex:
        print (ex)

    finally:
        cap.release()
        cv2.destroyAllWindows()
        send_command("streamoff")
        sock.close()
        print("--- END ---")

if __name__ == "__main__":
    main()


ーうまくいかない点ー
①フレームスキップを入れるとしたらどこが適切か
➁そもそもフレームスキップ云々以前の問題なのか

よろしくお願いいたします。

ー参考にさせていただいたサイトー
https://atsblog.org/tello_tracking_camshift/
http://totech.hateblo.jp/entry/2017/10/22/100726
企画〜リリースまでの流れフロー図 メモ_φ(･･


プロダクトの企画から携わって開発したいと思いあれこれやってる備忘録メモです。

企画の進め方やPJTの進め方は、本などで大枠はあっても、フェーズや規模、文化、人、状況などにより
微妙に違ったり細かいところが抽象的だったりするので、
自分なりの昨年 経験したフローを図に整理してみました。

## 今回の前提

- **プロダクト**：多機能なツール系 Webサービス
- **フェーズ**：提供する機能(価値)の大枠は決まっていて改善フェーズ
- **状況**：自社開発で厳密な細かい仕様書をまとめる文化はあまりない。
- **今回の役割範囲**：プロダクトの改善要望の収集から企画、計画、要件定義、仕様UI設計、開発に落とし品質チェックやPJT全体管理まで

## 前回

この記事の先に、テキストで
フローの全体像、各説明と、工夫してやってみてよかったと思うやり方の紹介を
少し前に次にあげました。(図を書くときに書き直した部分があり少し差異あります)

📝[PO・PM・SE 的 プロダクトの「改善フロー」「設計推進方法」「PJT管理」備忘録](https://tech.basicinc.jp/articles/182)

今回は、テキストだけだと 辛いので^^; 図解にしてみたのをメモしておこうと思います。
※各フローのステップごとの詳細は上記記事にあるので今回は割愛

## 企画〜リリースまでのフロー図

※P企画：プロダクト企画
![企画〜リリースまでのフロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6714/29acedad-0116-53d1-9d79-5d8d8a22df8b.png)

どの段階でどのステークホルダーと相談・確認しないといけないのか
プロジェクトによって違ってくると思うので、こうしてフロー図にすることで、
早めに関係者との打ち合わせの予定を確保したりそれに間に合うように事前準備をしたりと考えやすくなるので
こういう普段の進め方を整理すると チームで共通認識が持ちやすくなっていいのかもと思いました☺️

## 過去に書いた関連記事

- 📝[PO・PM・SE 的 プロダクトの「改善フロー」「設計推進方法」「PJT管理」備忘録](https://tech.basicinc.jp/articles/182)
- 📝[UIUX改善リニューアルに向けてのディレクションとUI設計準備メモ - Qiita](https://qiita.com/hitomi_/items/ea52477db415203629ec)
Coil+Twitter4JでTwitterのDM添付画像をロードする

# やりたいこと

Android用の画像読み込みライブラリ [Coil](https://coil-kt.github.io/coil/) を使うと、下記の1行だけで任意のURLの画像をダウンロードして `ImageView` に表示することができます。

```Kotlin
imageView.load(imageUrl)
```

Twitterクライアントのようなアプリでツイートの添付画像を表示する場合は上記のコードで十分ですが、DM(メッセージ)の添付画像の場合は[認証が必要](https://developer.twitter.com/en/docs/direct-messages/message-attachments/guides/retrieving-media)となるので 401 が返ってきてしまいます。

```
    coil.network.HttpException: HTTP 401: 
        at coil.fetch.HttpUrlFetcher.fetch(HttpUrlFetcher.kt:57)
        at coil.fetch.HttpUrlFetcher$fetch$1.invokeSuspend(Unknown Source:16)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:561)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:727)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:667)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:655)
```

ちなみに上記のエラーは `listener` の `onError` で取れます。

```Kotlin
imageView.load(imageUrl) {
    listener(onError = { _, throwable ->
        Log.e(TAG, throwable.message, throwable)
    })
)
```

これまで `Twitter4J` で DM の添付画像を取得したい場合は下記のように専用のメソッドを利用していました。

```Kotlin
// DM添付画像対応のため認証付きで取得する
twitter.getDMImageAsStream(imageUrl)
```

この `InputStream` を `Coil` に渡せればいいのですがあいにくそんなI/Fはないので、別の方法が必要です。

# Coil に認証ヘッダーを設定する

前置きが長くなりましたが、`Coil`でTwitterの DM 添付画像をロードするには下記のように認証ヘッダーを設定するだけです。

```Kotlin
imageView.load(imageUrl) {
    val twitter = ... // 何らかの方法で Twitter4J の Twitter インスタンスを取得する
    val req = HttpRequest(RequestMethod.GET, imageUrl, null, twitter.authorization, emptyMap())
    val authorizationHeader = req.authorization?.getAuthorizationHeader(req)
    addHeader("Authorization", authorizationHeader)
}
```

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おお、Coil経由でDMの画像取れた！ <a href="https://t.co/F83xafcX8I">pic.twitter.com/F83xafcX8I</a></p>&mdash; 竹内裕昭 (@takke) <a href="https://twitter.com/takke/status/1214753740579672065?ref_src=twsrc%5Etfw">January 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

`Coil` 便利だなー。


# 参考文献
- [［Android］ 画像読み込みライブラリ Coil でできることまとめ \- Qiita](https://qiita.com/kaleidot725/items/b2ca56bfc5a8120efcea)
- [Retrieving media — Twitter Developers](https://developer.twitter.com/en/docs/direct-messages/message-attachments/guides/retrieving-media)
TypeScriptでReactのArrayを返すだけのFunctional Componentがエラーになる

ReactでTypeScriptを使っているときに

```TypeScript
const FuncComp = (props: any) => {
  return [
    <div>hoge</div>,
    <div>hehe</div>
  ];
}
```

とするとエラーになる。TypeScriptを使っていない場合には意図したとおりに動作する。

エラーにはなるのですが、一瞬ちゃんと表示された後にエラー画面になるので良くわからん。
ちゃんと調べてないけど、関数が最適化で展開されてるっぽい？

以下の様にFunctional ComponentをFunctionで型指定すると問題がなくなる。

```TypeScript
const FuncComp: Function = (props: any) => {
  return [
    <div>hoge</div>,
    <div>hehe</div>
  ];
}
```