OmniAICreator/Qiita-1.07M huggingface dataset:
bundle exec rails routesで特定のroutesのみ表示する

最近Qiitaを開くと、Rails系の自分の記事にいいねがよくついてます。

新人エンジニアや未経験エンジニアの方が多くなったからかなーと思いつつ、こんなものあれば便利なんじゃね？と思ったので書いてみます。

Linuxコマンドがわかる人は当然っちゃ当然のことをやっているので、見る必要はないです。

## 特定のrouteを取得

railsでrouteが多くなると目的のものを目視で探すの、クソだるいですよね？

なので、パイプでgrepを渡してあげます。
   
```
$ bundle exec rails routes | grep product
root         GET            /                                                                                        products#index
products     GET            /products(.:format)                                                                      products#index
             POST           /products(.:format)                                                                      products#create
new_product  GET            /products/new(.:format)                                                                  products#new
edit_product GET            /products/:id/edit(.:format)                                                             products#edit
product      GET            /products/:id(.:format)                                                                  products#show
             PATCH          /products/:id(.:format)                                                                  products#update
             PUT            /products/:id(.:format)                                                                  products#update
             DELETE         /products/:id(.:format)                                                                  products#destroy
```

さらに、`GET`のrouteだけ表示したいときは、

```
$ bundle exec rails routes | grep product | grep GET
root         GET            /                                                                                        products#index
products     GET            /products(.:format)                                                                      products#index                                      
new_product  GET            /products/new(.:format)                                                                  products#new
edit_product GET            /products/:id/edit(.:format)                                                             products#edit
product      GET            /products/:id(.:format)                                                                  products#show
```

こんな感じで、`grep <文字列>`を`|`でどんどん渡していけば絞って表示できます。

Linuxコマンド使えたら誰でも普通にやると思いますけど、Rails初心者でコマンドわからない方は是非使って活用してみてください。

## 補集合を取得

特定のroute以外を見たいときは以下を使います（たぶんこんな使い方はしないと思うけど）。

```
$ bundle exec rails routes | grep product | grep -v GET
POST           /products(.:format)                                                                      products#create
PATCH          /products/:id(.:format)                                                                  products#update
PUT            /products/:id(.:format)                                                                  products#update
DELETE         /products/:id(.:format)                                                                  products#destroy
```

`-v`オプションを使えば、それ以外のものが表示できます。

## 新人エンジニアの方へ

最初はいろいろ大変かもしれないですが、ググり散らかしてどんどんサービス作ってエンジニア界隈を盛り上げてください！

僕ももっと有用な記事をかけるように日々精進します:muscle:
Ruby最大値(max)と最小値(min)の位置インデックス(index)を得る方法

```:ruby
 a=[1,2].each_with_index.max[1]
#=>1
 a=[1,2].each_with_index.min[1]
#=>0
```
1番から始めたい場合

```:ruby
 a=[1,2].each_with_index.max[1]+1
#=>2
 a=[1,2].each_with_index.min[1]+1
=>1
```
参考
https://stackoverflow.com/questions/2149802/in-ruby-what-is-the-cleanest-way-of-obtaining-the-index-of-the-largest-value-in
Kerasの重みの初期化タイミング

#Kerasの重みの初期化タイミング
##はじめに
ニューラルネットワークを使う際に、重みのよる初期化の違いを飽和するために複数回に渡って学習させなおし、平均した結果が欲しいことがあります。
しかし、自分が初心者のため、どこで重みの初期化が行われているかわからなかったので検証してみました。

##結論
先に結論を書きます。
重みはレイヤーの追加時に初期化されてるようです。
公式のドキュメントにも書いてありました。
https://keras.io/ja/initializations/

このページは読んでいたのですが、初期化方法を定義するだけだと勘違いしていました。

##二回立て続けに学習させた場合


```python
#引数は見易さのため省略しています
model.fit()
model.fit()
```
このようにfitを二回行った場合は、重みは初期化されず、続けて学習されているようです。
2回目の学習のlossの値がほぼ変わらずに始まります。（1回目のEpochでは1.0以上のlossです）
<img width="569" alt="スクリーンショット 2018-11-05 12.19.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/241671/45d4d54b-4395-742d-cbc9-8890b0cdb7a3.png">

##途中にcompileを挟む

```python
#引数は見易さのため省略しています
model.fit()
model.compile()
model.fit()
```
きっとダメだろうな、と思いつつも実行。
<img width="713" alt="スクリーンショット 2018-11-05 15.04.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/241671/7161a4b3-32aa-11b5-2532-89b8dd95999f.png">
やっぱりダメでした。

##レイヤーをもう一度追加

###追記
この方法だと層が追加されているだけで上手くいかないことを教えていただきました
(追記終わり)


ここで、ようやく私は、公式ドキュメントに書いてあることが初期化法を定義しているだけではない、という考えに気がつきました。

```python
#引数は見易さのため省略しています
for i in range(2):
        model.add()
        model.add()
        model.add()
        model.summary()
        model.compile()
        model.fit()
```

<img width="718" alt="3.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/241671/a2371230-7533-cc7c-01ef-88db19322576.jpeg">

~~lossがちゃんと高くなっている……！~~
層が追加されているためにlossが高くなっていることをコメントで指摘していただきました。

##層の初期化とレイヤの追加
```python
for i in range(2):
        model = Sequential()
        model.add()
        model.add()
        model.add()
        model.summary()
        model.compile()
        model.fit()
```
modelを初期化してから、層を追加する必要があります。


##おわりに
私の読解力に難ありでした。
もし間違っていたら、コメントいただけると嬉しいです。
AWS DevAWSomeDayに行ってきました

## はじめに
* 今年になってWeb業界のエンジニアに転職し、いろいろと業務をしていくなかでやはり(今更感がすごいですが)ちゃんと勉強してこよう！と思い、AWS DevDayの1日目(2018/10/30)に開催されたDevAWSomeDayに参加してきました。

## 私のクラウド経験について
* AWS: 未経験。部門内でAWS上で稼働しているプロダクトがあるので、その関係でいくつかの機能について知識がある程度
* GCP: 自社のプロトタイプ開発でCloudFunctionやNaturalLanguageAPI触った程度

## 内容(ざっくり)
* AWSの基礎知識から解説してくれるセッションと、簡単なWebアプリケーションを作成するハンズオンが交互にありました。
* ハンズオンにつきましてはAWS運用・開発経験者の参加も想定しているのか、時間が余った人用のラボもありました。
* 終了後にはセッション・ハンズオン共に資料をダウンロードさせていただきました。完了後もこれをつかって復習可能です。
 * ちなみに、会場はWifiおよび電源タップ共に用意されていました。
* 基本的にAWSのインスタンス構築などはWebブラウザのコンソールででき(ると思い)ますが、場合によってはCloud9のターミナルからコマンドを叩く場面もあります。そのあたり、メインターゲットはやはりエンジニアな印象です。

### ハンズオンで使ったサービス
※ひとつひとつの解説は省略させていただきます。

* AWS Identity and Access Management(IAM)
* AWS Cloud9
* Amazon Cognito
 * セッションのなかでは、今後はAWS AppSyncを推奨するみたいなことを行ってました
* Amazon S3
* Amazon DynamoDB
* AWS lambda
* Amazon API Gateway
* AWS CLI

※応用編的なハンズオンでは、Amazon Recognitionも使います。

## 完走した感想ですが
* 初見だと何を使っていいかわからなかったAWSでしたが、手順を踏んで実際に触ることでようやくこの機能が何をしているのか、がよくわかったと思います。
    * AWS全く触ったことなくて、これから勉強したいと思うひとは絶対いくべきだ！と思いました。
* ハンズオン参加者の中には、エンジニアを本職としない方や既にAWSの運用に携わっている方もちらほらいらっしゃいました。
* 会社に2017年のDevAWSomeDayに参加された先輩がおり、事前にその時の資料も見せてもらっていたのですが、その時とも全然違う内容でした。なので、リピートで参加する人もいるのかも？
古いMacとOSXとファイルメーカーの相互互換表

FileMakerの互換問題に関する覚書

Mac本体と搭載可能OS
そして動くFaileMakerのバージョン表
![OSX-FM.jpg](https://qiita-image-store.s3.amazonaws.com/0/311074/08febbcb-b4d7-7a6f-920e-29370dca4fec.jpeg)
AWS Dev Day Challengeで優勝したのでその振り返り

# AWS DevDay Challenge

AWSの東京本社オフィスで開かれたアプリケーションデベロッパー向けイベント
「AWS DevDay Tokyo 2018」の最終日に行われた開発コンテストです。  
当日の朝に出されたお題の中から１つを選び、それをチームで実装して、
最後に、その日の夜に行われるアフターパーティ内で発表を行い、
AWSのソリューションアーキテクトの方達が独断で「一番イケてる」ものを選び表彰するというものです。  

**そのコンテストに社内の有志3人（@w-iijima、@wpuzzle_minegishi、私）で格安SIMというチームで参加し、
優勝してきました！**

当日、どんな様子だったのかつらつらと書いていきたいと思います。

# 当日の様子

### 9時頃
目黒駅でメンバーと待ち合わせてAWSのオフィスへ。
会場の[AWS Loft Tokyo](https://aws.amazon.com/jp/start-ups/loft/tokyo/)に到着すると、DevDay Challenge参加者向けに朝食としてサンドイッチと飲み物が無料で配られていました！（写真撮り忘れました）

ここは広々としていて明るく静かで、WiFiも電源も無料で使用できますし、
カフェも設置（良心価格）されているという素晴らしい環境でした。  

![IMG_3997.jpg](https://qiita-image-store.s3.amazonaws.com/0/262735/9f569597-9418-7b01-c1ef-58a9b204522e.jpeg)

ちなみに、この[AWS Loft Tokyo](https://aws.amazon.com/jp/start-ups/loft/tokyo/)は、イベント等がない日はコワーキングスペースとして
AWSアカウントを持っている人には無料で開放されていて、AWSのことでわからないことがあれば
相談コーナーにいるSAの人たちにすぐ話を聞けるという素敵な場所です。

AWS Loft Tokyo
https://aws.amazon.com/jp/start-ups/loft/tokyo/

### 9時45分頃

満を持して、運営の方から発表されたお題は４つ

- Chat
- ChatBot
- SNS
- 動画投稿サイト

マシンラーニング系が来るのかと思ったりしてたのですが、わりと基本的なWEBアプリでした。
我々はこの中から、プレゼン映えを狙って動画投稿サイトを選択しました。  

コンセプトはガヤ感あふれる「ガヤガヤ動画」に決定。
概要としては、

- スマホを使って動画を投稿。
- 投稿した動画はWEBサイト上にリアルタイムに追加されていき画面が動画で埋め尽くされるというもの。
- 投稿された動画はリピート再生させてガヤ感をアップ


### 11時頃

チームメンバーで分担しながら作業を進めていきます。
私は、アーキテクチャ図を[cacoo](https://cacoo.com/ja/)で作成するのと、
スマホから送信するフロント側の実装とS3のPutEventでIoT CoreにPublishするLambdaの実装を担当しました。

今回の構成は全てがマネージドなサービスで完結するサーバーレスな構成で、
S3を起点にイベントで駆動するというサーバーレスとしてはオーソドックスなものです。

開発者的には複雑なAWS構成にしてドヤりたいのですが、
最初に決めた「プレゼン映え」を狙うには、限られた時間内で完全に動くデモを用意する必要がありました。
ですので、デモが未完成でフィニッシュしてしまうリスクを避けて、
あえてシンプルな構成にして完成させることを最優先にしました。
（今回のイベント向けの一発アプリなので、ライフサイクル管理についてはバッサリ捨てました）

![Untitled (3).png](https://qiita-image-store.s3.amazonaws.com/0/262735/2ddf1744-c8dd-d741-1f90-c27a8a2a83a6.png)
※これには記載していませんが、WEBコンテンツは全てS3でホスティングさせています。

### お昼

無料でお弁当とお茶が配られました。（写真撮り忘れました）
切りの良いところでご飯タイムで気分転換します。

### 15時頃

それぞれの作業がある程度完成したところで、全てを繋げてテストするために
動画を撮影して投稿していきます。
コワーキングスペースの一角にSnowball等珍しいものも展示されていたので、
動画撮影と気分転換も兼ねてうろつきます。
（一歩間違うと不審者に間違われそうです。）

### 16時頃

テストをしながら細かい調整を終わらせて、@w-iijimaがプレゼン資料を作成していくのを見守ります。
このイベントに参加しようと思ったときから、発表者は彼にお願いするつもりでしたので、大船に乗ったつもりでおまかせです。
  
プレゼンでリアルタイムに動画が投稿されていく様子を見せたかったので、
メンバーで相談しながら、スライドの順番等微調整をして最終的な段取りを確認しました。

### 18時頃

AWS DevDayのアフターパーティがはじまりました。
立食形式のパーティで、食べ物や飲み物が振る舞われました。

そして、司会の方のアナウンスと共に、DevDay Challengeのチームのプレゼンがはじまります。

### 18時30分頃

我々チームの発表がはじまりました。
各チームの持ち時間は３分と、かなり短いため時間をオーバーするチームもあったのですが、
@w-iijimaはピッタリ３分でまとめまてくれました！
完璧なプレゼンだったと思います。

下の写真はDevDay Challenge結果発表の前に、
アフターパーティ参加者による言語、エディタの投票結果発表の様子。
ちなみに言語トップはPython、エディタトップはVS Codeでした。（予想通りでしたね）
![IMG_4948.jpg](https://qiita-image-store.s3.amazonaws.com/0/262735/460a601e-f277-b4b7-40cf-f54e5f165351.jpeg)

# 結果発表

19時頃に結果発表があり、なんと我々、格安SIMチームが優勝しました！（もちろん写真は撮り忘れています）
他のチームも力作ぞろいだったので、その中で選ばれたのは非常に嬉しいです。

ちなみに、技評の[Software Design](https://gihyo.jp/magazine/SD)編集部の方が
AWS DevDay Tokyo 2018の取材に来られていて、
このイベントの模様も掲載していただけるようですので、
どんなイベントだったのか興味がわいた方はぜひ[Software Design](https://gihyo.jp/magazine/SD) １月号をご覧いただければと思います。

# さいごに

運営スタッフの方々のおかげで、とても快適な環境の中で
集中して楽しみながら作業をすることができました。
ありがとうございました！
Laravel 独自バリデーションのメッセージに指定したパラメータを載せたいんじゃー

ほい。

Laravelで独自バリデーションの実装は調べると結構出るが、独自バリデーションのパラメータをメッセージに埋め込む方法がいまいちわからなかったので備忘録のアレ

まずアレでバリデーションのサービスプロバイダーを作る。名前とかは何でもおｋ

```
php artisan make:provider ValidatorServiceProvider
```

validate* としたら独自バリデーションを定義できるのは調べたらすぐ出る
replace* としたら独自バリデーションのメッセージの置換を実装できる ← **これのやり方を調べてもいまいちでなかった**

`app/Validator` 配下に CustomValidationクラスを作成

```php

<?php

namespace App\Validator;

class CustomValidation extends \Illuminate\Validation\Validator
{
    // 数値化指定した指定した日付フォーマットのみ許可 
    public function validateIntegerOrDateFormat($attribute, $value, $parameters)
    {
        if (is_numeric($value)) {
            return true;
        }

        if (false !== \DateTime::createFromFormat($parameters[0], $value)) {
            return true;
        }

        return false;
    }

    // メッセージの:formatという文言を置換してリターン
    protected function replaceIntegerOrDateFormat($message, $attribute, $rule, $parameters)
    {
        return str_replace(':format', $parameters[0], $message);
    }
}

```

ほんでプロバイダに登録

```php
<?php

namespace App\Providers;

use App\Validator\CustomValidation;
use Illuminate\Support\ServiceProvider;

class ValidatorServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        \Validator::resolver(function ($translator, $data, $rules, $messages) { // （１）
            return new CustomValidation($translator, $data, $rules, $messages);
        });
    }

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
```

メッセージ定義

src/resources/lang/ja/validation.php

```php
return [
    // 前略
    'integer_or_date_format' => 'フォーマットが不正です。数値、または":format"の形式で入力してください',
];

```

指定方法

```php
$validator = Validator::make($params, [
    'input_hoge' => 'integer_or_date_format:Y-m-d'
]);
```

これで 
`フォーマットが不正です。数値、または":format"の形式で入力してください` 
これが
`フォーマットが不正です。数値、または"Y-m-d"の形式で入力してください`
になる

やったぜ。
Kotlin to Scala cheat sheet

Kotlinをやったことがあって、Scalaをやったことがない人向けのシンタックスチートシート。
細かい動作の違いや仕様の違いは書いてません。

|概念|Kotlin|Scala|
|:---:|:---:|:---:|
| top level |function|object|
|companion object| companion object| object |
| Value Object |data class | case class|
| 関数 | fun | def|
| forでの初期代入 | in | `<-`|
| range | 0`..`10 | 0 `to` 10|
| forでの値飛ばし |step, downTo | by |
| パターンマッチ | when ~ is | match ~ case |
| インスタンス生成 | Foo() | new Foo |
| コンストラクタ | constructor | def this |
| インターフェース | interface | trait |
| ジェネリクス | `<T>` | [T] |
| 変性 | out, in | +, - |
| lamda | `->` | `=>` |
| nullable | String? | Option[String] |
| build tool | gradle | sbt(Scala Build Tool) |
| スコープ関数 | with, apply, let, run, also | 対応なし |
| 拡張関数 | fun クラス名.関数名() | pimp my library |
| 暗黙的な型変換など | 対応なし | implicit |
| 関数の空実装 | TODO() | ??? |
| formatter | ktlint | Scalafmt, Scalareform |

Scalaでしかできないもので勉強した方がよさそうなこと

- implicit
- Pattern Match
- モナド
PHPからC言語へ

こんにちは。

最近は、C言語を学んでいます。

PHPを元々やっていた関係で

C言語の理解も早いものですが、

だからと言って書き方は全く違うし

用語も若干違うので一つ一つ学びなおしています。

後置インクリメントやら前置インクリメントやら

知らなかったキーワードを学習しています。

また、「やさしいC」という本の内容をCentOS7のgcc環境で

勉強を進めています。非常に楽しいです。

viエディタの使い方は覚えていきますし

C言語のコンパイルのやり方も覚えましたし

できることが少しずつ・・・少しずつ増えています。

現在は、優しいCの４章まで終わらせました。

次は５章から勉強です。

基礎は大切なので１回やったら

２回目もう一度最初からやり直す

っていう事もしてみたいなと思っています。

PHPもCもそうなんですが

「やっていて楽しい」と思えるんですね。

職業としては私のレベルは全然通用しないものではありますが

職業としてではなくプライベートとしてだったら

エンジニアやっていてもいいよなぁとか思っています。

スキルアップのためにMOSも受けようかと考えていますし

LinuCも受けようと考えています。

仕事では使わないにしてもプライベートでは深い知識まで

身に着けていきたいので身に着けて何かを生み出せればな

と思っています。
意外と躓くgraphviz(備忘録)

scikitlearnの本で出てきたけどうまく入れられなかった描画ライブラリのgraphvizをpython上で使うことができたので備忘録としてまとめる。めっちゃ雑記。
これでやっと決定木のお絵かきができますね^^

環境：linux系, python3.6

## terminal上での操作
anaconda環境の人はcondaコマンドで入れた方がいいです。
コマンドを通すときにpipだと探してくれないっぽいです。

```
$conda install graphviz
```
次にdotファイルを探します。
これを環境変数に設定しておいてやっとgraphvizが動作します。
私のような初心者はここらへんが一番沼ったと思います。

```
$type dot
dot is /home/user/.conda/envs/…/dot
```
あとはこれがどこからでも実行できるように環境変数PATHに追加してあげれば動きますね。
「export PATH=$PATH:」以降は先ほどの出力されたものをコピペするだけです。

```
$export PATH=$PATH:/home/user/.conda/envs/…/dot
```

動作確認です。
```
$dot -V
dot - graphviz version ....
```
GASの覚書

## GASのいろんなメモ
GASの個人的なメモです。
扱うことが少ないので、備忘録的に要点をまとめます。
**随時更新**します。

## ログ
#### ログを表示させる
```javascript
Logger.log(XXXX);
```

## スプレッドシート操作
スプレッドシートに関する操作について。
<br>

### スプレッドシートの取得
#### アクティブなスプレッドシートを取得
アクティブなスプレッドとは、スクリプトが紐づいているスプレッドシート。
以下で取得できる。

```javascript
SpreadSheetApp.getActiveSpreadSheet()
```

##### ↑ここで出てきたSpreadSheetAppとは?
スプレッドシートのグローバルオブジェクト。ルートオブジェクト。

<br>

### シートの取得
#### シート名を指定してシートを取得
```javascript

スプレッドシートのオブジェクト.getSheetByName('シート名')
```
ただし、シート名はユーザーが変更できるので注意が必要。
スプレッドシートに含まれるシートが一つの場合は次の方法を使う。

#### アクティブなシートを取得
```javascript
スプレッドシートのオブジェクト.getActiveSheet()

//もしくはこれ↓
SpreadsheetApp.getActiveSheet()
```

<br>

### シート内のセルやセル範囲の取得

#### アドレスを指定してセル範囲を取得する
ここでいうアドレスとは、セルのアドレス。例えば、A10とか[F10:I13]とか。

```javascript
Sheetオブジェクト.getRange(アドレス)

// 例
getRange('C3')
getRange('B2:C3')
```

#### 行番号と列番号を指定して、取得
```javascript
// 引数は数値型
Sheetオブジェクト.getRange(行番号, 列番号)

// 例
getRange(2,2)     //B2を取得
getRange(2,2,3,3) //B2:C3を取得
```
A1の場合は、1行目の1列目。


#### 単体セルの取得
```javascript
Rangeオブジェクト.getValue()
```

#### 複数セルの取得
複数セル = 範囲を取得する場合は、返り値は２次元配列となる。

```javascript
// sを忘れない
Rangeオブジェクト.getValues()

// 例
Sheetオブジェクト.getRange('A2:C3')
Rangeオブジェクト.getValues()

//　↑を実行すると返り値はこうなる。
[
  [A2セルの値, B2セルの値, C2セルの値], 
  [A3セルの値, B3セルの値, C3セルの値] 
]
```

### シートの最終行を求めるgetLastRow
for文まわして取得するときに便利なgetLastRowメソッド

```javascript
Sheetオブジェクト.getLastRow()
```
Xamarin.AndroidでのJavaScript⇔WebView間のやり取り

# addJavascriptInterface

AndroidのWebViewは`addJavascriptInterface`メソッドでJavaScriptから呼び出せるメソッドを作成できる
参考: [JavaScript から Android 側のメソッドを呼び出す](https://qiita.com/hkusu/items/3777b75aa5bf130e9202)

これがXamarinの場合はいくつかおまじないが必要という話

## JavaScript用のクラスを作る

ポイントは３つ

1. Java Objectを継承させる
2. 公開するメソッドにJavascriptInterface属性を付与
3. 公開するメソッドにExport属性を付与

```c#:JavaScriptHandler.cs
//1. Java Objectを継承
class JavaScriptHandler : Java.Lang.Object
{
    //2. 3. 属性付与
    [Export]
    [JavascriptInterface]
    public void hogehoge()
    {
        SomeFunction();
    }
}
```

1.はXamarinでJavaっぽいことやるときはいつものおまじない
2.はAndroid 4.2以降`addJavascriptInterface`がセキュリティ面で制限されたことによる影響でJavaの場合でも必要

3.がXamarinのときにだけ必要なおまじない
ここにたどり着くのに色々調べまわった…
なお、これをつけるためにはプロジェクトの参照に`Mono.Android.Export`を追加する必要がある

## 参考

- [teratail: XamarinでWebviewを使ってのJavascriptとAndroidの連携ができません。](https://teratail.com/questions/83658)
- [AndroidのWebViewのaddJavascriptInterface](https://kujirahand.com/blog/index.php?Android%E3%81%AEWebView%E3%81%AEaddJavascriptInterface)
AndroidStudioとXcodeのショートカット対応表(Mac版)

# ショートカット対応表

機能 | Android Studio | Xcode
-----|-----|-----
ファイル検索 | Command + Shift + O | Command + Shift + O
自動フォーマット | | Ctr + i


# 参考
- [Android Studio 
キーボード ショートカット](https://developer.android.com/studio/intro/keyboard-shortcuts?hl=ja)
Amazon RDS for MySQL から Amazon Aurora Serverless へ乗り換えたお話

# はじめに

[Amazon RDS for MySQL](https://aws.amazon.com/jp/rds/mysql/) から [Amazon Aurora Serverless](https://aws.amazon.com/jp/rds/aurora/serverless/) へ乗り換える機会があったので、勘所のようなものをご紹介します。この記事では Java, [SpringBoot](https://spring.io/projects/spring-boot) を前提に記載していますが、本質は言語やフレームワークを問わない内容ですので、適宜ご利用の環境に読み替えてご覧頂けると幸いです。


# Amazon Aurora Serverles とは

詳細は公式のドキュメント等をご確認頂きたいのですが、大きな特徴としては管理するインスタンスを持たない点が挙げられます。少し乱暴な例えかも知れませんが、 [AWS Lambda](https://aws.amazon.com/jp/lambda/) のデータベース版のような仕組みで、データベースを使用するタイミングでデータベースサーバが起動、使い終わったら停止するような動作となり、その間に利用した Aurora Capacity Unit (ACU) の使用量で課金されるといったサービスになります。(正確には ACU 以外にもデータベースストレージと I/O で別途料金は発生します)


# Amazon Aurora Serverles の使い所

私の場合は、Amazon RDS for MySQL を社内のシステムで使用していましたが、それを Amazon Aurora Serverles に乗り換えました。このシステムは基本的に営業時間内しか利用しないのと、それほどシビアな応答時間を求められないという前提がありましたので、データベースが起動するまでの時間はさほど気にせずともよく、営業時間外ではコスト面からむしろ停止しておきたいという状況で Amazon Aurora Serverles の利用には適したシステムでした。

一方、 24 時間 365 日 、いかなる時も素早い応答を求められるようなシステムでは、あまり適しているとは思えませんので、システムの特徴を理解した上で適切なサービスを選択することが重要と言えそうです。


# Amazon Aurora Serverles のハマりどころ

ハマりどころというのは少し語弊があるかも知れませんが、データベースのコネクションプールを使用しているケースでは少し注意が必要になります。使用しているフレームワークやその設定にも依りますが、コネクションプールを使用していると多くの場合はデータベースに対する接続を恒常的に持ち続けている状態となる為、 Amazon Aurora Serverles がいつまで経っても停止しないという状況に陥ります。この状況を避けるには、コネクションプールの設定を見直したり、コネクションプールを止めるなどの対応が必要になります。

私の場合は、 SpringBoot 2.0 で [HikariCP](http://brettwooldridge.github.io/HikariCP/) というコネクションプールを利用しておりましたので、この設定を変更する方向で対応しました。変更したのは以下のプロパティのみとなります。

```
spring.datasource.hikari.minimum-idle=0
spring.datasource.hikari.idle-timeout=180000
```

`spring.datasource.hikari.minimum-idle` はコネクションプール内で維持されるアイドル接続の最小数で、 `spring.datasource.hikari.idle-timeout` はコネクションプール内で接続がアイドル状態に切り替わるまでの時間（ミリ秒）です。

これらの設定を行う事で、 180 秒後に接続はアイドル状態となり、アイドル接続は維持しないという設定から、コネクションプールから接続が破棄されるという状態になります。これで使用がない時はコネクションプールから接続破棄されて、 Amazon Aurora Serverles が停止できる状態を作り出すことができました。


## Spring Session との相性

さらにニッチな話になりますが、アプリケーションのセッション管理に [Spring Session](https://spring.io/projects/spring-session) を利用しており、そのセッションストアに Amazon Aurora Serverles を使用する場合も少し注意が必要になります。 Spring Session は有効期限が切れたセッション情報を削除するクエリを定期的に発行するのですが、デフォルトでは毎分このクエリが発行されます。毎分クエリが発行されると当然 Amazon Aurora Serverles が停止されない状況に陥ります。

このクエリの発行間隔については以下のプロパティで変更可能です。（デフォルト値は `0 * * * * *` です）

```
spring.session.jdbc.cleanup-cron=0 0 0 * * 0
```

上記の設定値の場合は毎週日曜日 00:00:00 に削除クエリが発行されるようになります。（このプロパティは、 cron とは違って「秒、分、時、日、月、曜日」であることにご注意ください）


# アプリケーションに対する影響

私のケースでは上記の設定変更を除くと、JDBC の接続文字列以外は何も変更する必要はありませんでした。データベースのサイズにも依存するのかも知れませんが、少なくとも私が対応したシステムでは Amazon Aurora Serverles は 20〜25 秒あたりで起動しており、一度起動さえしてしまえばこれまでと遜色ないパフォーマンスでアプリケーションが動作しています。


# まとめ

コネクションプール周りを除き、従来のリレーショナル・データベースと変わらない扱い方でサーバレスのデータベースに切り替えられるというのが本当に驚きでした。コネクションプールの部分も、知見のある方なら察しがつくと思われますので、記事内のハマるという表現も正直適切では無いのかも知れません。前提さえ合えば、コストや運用面で非常に有効なサービスだと思いますので、一度検討してみてはいかがでしょうか。
input file に同じファイルonchangeが発火されない

ファイルアップロードで型がfileのinputタグを使う時に、同じファイルを再度選択する時に、onChangeイベントが発火しないことを気づいた。
調べてみたら、同じファイルを選んだ時に、inputタグのvalueの値が変わってないから発火しない原因です。
その為、inputのonClickでvalueを初期化すれば、直れます。下記react用ソースコードをメモします。

- 修正前

```react

<input
  type="file"
  accept="application/pdf"
  value=""
  onChange={this.doUpload}
  />
```

- 修正後

```react

<input
  type="file"
  accept="application/pdf"
  value=""
  onChange={this.doUpload}
  onClick={(e) => {
    // valueを初期化する
    e.target.value = '';
  }}
  />
```

### 参考記事

- [JavaScriptで同じローカルファイルをもう一度読み込む](https://qiita.com/te20/items/00a72535163c6d632408)
Javaのfinalでずっと気になっていたこと

public class MainActivity extends AppCompatActivity {

    TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = findViewById(R.id.text_view);

        String a = "a";
        String b = "b";

        test(a);
        test(b);
    }

    private void test(String string){
        final String localStringFinal = string;
        mTextView.setText(localStringFinal);
    }
}

メソッド内のローカル変数（例ではlocalStringFinal）につけるfinalは、
呼び出し元が別ならば値をセットすることができる。

例では
test(a);
test(b);
でaとbをセットしている。
呼び出し元が違うため、bをセットすることができる。
（finalでも呼び出し元が違えば、一度だけ値をセットできる）
visual studio 2017 > 次のパラメーターと一致する製品が見つかりません



次のパラメーターと一致する製品が見つかりませんと表示されて更新が進まなくなった。

#### 結果以下を行う事でかいけつ

#### コマンドプロンプトでInstallCleanup.exeに -fullオプションを付けて実行する

InstallCleanup.exeは以下にあり。

 "%programfiles(x86)%\Microsoft Visual Studio\Installer\resources\app\layout\InstallCleanup.exe -full"



## 参考

[Visual Studio 2017をインストールする際にエラーが表示される - マイクロソフト コミュニティ](https://answers.microsoft.com/ja-jp/windows/forum/windows_7-winapps/visual-studio/e1096405-3d1a-46b0-9280-5e18463a6c95)

[A product matching the following parameters cannot be found: ](https://developercommunity.visualstudio.com/content/problem/96079/a-product-matching-the-following-parameters-cannot-2.html?childToView=113850#comment-113850)


```
Please follow the cleanup steps and retry your VS install

* See if you have this file on your machine: "%programfiles(x86)%\Microsoft Visual Studio\Installer\resources\app\layout\InstallCleanup.exe"
* If so, please launch it from an admin command prompt with a -full param:
InstallCleanup.exe -full

* If not, please manually delete the "%programfiles(x86)%\Microsoft Visual Studio\Installer” folder
Relaunch the newly downloaded vs_enterprise.exe (or vs_professional.exe or vs_community.exe…)
* Allow the first step to install the installer
* Once the installer comes up and you can see workload choices (.net desktop and the like), close it
* Go launch the same InstallCleanup.exe to clean up old build of VS

Then relaunch vs_enterprise.exe and install VS
```
php-master-changes 2018-11-04

今日は ext/ldap のテストの修正、ext/pcre のビルドシステムでの JIT サポートチェック方法修正、ext/fileinfo の libmagic の修正があった！
あと11/3はmasterへのコミットない日だった！

# 2018-11-04
## mizunashi-mana: Fix a test for ldap extension
- https://github.com/php/php-src/commit/e4121957725083223973ba5bbd5cd0ab42f2c5ef
- ext/ldap のテストがこける場合がある問題の修正
- pcntl_fork() 使うテストだしタイミング問題なのかなーと思ったものの、よく見ておらず

## weltling: Change the way JIT availability is checked
- https://github.com/php/php-src/commit/aea411657ee20572f8268060a4afa73bc3795497
- [7.3~]
- ext/pcre のビルドシステムで PCRE2 の JIT サポートチェックを修正

## weltling: Rework places in libmagic regarding previous CVE-2014-3538 fixes
- https://github.com/php/php-src/commit/7f5f46013b8a37bab6b378903aace5da9ce8dc5e
- [7.3~]
- ext/fileinfo で libmagic に [CVE-2014-3538](https://nvd.nist.gov/vuln/detail/CVE-2014-3538) 対策のパッチをあてていたが、上流で対策済なうえ、PCRE JIT が無効な時にパッチ箇所が原因で[性能問題](https://bugs.php.net/bug.php?id=77095)が出るようになっていたので、上流のコードから関連コードを引っ張ってくることで解決
Java アプリケーションから Aurora (MySQL) に接続する

## 概要
この記事で伝えたい事は、Java アプリケーションから Aurora (MySQL) に接続する時は、**MySQL Connector/J** では無く、**MariaDB Connector/J** を使え、という事

## Connector/J とは
Java から MySQL に接続するには、**JDBC ドライバ**を使用する必要がある
※JDBC とは、Java から リレーショナルデータベース (RDBMS) にアクセスする為の標準 API

MySQL に接続する際は、**Connector/J** 呼ばれる JDBC ドライバを利用する
ここでは MySQL が作成したものを **MySQL Connector/J**、MySQL から派生した MariaDB が作成したものを **MariaDB Connector/J** と呼ぶ

どちらでも Aurora (MySQL) で利用する事は可能だったが・・・

## Aurora (MySQL) には MariaDB Connector/J を選択すべき
先に結論を出すと、**Aurora のフェールオーバーに対応している**ので、選ぶなら MariaDB Connector/J だった

どうやら、Writer、Reader すべてのインスタンスにコネクションを張り、innodb_read_only が Off = master と判別する
その後は、クラスターエンドポイントより信頼できる replica_host_status を確認するみたい
※[これを参照](https://stackoverflow.com/questions/47163044/mariadb-connector-j-aurora-fast-failover-implemantation)

なお、[公式サイト](https://mariadb.com/kb/en/library/about-mariadb-connector-j/)には、対応するバージョンの記載があった

|Driver Version|Java Version|
|:--:|:--:|
|2.X|Java 9, Java 8|
|> 1.6.1 - < 2|Java 9, Java 8, Java 7, Java 6|
|1.2 - 1.6.1|Java 8, Java 7|
|1.1|Java 8, java 7, Java 6| 

## 実際に試してみた
MySQL Connector/J の場合は、コネクションが 0 となっている
![screen_capture_11-05.png](https://qiita-image-store.s3.amazonaws.com/0/269938/7790b0d8-e1c9-a62e-c64a-9571d4863c89.png)

MariaDB Connctor/J の場合は、Writer、Reader ともにコネクションが張られている状態となる
![screen_capture_11-05(0).png](https://qiita-image-store.s3.amazonaws.com/0/269938/b3f9686b-8519-9b2f-e991-523c80701c7c.png)

## 仲間募集中
[弊社](https://www.nittsu-infosys.com/)ではエンジニアを募集中です。インフラからアプリ、ユーザサポートまで幅広く業務を行ってます。
https://www.nittsu-infosys.com/recruit/2019/index.html
vuetifyでcard内のavatarを中心に持ってくる

# card内でavatarを使う

avatarをv-card内で使うと、画像が中心に持ってくるのが難しい

```vuejs
<v-card>
  <v-avatar
    size="50%"
  >
  <img src="画像データ">
  </v-avatar>
</v-card>
```

`text-xs-center` や `justify-center` をavatarや画像につけたり
`maring: 0 auto;`をしてみても中心に持ってこれない


# 解決策

`<v-layout>` で `justify-center` を使うと画像を中心に持ってくることができる

```vuejs
<v-card>
  <v-layout justify-center>
   <v-avatar
    size="50%
   >
    <img src="画像データ">
   </v-avatar>
  </v-layout>
</v-card>
```
ansibleのelb_target_group_factsの検索は全一致になるらしい(というか boto3 elbv2のdescribe_load_balancersが全一致)



## TL;DR

- `elbv2`のdescribe_load_balancersは存在しないELBを検索しようとすると`LoadBalancerNotFoundException`
- 検索したいload balancer nameを1つずつfor文で回すしかない

## 経緯

AWSのALBの情報を取得するansibleを書いていたのですが、`elbv2`の`describe_load_balancers`の仕様にはまったのでメモ。

## 問題点


ansibleのALBの情報取得をする`elb_application_lb_facts`で以下のように書いたのですが、

```yml
- elb_application_lb_facts:
    aws_access_key: hoge
    aws_secret_key: fuga
    region: ap-northeast-1
    names:
      - "alb-blue"
      - "alb-green"
  register: alb_result
```

load balancerの情報を取得できない。。

```
"load_balancers": []
```
実際のlibraryを確認してみると、`LoadBalancerNotFound`が発生した場合は空で返すとのこと。
つまり検索候補のうち、片方が存在しない名前のLoad Balancerの場合、エラーを吐くらしい。きつい。
https://github.com/ansible/ansible/blob/stable-2.7/lib/ansible/modules/cloud/amazon/elb_application_lb_facts.py#L222

一応自分でpythonで以下のように試してみたのですが、

```python
import boto3

access_key = 'hoge'
secret_key = 'fuga'
client = boto3.client(
    'elbv2', 
    region_name='ap-northeast-1',
    aws_access_key_id = access_key,
    aws_secret_access_key = secret_key
)
response = client.describe_load_balancers(
    Names=[
        'alb-blue',
        'alb-green'
    ]
)
print(response)

```

やっぱり`LoadBalancerNotFoundException`が出てしまう。避けられない仕様らしい。

```
botocore.errorfactory.LoadBalancerNotFoundException: An error occurred (LoadBalancerNotFound) when calling the DescribeLoadBalancers operation
```

結局以下のように無理やりloopにして対応しました。

```yml
- set_fact: 
    alb_list: []

- elb_application_lb_facts:
    aws_access_key: hoge
    aws_secret_key: fuga
    region: ap-northeast-1
    names:
      - "{{ item }}"
  register: alb_result
  with_items:
    - "alb-blue"
    - "alb-green"
 
- set_fact:
    alb_list: "{{ alb_list }} + {{ item['load_balancers'] }}"
  when: item['load_balancers'] | length > 0
  with_items: "{{ alb_result['results'] }}"
```

## 結論

`elbv2`のdescribe_load_balancersは全一致しか許さない、という鬼仕様でした。
今回はansibleのyml側で制御する方法を取ったのですが、
`elb_application_lb_facts`を多用するのであれば、custom moduleを作成して、
python内部でfor文を回した方が保守性が良くなりそうです。
sounddeviceでPythonを使って録音する

音響測定でDAWで録音→書き出し→Pythonで分析の流れが非常に面倒だったので、なんとかワークフローを自動化できないかなと思っていたところ、[sounddevice](https://python-sounddevice.readthedocs.io/en/0.3.12/ "sounddevice")という再生、録音をPython上で簡単に行えるモジュールを見つけたので、メモしておきます。

# インストール
anacondaを使っている場合

```
conda install -c conda-forge python-sounddevice
```
pipの場合

```
python3 -m pip install sounddevice --user
```
でインストールできます。

# 使い方

まずはじめにインポートします。

```python
import sounddevice as sd
```

## デバイス設定
ターミナルから以下のコマンドを打つと、使えるデバイスの一覧が出てきます。

```
python3 -m sounddevice
 >>>
  0 Scarlett 2i2 USB, Core Audio (2 in, 2 out)
  1 MacBook Proのマイク, Core Audio (1 in, 0 out)
  2 MacBook Proのスピーカー, Core Audio (0 in, 2 out)
```
Pythonのスクリプト上で、 ```sounddevice.default.device```にデバイス番号をアサインすると使うデバイスを設定することができます。

```python
import sounddevice as sd

sd.default.device = 0 #Scarlet 2i2の入出力を使う
# sd.default.device = [in, out]のように、入出力で別々にアサインすることも可能
例：sd.default.device = [1, 2]
```


## 再生
例えば440Hzの正弦波を3秒再生したい場合、 ```sounddevice.play()```を使うことで行なえます。

```python
import numpy as np
import sounddevice as sd

fs = 48000 #サンプリング周波数
f0 = 440 #周波数
duration = 3 #再生時間

t = np.linspace(0, duration, duration * fs, endpoint=False)
x = np.sin(2*np.pi*f0*t)

sd.play(x, fs)
sd.wait()
#sd.stop()で再生停止もできます
```

## 録音

録音は```sounddevice.rec()```で行えます。録音している間に他の処理を行いたい場合は、```sounddevice.rec()```の下に処理をかけば良いですが、そうではなくて、録音が終わってから処理を行いたい場合は```sounddevice.wait()```を使って次の処理に進ませないようにする必要があります。

```python
import sounddevice as sd

fs = 48000

duration = 5  # seconds
myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=1)
sd.wait() # 

'''
何らかの処理
'''
```

## 再生と同時に録音
これは個人的に一番使うことになると思うのですが、再生と同時に録音も行いたい場合は```sounddevice.playrec()```を使います。
例えばスピーカに先程の正弦波を入力して、スピーカからの出力をマイクで録音する処理は場合は以下のコードで行えます。

```python
import numpy as np
import sounddevice as sd

fs = 48000 #サンプリング周波数
f0 = 440 #周波数
duration = 3 #再生時間

t = np.linspace(0, duration, duration * fs, endpoint=False)
x = np.sin(2*np.pi*f0*t)

recording = sd.playrec(x, fs)
sd.wait()
```

# 注意点
きちんと同期がとれるかはまだ未確認なので利用時は自己責任でお願いします。
また確認次第追記します。

# 参考
https://python-sounddevice.readthedocs.io/en/0.3.12/index.html
CentOS7で定期的にリブートする方法

# 1.rebootシェルを作成

```reboot.sh
sudo shutdown -r now
```
# 2.cronを起動

```
crontab -e
```

# 3.cronを設定
任意の日時にリブートシェルを実行

```
* * * * * [実行コマンド]
```

# 4.起動確認
- 以下のコマンドでcronが起動した日時がわかる

```
cat /var/log/cron
```

- 以下のコマンドで再起動した日時がわかる

```
last reboot
```
新しいWindows PCをセットアップするたびに調べてしまうこと

新しいパソコンをセットアップするたびに調べてしまうことをまとめました。
個人的なメモとして書いていますので、くだらない記事を読んだと怒らないようお願いします。

#Acrobat Readerでサイドバーを出さないようにする
https://helpx.adobe.com/jp/acrobat/kb/disable-right-hand-pane-in-acrobat-reader.html

#CortanaのWeb検索を無効にする
https://www.softantenna.com/wp/tips/windows-10-disable-web-search/

#NTPサーバーを設定する(Windows10)
time.windows.comはネットワーク的に遠いし、よくエラーになるので変えたほうが良い
https://win.just4fun.biz/?Windows10/NTP%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E5%A4%89%E6%9B%B4%E6%89%8B%E9%A0%86

#既定のIMEを変更する(Windows10)
https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=5910-8527

#不要なサービス(Windows10)
https://ygkb.jp/4475

#スタートメニューのスタートアップの位置(Windows10)
shell:startup

#ログイン画面のTipsみたいなのを消す(Windows10)
https://news.mynavi.jp/article/win10tips-194/

#高速スタートアップを無効化する(Windows10)
https://121ware.com/qasearch/1007/app/servlet/qadoc?QID=018214
Swift：ランダムな色を取得

お手軽にランダムな色を取得するためのExtension

コメントを受けて修正しました

```swift:
extension UIColor {
    static var randomColor: UIColor {
        let r = CGFloat.random(in: 0 ... 255) / 255.0
        let g = CGFloat.random(in: 0 ... 255) / 255.0
        let b = CGFloat.random(in: 0 ... 255) / 255.0
        return UIColor(red: r, green: g, blue: b, alpha: 1.0)
    }
}
```
JSONファイルの変更を監視して差分を表示するシェルスクリプト

JSONファイルの変更を監視して、変更が発生したら差分を表示する簡単なシェルスクリプトを書いた。
データをJSONファイルに保存する処理の開発・デバッグに使うと良いです。

ファイルの日付を見て変更を監視し、node.jsで引数のjsonを出力形式を整えてdiffに渡している。
外部モジュールのインストール不要なのがメリット。

macOS High Sierraとmojaveで動作確認したがnode.jsとshellが動けば動くと思われる。
なお、引数のファイルパスは拡張子を.json(大文字でもOK)にする必要があります。

参考：
- https://qiita.com/tamanobi/items/74b62e25506af394eae5
- https://fumiyas.github.io/2013/12/06/tempfile.sh-advent-calendar.html
- https://qiita.com/hirobe/items/c7845fd3b6f9177e604f


``` watchjson.sh
#!/bin/sh

if [ $# -ne 1 ]; then
    echo "Usage:"
    echo "./watchjson.sh filepath.json"
    exit 1
fi
INTERVAL=1 # sec
last=`ls -l -T "$1" | awk '{print $8}'`
tmpfile=`mktemp`.json
cp "$1" $tmpfile

atexit() {
  [[ -n ${tmpfile-} ]] && rm "$tmpfile"
}
trap atexit EXIT
trap 'rc=$?; trap - EXIT; atexit; exit $?' INT PIPE TERM

while true; do
    sleep $INTERVAL
    current=`ls -l -T "$1" | awk '{print $8}'`
    if [ $last != $current  ] ; then
        echo ""
        echo "updated: $current"
        last=$current
        node -e "console.log(JSON.stringify(require('$tmpfile'),null,2))" | (node -e "console.log(JSON.stringify(require('$1'),null,2))" | diff /dev/fd/3 -) 3<&0 
        cp "$1" $tmpfile
    fi
done
```

##　使い方

```shell-session
$ ./watchjson.sh jsonのパス
```

出力例：

```
updated: 12:05:01
166c166
<       "schedule": "",
---
>       "schedule": "スケジュール",

updated: 12:05:04
179c179
<       "items": "",
---
>       "items": "アイテム",
```

# おまけ
上記シェルスクリプトはjsonファイル専用ですが、ちょっと変更するとjson以外のテキストファイルの差分監視ができます。
こんな感じ

``` watchdiff.sh
#!/bin/sh

if [ $# -ne 1 ]; then
    echo "Usage:"
    echo "./watchdiff.sh filepath"
    exit 1
fi
INTERVAL=1 # sec
last=`ls -l -T "$1" | awk '{print $8}'`
tmpfile=`mktemp`
cp "$1" $tmpfile

atexit() {
  [[ -n ${tmpfile-} ]] && rm "$tmpfile"
}
trap atexit EXIT
trap 'rc=$?; trap - EXIT; atexit; exit $?' INT PIPE TERM

while true; do
    sleep $INTERVAL
    current=`ls -l -T "$1" | awk '{print $8}'`
    if [ $last != $current  ] ; then
        echo ""
        echo "updated: $current"
        last=$current
        diff $tmpfile $1
        cp "$1" $tmpfile
    fi
done
```
Webサイトの状況を確認するツール②　～aguse.jp～

Webサイトを開発・運用していくうえで、避けては通れないのがパフォーマンス。計測ツールも多々あるので、ニーズに合わせて最適なものを使っていきたい。

先日の「アプリケーション・パフォーマンス 2018」のイベントに参加をした際に、いくつか紹介をしてもらったので、備忘録を兼ねて。

# aguse.jp
**Webアプリケーション**
[aguse.jp](https://www.aguse.jp/)
↑にて確認が可能

![as1.PNG](https://qiita-image-store.s3.amazonaws.com/0/269801/07ef2f91-6c54-b512-eea0-5cec00c33c57.png)

再び、私の大好きなサイト「amazon」で試してみました。
[Lighthouse](https://qiita.com/shingo_76/items/f7f7ff3125eaef6f7f6e)とは違って、サイトの基本状態を確認するものの様です。
※改善点等の指摘はなく、サイトがどのような構造になっているかを簡潔に表現してくれます。

表示される項目は以下の様な感じになります。

## #サイト概要
![as3.PNG](https://qiita-image-store.s3.amazonaws.com/0/269801/953e5872-3c8b-e446-cca7-dce94c9eaecf.png)
サイトのURLやTitle,IPアドレス、METAタグの情報といった感じです。
「検出されたマルウェア」という項目もあり、amazonではタイムアウトしていますが、この項目は
>カスペルスキーによるマルウェア検査が行われ、検出された場合にはマルウェアの名前が表示されます。発見されたマルウェアについての詳細情報へのリンクも表示されます。
といった内容の様です。
※いくつか試しましたが、表示されるサイトを見つけられませんでした。（怪しいサイトは、基本的に踏みませんので・・・）

## #外部と接続するオブジェクト
![as4.PNG](https://qiita-image-store.s3.amazonaws.com/0/269801/3e2e7c09-365a-96fc-7def-fe0bfed50629.png)
意味合いとしては、以下の様な感じです。
>ページ内に含まれる外部サーバのコンテンツ、リンク先、フォーム送信先を一覧表示し、それぞれマルウェアの検査とサーバ設置国表示を行います。表示対象カテゴリは<iframe>,<frame>,<javascript>,<a>(通常のリンク),<form>です。を押すとスクリーンショット上での位置を確認できます。

昨今、自社内（サイト内）で全てを完結するのはコストも掛かるので、良いものは先人（他サイト）のものを使わせてもらったりもします。
そのうち、何を使っているのかが分からなくなるのも実情。
こういった欄があると少しは管理しやすくなるのかな。

## #ブラックリスト判定結果
![as5.PNG](https://qiita-image-store.s3.amazonaws.com/0/269801/6608d291-87d2-1203-dc2e-32a6afb18475.png)
意味合いとしては、以下の様な感じです。
>調査したサイトが他の各ブラックリストに要注意サイトとして登録されているかどうかを表示します。
正直、「こんなものがあったんだ」という驚きです。ブラックリストの機能自体はあってしかるべきだとは思っていましたが、その状況を確認できるのは嬉しいです。
愛をこめている自分のサイトで「○SAFE」以外が出ることの無いよう、しっかりと運用していきます。

# まとめ
[Lighthouse](https://qiita.com/shingo_76/items/f7f7ff3125eaef6f7f6e)とは用途も異なり、別の視点からサイトを確認できるツールとなります。
特に、外部からどう見られているのか、という点での確認ができますので、定期的に確認をすることで早めの対処に繋げることができるのかなと思います。
C++ Builder XE4 > モジュール'XXX.exe'のアドレスXXXでアドレスYYYに対する書込み違反が発生しました。 > 「自動生成フォーム」を「使用可能フォーム」にした上でそのフォームを使うことで発生する

```txt:動作環境
C++ Builder XE4
```

> モジュール'XXX.exe'のアドレスXXXでアドレスYYYに対する書込み違反が発生しました。

となる再現方法。

### 再現方法

1. プロジェクト > オプション > 「自動生成フォーム」内のフォームを「使用可能フォーム」へ移動
2. ソフト内にそのフォームの処理を呼出す


### 補足

「自動生成フォーム」から「使用可能フォーム」にすることでそのフォームの機能を廃止しようとした。
別の部分でそのフォームの処理を呼出す部分が残っており、上記のエラーが出るようになっていた。

対処としては、「きちんと機能を取除く」こと。
IdeaVimで矩形選択(multiple cursors)

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">IdeaVim 0.50 is here. Multiple cursors support and vim-multiple-cursors emulation (enable it in ~/.ideavimrc). Lots of fixes for focus issues, &lt;Esc&gt; handling, navigation in Run/Debug tool windows. See the changelog for more details about multiple cursors  <a href="https://t.co/1zVGFXxU40">https://t.co/1zVGFXxU40</a></p>&mdash; IdeaVim (@ideavim) <a href="https://twitter.com/ideavim/status/1052904607960195072?ref_src=twsrc%5Etfw">October 18, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


[IdeaVim](https://github.com/JetBrains/ideavim)のバージョン[0.50](https://github.com/JetBrains/ideavim/tree/0.50)から[`vim-multiple-cursors`](https://github.com/terryma/vim-multiple-cursors)と同等の機能が使えるようになったが、macOSで使用するにあたってはキーのリマップが必要だったので、その設定メモ。

##### 手順

1. `IdeaVim`プラグインのアップデート
2. `~/.ideavimrc`の作成 (必要であれば)
3. 上記ファイルに下記を追加し、IDE内で`:source ~/.ideavimrc`して設定を反映する

```
set multiple-cursors
map <C-N>  <A-N>
map <C-P>  <A-P>
map <C-X>  <A-X>
map g<C-N> g<A-N>
```

---

**`Command + N`で同じワードを複数選択した例**
[![Screenshot from Gyazo](https://gyazo.com/c16ad375cbf2e28e330621dacc9ebc69/raw)](https://gyazo.com/c16ad375cbf2e28e330621dacc9ebc69)

##### 参考

- [Multiple-cursor key commands give unexpected results on macOS](https://youtrack.jetbrains.com/issue/VIM-1531)
初めまして、詳細設計

##目的
現場で詳細設計を作成する機会が増えた為、「詳細設計の役割って何？」「分かりやすい詳細設計書の書き方は？」ということをまとめて、自分の理解を深めると共に、研修を終えて現場に出たエンジニアの方に少しでも詳細設計についての知識を共有できればと思い投稿しました。

##詳細設計とは
システム開発の上流工程は
「要件定義」→「基本設計」→「詳細設計」の流れに従って進められていきます。

その中で詳細設計は
「基本設計で決められた動きをどうやって実現するかを決める」
役割を担っています。

要するに前工程である「要件定義」「基本設計」までで決められたシステムの実現の為に「どう実装するか」というところまで落とし込む工程と言えます。

故に、詳細設計を見る人間はお客様ではなくプログラマーであり、「分かりやすい詳細設計」＝「実装しやすい設計書」とも考えられます。

##分かりやすい詳細設計の作成方法

ポイントは
・認識のズレがないように
・求められている機能を実現
できる設計書を作ることだと思っています。

よくあるプログラミングバグで、受け取る値を間違えたり、値の送り先を間違えたりといった、プログラミングの知識以外のところでつまづくことがあります。

どんなエンジニアが見ても
「何」を「どうする？」
ということが分かるような設計書を作ることが大切です。

##じゃあ具体的に何を注意するのよ？

はい、ここからが本題です。
詳細設計はエンジニアがプログラミングしやすいように作成することが大切なんだなーと何となく分かったところで、じゃあ具体的に何をすれば良いのか分からないですよね。

ここからはぼくが実際に現場に出て意識した方がいい事、大切だと思った事をまとめていきます。


###当該文書の作成目的を文頭に宣言する

プログラマーが実装する際に参照する資料を探す時間を短くするため

（例）「本書では◯◯機能の仕様について記載する」のように目的を明確化する。

###簡潔な文章を

長々とした文章は分かりにくくなりがち。なるべく短い文章で分かりやすく表現することで認識のズレを回避する。

（例）文章は30字から40字程度に収まるように表現する。

###図の使用

プログラムの動きなど、文章のみでは理解しづらいものはフロー図を作成したり視覚的に理解できるような設計だと親切。

（例）エクセルであればフロー図を記載してあるシートを作成する。

###表の使用

条件分岐などは表を使うことでより分かりやすくなる。

（例）「分岐については以下を参照。」と記載して表を作成する。

###用語の統一

同じ機能、同じ概念は、一言一句同じ用語を使う。同じことを別の用語で記載すると認識のズレに繋がる。

（例）過去案件の設計書から用語を拾う。用語がまとめた資料を作成する。

###造語をしない

プロジェクト内で共通の概念であれば、既に使われている表現を使う。
当該文書内に閉じた概念で、自分で作り出した用語であれば、その定義の項を作り、明確に記載する。

（例）
〇〇〇〇〇（注1）

文末に
（注1）造語の説明を記載
等

###コピペを上手く使う

表記ミスをなくすためにキーボードでの手打ちをなるべくしない。

（例）
設計書にＤＢのテーブル名を記載するときは論理設計書からコピペする。

###レビューを受ける

設計書が完成したらチームリーダー等、第三者にレビューを受ける。
他人から見て「どういうこと？」と思われる箇所の指摘をしてもらうとなお良し。

##まとめ

実際に現場に出ると、プログラミングの知識不足によるミスや時間ロスと同じくらい設計書を読み解くのに時間がかかることがあります。知識は勉強したり仕事をしていくうちに覚えていけばいいことですが、それ以外のところで掛かる時間を減らせるような詳細設計書を作成する意識が大切だと思う今日この頃でありました。
FAQ集をWatson 使ってどのように活用できるか試行錯誤

とある製品のFAQ作りに長年携わってきた。これをもとにWatson を使って「何か質問したら、いい感じの答えを返してくれる」ようにするにはどうしたらいいのだろう、と悩んだ。

結果的に、来た質問の種類を分類するのに使えば一番シンプルだな、という結論に落ち着いた。そこにいたるまでの悩みをまとめたメモ。
もちろん今時点では私はこのように考えた、というだけなので、これからまた考え方を変えていくかもしれない。私の使い方が慣れていないだけなのかもしれないし。

# Watson Assistant
チャットボットが作れるサービスと聞いて、FAQをチャットボットに答えさせればいいんじゃない？というアイデアが浮かぶも、私にとっては分かりづらい・使いづらい概念が「インテンツ」だった。

インテンツは「質問の意図」なんだそうだけれど、FAQは一つの質問に対して、一つまたは複数の答えを書いている。でもWatson Assistant のインテンツの説明を見ると、どうやら一つの答えに対して複数の質問が対応するような書き方をしている。言い回しが違っていたり、類義語が使われていたり、違う切り口で聞いていたり。

私が関係しているFAQは、似たような答えになる複数の質問を用意しているわけではなかった。（例外はある）
例外的に似たような答えに落ち着く複数の質問だけ１つのインテンツにまとめて、その他のFAQ一つごとにインテンツが一つ必要なのじゃないだろうかと悩む羽目になった。

もうひとつの「エンティティ」という概念は、Watson Assistant の定義画面見ると、実質的には同義語（あるいは似たような意味を表す句）をリスト化したものなのだろうなと思った。これは分かりやすいが、「インテンツ」と「エンティティ」の組み合わせで回答が決まる、ってどういうこと、と悩んだ。

FAQの一つの質問に対して、答えが複数ある場合に分岐条件として「エンティティ」を使うものなのだろうか？

# Watson Discovery
PDF、HTML、WORD文書などを取り込んでくれて、質問をすると順位付けされた複数の回答を返すもの、と紹介資料には書いてあったりする。たしかに製品マニュアルなどを Uploadしたら何かしら取り込んでいるように見える。

しかし質問欄に単語だけであったり、質問文などの文章を入力してみた結果としては、これは質問文に含まれる単語を元に、その単語が含まれる場所を返してくれる検索システムなんじゃないかという気がした。 Watson Explorer というテキストマイニングするためのソフトウェアの Foundational Components (主に文書検索を行う部分)を使っているような感覚。Watson Discovery の紹介資料のような夢の世界からはだいぶ遠い。

私のデータの与え方が間違っていて、もっと工夫が必要なのかもしれない。事前に文書の中身を目的別に分類しておいてから、それぞれ別の「クラス」として与えるとか？ 

# Natural Language Classifier 
結論から言うとこれが私には一番分かりやすい。今まで関わってきた FAQ 集は、質問のカテゴリー別に分類していた。その質問文と所属するカテゴリーのペアを CSV で Natural Language Classifier (NLC) に与えて学習させた。

学習が終わったところで質問文を微妙に変えて NLC を呼び出すと、おおむね意図通りの分類をしてくれる。意図したのと違う分類結果を返してくる場合ももちろんあるが、それによって実は自分の先入観というか思い込みで分類が間違っている（というか「ゆがんでいた」）ことに気づく、という効果もあった。

NLC には UI が無いので、NLC を呼び出して結果を受け取ってなんらかの表示をするには、Node-RED で表示部分を作ってあげる必要がある。

# そして再び Watson Assistant へ
でも UI が必要なら、実は Watson Assistant が内部で NLC を呼び出しているので、Watson Assistant を UI 代わりに使うという方法があることに気づいた。

簡単な使い方としては既存のFAQ集のどのページを見れば目的の質問と回答があるのか分からない人に対して「質問のカテゴリーはXXですね、ではこちらのページをご覧ください」と、案内すればよいのではないだろうか。

# 気づき
ここで気づいた。実は私の関わってきたFAQ の「インテンツ」とは、FAQ 集の「質問のカテゴリー」だったのではないかと。

チャットボット「が質問に答える」ことが本当にしたいことでは無くて「目的の答えに早くたどり着けるように」チャットボット「に手助けさせる」ことが実は必要なのだ。

# 今後の課題、言い換えると次に目標
というわけで遠回りではあったが Watson Assistant で質問のカテゴリーを判定して、それをもとに「ここに目的の質問の答え載ってますよ」と案内すれば良いよね、と気づいた。しかし、質問の内容によっては、さらにヒアリングしないと答えが決まらないようなものがある。

いまは、FAQ集に １）２）３）のように複数の答えを書いていて、その文章を順次見ていって自分自身で判断して頂く必要がある。その判断部分もガイドできるようになるとすばらしい。それをどう実現するのか、今後の課題だ。
CentOSの日付設定でつまづいた話

普通にNTPサーバーにアクセスして合わせたいのですが、弊社都合で他社のNTPサーバーにアクセスできないので手動で設定する事に。
VPNサーバー周りのせいです。

まぁ手動であわせればいいやということで下記コマンドを実行

```
$ date --set='2018/11/05 11:35:00'
date: cannot set date: Operation not permitted        
Mon Nov  5 11:35:00 UTC 2018                          
```

なんじゃこりゃ。sudo つけてもダメでした。
Dockerの権限エラーらしい。[参考](https://qiita.com/fulcrum/items/6477fd192bb48bac8089)

imageから作り直しが必要らしい。辛い。他の方法を考えていたら、CentOS7には `chorony` という便利なコマンドがあるらしい [参考](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-using_chrony)

こちらを使って解決。
SwiftでMarkdownを表示する

# Markdownとは

Qiitaの記事を書くときやGithubでREADME.mdを書くときに使う機会があると思います。

今回はそのMarkdownをSwiftで表示するライブラリを紹介します。

# MarkdownView

ライブラリのリポジトリは[こちら](https://github.com/keitaoouchi/MarkdownView)

CocoapodsとCarthageで導入出来ます。

## CocoaPods

### 1.init

```
$ pod init
```

### 2.Podfileに記載

```
pod "MarkdownView"
```

### 3.インストール

```
pod install
```

## Carthage

### 1.Cartfileを作成

```
$ touch Cartfile
```

### 2.Cartfileを編集

```
$ vim Cartfile
```

### 3.Cartfileに記載

```
github "keitaoouchi/MarkdownView"
```

### 4.ライブラリをビルド

少し時間が掛かります

```
$ carthage update --platform iOS
```

### 5.Linked Frameworks and Librariesに追加

Linked Frameworks and LibrariesにSkeletonView.frameworkを追加します

### 6.RunScriptに記載

```
/usr/local/bin/carthage copy-frameworks
```

Import Filesに記載

```
$(SRCROOT)/Carthage/Build/iOS/MarkdownView.framework
```

# 使い方

```swift
import UIKit
import MarkdownView

class ViewController: UIViewController {

    private let mdView = MarkdownView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        mdView.frame = view.bounds
        mdView.load(markdown: "# Markdown")
        view.addSubview(mdView)
    }
}
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/165815/7221ab21-182a-5374-a2f5-24bd4263ce63.png)


たったこれだけでMarkdownを表示することが出来ます。

QiitaのAPIなどで記事をMarkdownで取得することが出来ますので、そういった機会に活用できると思います(^_^)

Markdown内のURLをタップするとsafariを開く、のような動作もできるようですので詳しくは[こちら](https://github.com/keitaoouchi/MarkdownView#options)を御覧ください
gitの差分を見やすくする

## はじめに

今年もアドベントカレンダーはじまりました！
この記事は[Hamee Advent Calendar 2018](http://qiita.com/advent-calendar/2018/hamee)の1日目の記事です。
[Hamee](http://hamee.co.jp/)のエンジニア(一部デザイナー)が自分の興味あるテーマについて書いていきます。
毎年一緒に参加して盛り上げてくれる皆さんに感謝です :clap: 

## 本題

さて本題ですが、常々思っていたんですがgitの差分を表示する時に「違う、そうじゃない」ってなることが多々あり、何とかしたいと思ったので調べました

### サンプルコード

言語はなんでもいいんですがとりあえず`PHP`にしておきます。
例えば以下のコードがあったとしましょう。

```php
<?php
class Test{
    public function hoge(){
        return 'hoge';
    }

    public function moge(){
        return 'moge';
    }
}
```

この状態でコミット。
次に以下のように修正したとしましょう。

```php
<?php
class Test{
    public function test(){
        return 'test';
    }

    public function hoge(){
        return 'hoge';
    }
}
```

* やったこと
    * mogeメソッドの削除
    * testメソッドの追加

これを`git diff`で見ると以下のようになります

```diff
 class Test{
-    public function hoge(){
-        return 'hoge';
+    public function test(){
+        return 'test';
     }

-    public function moge(){
-        return 'moge';
+    public function hoge(){
+        return 'hoge';
     }
 }
```

* この差分表示を見ると
    * hogeメソッドをtestメソッドに変更
    * mogeメソッドをhogeメソッドに変更

っていうように読み取れる

## 違う、そうじゃない

hogeメソッドは一切触っていないのにさも修正があったように見えて、開発者本人ならともかく第三者が見たら混乱するでしょう。
こんな時にぴったりのオプションがあります

`git diff --histogram` or `git diff --patience`

このオプションを使って差分を表示すると以下のようになります

```diff
 class Test{
+    public function test(){
+        return 'test';
+    }
+
     public function hoge(){
         return 'hoge';
     }
-
-    public function moge(){
-        return 'moge';
-    }
 }
```

この差分であればtestメソッドを追加、mogeメソッドを削除、hogeメソッドに関しては差分なし、というのがはっきり分かります:smile:

## まとめ

差分を検知するアルゴリズムを指定することでより人間に分かりやすい表示となります。
`git diff --histogram` と `git diff --patience`の違いは正直良く分かっていません（詳しい方補足お願いします）
アルゴリズムの詳しい挙動も良く分かっていないので場合によっては意図しない差分表示になるかもしれません。
この辺はもう少し勉強してみます。
惜しむべきは弊社でプルリクとかのやりとりに使っている`bitbucket`では対応していないということでしょうか…
プルリクもdiffのアルゴリズムを指定できるようになると更に捗りそうだなーと思っています。
Atlassianさんご検討よろしくお願いしますｗ


## 参考

Git - git-diff Documentation
https://git-scm.com/docs/git-diff

## おわりに

アドカレ4年目です。
Qiitaではゴミ記事問題などありましたが、知識をアウトプットしていくことはとても大事なことなのでこの文化だけはなくなってはいけないと思っています。
Qiitaでなくても良いし技術ブログでなくてもいい、とにかくアウトプットした方が絶対に成長できます。
皆さんも積極的にアウトプットしていきましょう！
ではこの後も[Hamee](https://qiita.com/advent-calendar/2018/hamee)のアドカレをお楽しみに！
vue.js, nuxt.jsでtableを使った時の謎のエラーの対処法

# シンプルなtableを作成するとエラーになる

```html
<table border="1">
  <tr>
    <th>果物</th><th>味</th>
  </tr>
  <tr>
    <td>イチゴ</td><td>甘い</td>
  </tr>
  <tr>
    <td>レモン</td><td>酸っぱい</td>
  </tr>
</table>
```

上記のようなtableを作成すると下記のようなエラーが複数でる

## error

```
vue.runtime.esm.js:587 [Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.
```

## warning
```
Mismatching childNodes vs. VNodes:  NodeList [tbody] (3) [VNode, VNode, VNode]
```

```
Parent ...
```

# 解決策
解決策はシンプル。tbodyを追加する

```html
<table border="1">
  <tbody>
    <tr>
      <th>果物</th><th>味</th>
    </tr>
    <tr>
      <td>イチゴ</td><td>甘い</td>
    </tr>
    <tr>
      <td>レモン</td><td>酸っぱい</td>
    </tr>
  </tbody>
</table>
```
gRPCの概要だけ

gRPCを扱う事になったので概要だけ書く。概要の概要の概要です

# gRPCとは?
Googleが開発したRPC(Remote Procedure Call)プロトコル。
ProtocolBuffersを使用し高速な通信が実現できる。

## Protocol Buffer
プロトコルバッファーは構造化されたデータをシリアライズするための技術。
言語やプラットフォームに依存しないせず、.xmlよりシンプルで小さく高速なのが特徴。データを構造化する方法を定義してから生成されたソースコードを使用し、
様々なデータストリームとさまざまな言語(Go, PHP, Java, Ruby, Python)を使用して構造化データを簡単にRead/Writeすることができる。

## 詳細
gRPCではIDL（Interface Definition Language）を使ってあらかじめAPI仕様を`.proto`ファイルとして定義し、
サーバー側＆クライアント側に必要なソースコードの雛形を生成する。言語に依存しないIDLで先にインタフェースを定義することで色々なプログラミング言語の実装を生成できるというメリットがある。

マイクロサービス間の通信手段として使用する場面が多い。シリアライズされたデータはバイナリ形式でやり取りされるため高速に動作する。

## gRPCの始め方
- protocol buffer compilerをインストールする
- `.proto`を用意する (自動生成ライブラリを使うのとよい)
- `.proto`からサーバー側で実装する言語(Goとか)のインターフェースを作成する
- ↑で作成したインターフェースにそって具体的な処理を実装する

## ローカル環境で動作する場合、gRPCのcompiler&clientが必要

```
# Golangの場合
$ go get -u google.golang.org/grpc
```
styledComponentを使ってみた

## styledComponentの活用メモ
```js
//hocみたいに使う時 {css} がいる
import styled, { css } from "styled-components";

//props.active active={this.displayingDashboard()}ここの条件が実行されたら${props=>}が走る
const ControlButton = styled.div`
  color: red;
  ${props =>
    props.active &&
    css`
      text-shadow: 0px 0px 60px #03ff03;
      colore: blue;
    `};
`;

class App extends Component {
  state = {
    page: "dashboard"
  };

  //stateのpageがdashboardであれば[ControlButton]が実行される
  displayingDashboard = () => this.state.page === "dashboard";

  render() {
    return (
      <AppLayout>
        <Bar>
          <Logo>CryptoDash</Logo>
          <div />
          //activeで関数が実行↑
          <ControlButton active={this.displayingDashboard()}>
            Dashboard
      //抜粋
```
なんか人のコードをみて触っていた時に、verが変わったタイミングだったのかさだかではないが、「あれ、これいけへんやん」って思った時に公式サイトみたら書いてたのでメモ

## 個人的メモ
styledComponentめっちゃ便利ですが、やはり何をするにしても公式サイトみないとですね、、、、、
はい、実力不足です、、見るようにしましょう。自ら反省して戒めのようにここに書きたいと思います。
Reactではじめてtypescriptを使ってみた時ハマったことのメモ

## typescriptの型
正直型というものがなくてもReact出かけちゃう感じだったが今回とあるプロジェクトでtypescriptを触る機会があったので
軽く学んだことと、いつもエディターにメモして保存しちゃうこととかをこちらでメモ


## interfaceの個人的感覚メモ
```js
//ここで名前をStateにして
interface State {
  name: string
  id?: string
}
//ここで宣言してる
export class InvitationSendFrom extends React.Component<{}, State> {
  public state = {
    name: '',
    id: undefined,
  }
```

がその際に単純に疑問に感じたこと
- Stateって名前であっているのか
- 他の名前でもいいの？

## 命名についてのメモ
Stateっていう名前はかぶっちゃうので、衝突するリスクはあるから
インターフェース作るときは、コンポーネント名の名前にする方がベストらしい

## typescriptでのinputのevent
event多くないなら
jsxに書いちゃうのもあり（もちプロジェクトによる）

```js
onChange={(event: React.SyntheticEvent<HTMLInputElement>) =>
  this.setState({ name: event.currentTarget.value })
}
```

## currentTagetについて
最初書いていたのは,name属性をstateと紐づけてsetStateするやり方だったが
聞いたら`currentTaget`でもいけると聞いて使ってみたメモ

```js

onChange={(event: React.SyntheticEvent<HTMLInputElement>) =>
  this.setState({ name: event.currentTarget.value })
}
```

## typescriptの感想
軽くReactで触る前でドットインストールでみてたけど、propsやらstateやらで型をつけたりする流れがなかなか慣れない
（単純に私のスキル不足なので自覚してますのでスルーで）

とはいえ、人が書いたコードをみたときにtypescriptで型があるおかげで、「どこ」で「なにを」しているとかはちょっと追いやすくなった印象はありました。
もう少し触って慣れたいと思います