OmniAICreator/Qiita-1.07M huggingface dataset:
本日は迷惑アクセスに対抗する簡易的な方法を伝授します！

インターネット上に公開サーバを持って驚くのは、正規利用者以外の迷惑アクセスが結構大量に来ることだと思います。

個人で Web サービスを運営していますが、サイト運営初心者の頃に度重なる用途外アクセスでサーバを落とされた経験があり、昨今の「初心者の学習用にスクレイピングを薦めるブーム」に憤っています！

で、今日は簡易的ではありますが、そういったおかしなアクセスに対してクレームをあげる為の方法を伝授しますw

# 前準備
前準備として、クレームに必要なアクセスログを取ってください。
クレームの上げ先/抗議内容の確認に必須なので整理します。

一般的にクレームは、以下のようなものになるかと思います。
・アクセス頻度がおかしい
・アクセス内容（利用規約違反等）がおかしい
アクセス時間/IP アドレス/アクセス内容をまとめてください。

# プロバイダの割り出し
仕組みを知らない人は少し意外に思うかもしれませんが、クレームは「アクセス元の IP  アドレスを払い出したプロバイダ」にあげるとアクセスしてきた人に伝わります。

前準備で確認した IP アドレスからプロバイダを確認するのですが whois 情報で調査することが可能です。
レジストリからたどるのが正確で正解ですが、ip ひろば等のサービスを利用しても良いです。
担当者情報として、e-mail があります。
３つほど記述があり、本来は使い分けるべきですが、今回はクレームなのでどれでも良いです。
＊念の為、組織情報にあるプロバイダも確認しておくと良いです。e-mail でうまくつながらなかった場合はお問い合わせフォームから突撃です。

# クレームをあげる
前準備で用意したアクセス時間/IP アドレス/アクセス内容をもとに、クレーム内容を記述し、該当プロバイダに対して抗議します。
抗議はざっくり以下のような記述で良いかと
「貴社の管理する {ipアドレス} より、{クレーム理由} なアクセスを受け弊社の提供するサービスに影響が出ております。アクセスログからの抜粋をあわせて添付しますが、節度あるアクセスをするようにご伝達をお願いいたします。」
＊時間とアドレスを組み合わせることで、プロバイダではアクセス者を特定できるので、この2つが分かる資料で連絡してください。

この時、理解しておきたいのは、アクセスをしている人は「プロバイダから払い出された ip アドレスでアクセスしており、その利用はプロバイダの利用規約に縛られる」ということです。
一般的なプロバイダでは「アビューズ(abuse)」を禁止しており、違反者は解約させることを可能としているケースが多いです。
また、プロバイダは、個人情報の開示依頼でもなく、「サービスに影響を与えたアクセス」を放置することのリスクを認識しているので、アクセス元へ伝達を断る理由を持ちません。

何度かプロバイダ経由でやり取りすることになるかもしれませんが、これでアクセス元からのおかしな利用を制限することが出来ます。

# おしまい
このやり方は、直接クレームを叩きつけることも出来ず、報復としても緩いですが、非常にお手軽です。
国内からのアクセスであれば、ほぼ収束させられるかと思います。

カジュアルなスクレイピングや勝手ペネトレーションテストに対応するには効果的なので、迷惑に思っているのであれば試してみてください。
DB周りのパフォーマンスチューニングに関して

書籍を読んだので補足しつつ備忘録…
読んだ書籍はこちら
https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AESQL%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-%E7%A6%8F%E7%94%B0-%E6%AD%A6%E5%BF%97/dp/4797336080

#パフォーマンスチューニングとは
処理時間が遅いシステムを早くすること。
と一言で言ってしまうのは簡単なのですが、では何をどうすればよいのかという話
DB周りに集中して紹介します。

#ボトルネックの調査
開発環境では往々にしてデータ数が少なく、本番に出した瞬間に重すぎてやばい、ということが起こり得ます。
本番のDBをダンプしたり、psqlなら本番で`\timing`を使うなどして心配なクエリを修正した方が得策です

#よくある原因
よく原因になりそうなところと解決策を書いていきます
実験に使うテーブルは
レコード数： およそ1000万件
インデックス：update_dateにのみ貼られている
とします。

##インデックスが貼られていない
よく取得するカラムにインデックスが貼られていないと、びっくりするくらいレスポンスが遅くなることがあります。
インデックスに関しては、
https://qiita.com/Ohtak/items/8089b8d1fe58ae52cc9d
でも書いたのでよければそちらもどうぞ
ただインデックスを貼る目安は、
`全体のデータ量の10%~15%未満のデータを取ってくるとき`
だそうなので、全部をselectするようなときには当てはまらない時もあります。
ちなみにpsqlで、

```sql

select
  id
from
  test_table
where
  update_date >= current_timestamp + CAST(-96 || 'hour' AS interval);
```

というクエリを投げた場合の実行時間は、（抽出数の平均は0.1%未満でした)

```
update_dateにインデックスあり：24848.563ms
update_dateにインデックスなし：108.471 ms
```

という結果だったので、これだけでかなり早くなります。

##インデックスを貼っていないカラムでソートしている
DBにおいて、ソートは時間のかかる処理ですが、それに対してjavaでソートする方が早く済むことがあります。

```sql

select
  id
from
  test_table
order by
  create_date;
```
というクエリの実行時間は15016.297 msですが、

```java

long start = System.currentTimeMillis();
List<Integer> idList = testDao.select();
Collections.sort(idList);
long stop = System.currentTimeMillis();
System.out.println("実行にかかった時間は " + (stop - start) + " ミリ秒です。");
```
の実行結果は13036msと、わずかにjavaで実行した方が早い結果となりました。
また、インデックスを貼ったカラムはつねにソートされた状態で格納されているため、

```sql

select
  id
from
  test_table
order by
  update_date;
```
では9075.452msという結果になります。
データ量やインデックスを貼っている/貼っていない、その後の処理で何をやるかによって
全体を吟味しながら使い分けた方がよさそうです。

##不要なカラムを取ってきている

```sql

select
  id
from
  test_table;
```

```sql

select
  *
from
  test_table;
```
の二つを比べた際、

```
idだけselect      ：5346.993 ms
全てのカラムをselect：12002.372 ms
```

という結果になりました。
必要な時でなければ、「とりあえず全部のカラムをとってきとけ」というのは避けた方がよいかも？
（ただ、カラムを一つ取り出すのも二つ取り出すのもSQLの処理的には同じ（はず）なので、単にデータ量がメモリを圧迫してただけとかの可能性もあります。）

##頻繁に呼び出すデータのキャッシュが作られていない
たとえインデックスが貼られていても頻繁に呼び出されすぎる、あるいは他が重くなった時問題になることがあります。
マスタデータなど、それほど更新されないデータはキャッシュにしてしまいましょう

#まとめ
いろいろ書きましたが、まとめると
・テストするときは本番環境に近づけよう
・インデックスを正しく貼ろう
・必要なデータだけとってこよう
となります。
当然のことを言っているようですが、システムを拡張する際など、意識していないとやらかすときがあるため気をつけましょう。
DBまとめ

# 1.リレーショナルデータベース

## 1-1.サーバ型
Oracle
MySQL
PostgreSQL
SQL Server

## 1-1-1.Oracle
バージョンとサポート期限
https://blog.serverworks.co.jp/tech/2020/03/09/rds-for-oracle-end-of-support-2020/

## 1-2.組み込み型
SQLite
H2

#NoSQL

## キーバリュー型
### 説明
ディクショナリのイメージ

### 名称
DBM
memcach
レディス


## ドキュメント型
### 説明
Key-Value型のValueの中にディクショナリを格納するイメージ。
ドキュメント志向データベース。
JSON形式のデータを格納するのでSQL文を使わない。

### 名称
MongoDB(もんごでーびー)

## ワイドカラム型
### 説明
テーブルの列の自由度が高く、行毎に自由に列を追加していく。
データが横に伸びていくイメージ

### 名称
Hbase(えいちべーす)
カサンドラ
googleビックテーブル

## グラフ型
### 説明
オブジェクトの関係性を扱う

### 名称
Neo4j
VSCodeでLaTeX環境を構築する際にハマったこと

# 環境概要

+ Windows 10
+ [VSCode](https://code.visualstudio.com/) + [LaTeX Workshop](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop) (最新版に追従)
+ [Sumatra PDF](https://www.sumatrapdfreader.org/free-pdf-reader.html)
+ [TeX Live 2018](http://www.tug.org/texlive/)

主に`up*`系のツールを使用

# ハマった点
## ツールチェインの設定
### 当初の設定

```json:settings.json(一部)
  "latex-workshop.latex.recipes": [
      {
          "name": "ptex2pdf (uplatex) -> pbibtex -> ptex2pdf (uplatex) *2",
          "tools": [
              "ptex2pdf (uplatex)",
              "upbibtex",
              "ptex2pdf (uplatex)",
              "ptex2pdf (uplatex)"
          ]
      },
      {
          "name": "ptex2pdf (uplatex) *2",
          "tools": [
              "ptex2pdf (uplatex)",
              "ptex2pdf (uplatex)"
          ]
      }
  ],
  "latex-workshop.latex.tools": [
      {
          "name":"ptex2pdf (uplatex)",
          "command": "ptex2pdf",
          "args": [
              "-l",
              "-u",
              "-ot",
              "-kanji=utf8 -synctex=1",
              "%DOC%"
          ]
      },
      {
        "name": "upbibtex",
        "command": "upbibtex",
        "args": [
            "%DOCFILE%"
        ]
    }
  ]
```

このようにして、コマンドを順次実行する設定としていた

### 問題点

* 文献リストを持たない小さい文章の処理が失敗する
    * 保存して自動コンパイルが走るたびにエラー

### 解決策

+ latexmkを使う

```json:settings.json(一部)
  "latex-workshop.latex.recipes": [
      {
          "name": "latexmk",
          "tools": [
              "latexmk"
          ]
      }
  ],
  "latex-workshop.latex.tools": [
      {
        "name": "latexmk",
        "command": "latexmk",
        "args": [
          "-e",
          "$latex=q/uplatex %O -kanji=utf8 -no-guess-input-enc -synctex=1 -interaction=nonstopmode -file-line-error %S/",
          "-e",
          "$bibtex=q/upbibtex %O %B/",
          "-e",
          "$biber=q/biber %O --bblencoding=utf8 -u -U --output_safechars %B/",
          "-e",
          "$makeindex=q/upmendex %O -o %D %S/",
          "-e",
          "$dvipdf=q/dvipdfmx %O -o %D %S/",
          "-norc",
          "-pdfdvi",
          "%DOC%"
        ]
      }
  ]
```

本当は`.latexmkrc`を使ったほうが`latex-workshop.latex.tools`の設定内容が短くなるらしい

## プレビュー機能に関して(未解決)
### 問題点
VSCodeのタブやブラウザを用いたプレビューが正常に表示できない
### 原因分析

* GitHubでも同様のIssueが上がっているが拡張機能の作者の環境では発生していない
    * 環境依存の問題
    * VSCodeや拡張機能の不具合ではなさそう
        * ネットワーク関係(ファイアウォール周り?)の問題か?

### 回避策
SumatraPDFを使ってSyncTeX活用してなんとか頑張る
自己紹介

# 自己紹介
2019年1月より某自動車会社から某IT企業に出向しています。仕事ではWebアプリケーション開発を、プライベートでは機械学習（勉強中）をしています。

---
# このブログで扱うこと
現在、以下のようなことに関心があり、これらについて書いていこうかと思います。プライベートの関心事中心になるかもしれません。

* 仕事
    * アジャイル（SAFe、Scrum、モブプログラミングなど）
    * モデリング（DDDなど）
    * テスト（BDDなど）
    * OutSystems
    * 働き方、人材育成
* プライベート
    * 機械学習、ディープラーニング
    * python
    * GitHub
    * （C#、Unityにも手を出してみたいが、今は余裕がない・・・）

---
# なぜブログを書こうと思ったのか？
昨年経験したいくつかの素晴らしい出会いや、[澤円の深夜の福音ラジオ](https://voicy.jp/channel/632/)に触発され、アウトプットの重要性を感じたためです。自分自身の記録にもなりますし、それが他の人の役にも立てるのであればいいですよね！`エキスパートでないとアウトプットしちゃいけない`と思っている方もいるとは思いますが、そんなことはなく書き手と読み手のレベル差が小さい方がいいこともあると思うようになりました。

---
# なぜQiita？
あまり理由はないのですが、これまで調べものでよく見ていたからというのが大きいです。あとスライドモードにも少し興味があり早速使ってみました。

---
# 最後に
ということで、今後このブログを書いていきたいと思います。もしもみなさんのお役に立てれば嬉しいです。
GoでAWSのBilling情報をグラフ化するmackerel-pluginを作った

公式プラグインでも利用しているGo言語でのカスタムメトリックプラグイン作成用ライブラリの
 `github.com/mackerelio/go-mackerel-plugin`
を利用して、GoでAWSのBilling情報をMackerelダッシュボードにグラフ化するmackerel-pluginを初めて作りました。

# Mackerelの公式サイト
- go-mackerel-pluginを利用してカスタムメトリックプラグインを作成する
  - https://mackerel.io/ja/docs/entry/advanced/go-mackerel-plugin 

# 開発環境と実行環境

- 開発環境
    - Mac: 10.14.1
        - Golang: 1.11.2
        - Goland
- 実行環境
    - AWS
        - EC2
            - Ubuntu16.04
            - mackerel-agent
            - IAMロール(Billingが取得できる権限をEC2に付与)


# 今回作ったmackerel-plugin-awsbillingのソースコードは以下
- GitHub 
  - https://github.com/yhidetoshi/mackerel-plugin-awsbilling




# EC2のUbuntuサーバに設定
- Macローカルでmain.goをUbuntu上で動くようにクロスコンパイルする。
  - `GOOS=linux go build -o bin/mkr-plugin-aws-billing` 

- このpluginを実行するにはAWSのAPIを実行できるIAMが必要です。
  - 今回はEC2インスタンスにBiliing情報を取得できるようにIAMロールを付与しました。
- Ubuntuサーバの以下のパスに配置しました。
  - `/usr/local/yhidetoshi/mackerel-plugin-aws-billing`

# mackerel-agentを設定

- `/etc/mackerel-agent/mackerel-agent.conf`を以下のように別ファイルの設定も有効にできるようにする。

```
apikey = "XXXXXXXXXXXXX"
include = "/etc/mackerel-agent/*"
```

- `/etc/mackerel-agent/get_billing`

```/etc/mackerel-agent/get_billing
[plugin.metrics.awsbilling]
command = '/usr/local/yhidetoshi/mackerel-plugin-aws-billing -region=us-east-1'
```

- mackerel-agentを再起動する
  - `$ sudo systemctl restart mackerel-agent`

# Mackerelダッシュボードのグラフを確認

mackerel-agentに設定したホストにカスタムメトリックにグラフが追加された。


![mkr-aws-billing-qiita.png](https://qiita-image-store.s3.amazonaws.com/0/63395/2c5ebb34-9c81-919e-fd9d-f4829f7ede50.png)


# Mackerel公式のレジストリに登録する

mackerelのレジストに登録されれば、`mkr plugin install プラグイン名` でインストールすることができるようになる。方法は以下のMackerel公式のブログでで説明されている。

- mkr plugin installに対応したプラグインをする
  - https://mackerel.io/ja/docs/entry/advanced/make-plugin-corresponding-to-installer

GitHubでリリースを自動化するために、TravisCIを利用。コード等は以下でサンプルが用意されていたので利用しました。

- https://github.com/mackerelio/mackerel-plugin-sample

TravisCIで自動リリースすると、以下のように、コンパイルしたものをzip化されたものが生成される。

<img width="765" alt="スクリーンショット 2019-01-19 12.16.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/63395/5d918add-bc50-795a-2169-5ff4b0807414.png">


リリースまで完了したら、以下のリポジトリにPullRequestを投げる。PRを投げるときは、以下のリポジトリをForkしてからPRを作成しました。

- https://github.com/mackerelio/plugin-registry


<img width="801" alt="mackerel-plugin-git.png" src="https://qiita-image-store.s3.amazonaws.com/0/63395/8ab59c3c-6f16-07ef-c236-86fcc2579e03.png">

→ PRがMergeされて、`mkr plugin install プラグイン名` でインストールすることができるようになりました。

```bash
$ sudo mkr plugin install mackerel-plugin-awsbilling
Password:
           Downloading https://github.com/yhidetoshi/mackerel-plugin-awsbilling/releases/download/v0.0.3/mackerel-plugin-awsbilling_darwin_amd64.zip
           /opt/mackerel-agent/plugins/bin/mackerel-plugin-awsbilling already exists. Skip installing for now
           Successfully installed mackerel-plugin-awsbilling
```

# まとめ
Goを使って、mackerel-pluginを初めてつくりました。Pluginを作ることでGoの学習になりますし、またシステムを可視化することもできます。そして、作ったプラグインをmkrのレジストリに登録するところまでやりました。今後も別のプラグインを作っていければと思います。
VuexFireのDXが悪いのでVuexBlazeというライブラリを作ってみた

# VuexBlaze

* [github](https://github.com/ishiijp/vuexblaze)
* [npm](https://www.npmjs.com/package/vuexblaze)

## VuexFireのDXのどこが悪いのか？

### （1）Vuexのプラグイン機能を使っていない

VuexFireを使うにはルートのStoreに以下のようにMutationを追加する必要があります。

```
export default new Vuex.Store({
  mutations: {
    ...firebaseMutations
  }
})
```

これと同等のことは、Vuexのプラグイン機能を使えば可能です。
VuexFireのドキュメントを見るとちゃんと「ルートのStoreだけにfirebaseMutationsを設定せよ」と書いてあるのですが、コードだけを見ると、FirestoreをバインドさせたいすべてのStoreに設定しなければいけないのかな？と思ってしまいます。
実際モジュールのStoreのみにfirebaseMutationsを設定してハマっている人を見ました。
このように不要にライブラリの内部構造をさらけ出すようなコードを書かせるのはあまりよくないと思います。

### （2）バインドのためのコードが冗長

ただ単純にtodosコレクションをnameでソートしてtodosステートにバインドさせるだけなのに、アクションにこんな冗長なコードを書く必要があります。

```
  actions: {
    bindTodos: firebaseAction(({ bindFirebaseRef }) => {
      bindFirebaseRef('todos', todosRef.orderBy('name'))
  })
```


## VuexBlazeでは？

VuexBlazeのセットアップを含めたコードは以下のようになります。
※ firebaseのセットアップについては省略しています。

```
import { vuexblazePlugin, collection } from 'vuexblaze'
// .... firebaseのセットアップ
const firestore = firebase.firestore()

export default new Vuex.Store({
  plugins: [vuexblazePlugin.config({ firestore })],
  state: {
    todos: []
  },
　　　　actions: {
    ...collection('todos').orderBy('name').bind()
  }
})


// Vueインスタンス側
  mounted() {
    this.$store.dispatch('bindTodos')
  }
```


vuexblazePluginにfirestoreオブジェクトを渡していますが、[Nuxt](https://ja.nuxtjs.org/guide/)を使っていてかつ[Nuxt-Fire](https://github.com/lupas/nuxt-fire)でfirebaseをセットアップしている場合は、単に以下のようにすればOKです。

```
export const plugins = [vuexblazePlugin]
```

もちろんorderBy以外のクエリにも対応しています。

```
  ...collection('todos')
    .orderBy('name')
    .where('done', '==', true)
    .limit(10)
    .bind()
```

todosステート以外にバインドさせたい場合は、bindToを使います

```
  ...collection('todos')
    .where('isUrgent', '==', true)
    .bindTo('urgentTodos')


  // Vueインスタンス側
  this.$store.dispatch('bindUrgentTodos')
```

クエリを動的にしたい場合はfilterを使います。

```
    ...collection('todos')
      .filter(({ query, state, rootState, getters, rootGetters }) => {
        query
          .where('done', '==', state.search.done)
          .orderBy('name')
          .limit(state.search.limit)
      })
      .bindTo('searchedTodos')

  // Vueインスタンス側で再読込
  this.$store.dispatch('reloadSearchedTodos')
```


# VuexBlazeの詳細

とりあえずは、githubの[README](https://github.com/ishiijp/vuexblaze)や、[Vue Example](https://github.com/ishiijp/vuexblaze/tree/master/examples/vue-app)、[Nuxt Example](https://github.com/ishiijp/vuexblaze/tree/master/examples/nuxt-app) を見てください。

バグは…あると思います。今の所ホットリロードしたときに変な動きをすることがあるのを確認しています。

# 質問など

質問やバグ報告など大歓迎です。使い方が分からないとか、そもそもVue、Vuexが分からないとかそんなものでも結構なのでどしどしください。

githubのIssueは英語で運用したいと思っているので、英語が苦手な方は[Twitter](https://twitter.com/techlessninja)で質問頂けるとうれしいです。
Python3開発環境構築

#PyCharm

[File]-[Settings]を開く
[Editor]-[Inspections]から「PEP 8 coding style violation」と「PEP 8 naming convention violation」にチェックが付いていることを確認する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/187121/71f61071-070b-4c50-f303-06f470575c8c.png)

# Visual Studio
以下のページを参考に構築。
https://docs.microsoft.com/ja-jp/visualstudio/python/tutorial-working-with-python-in-visual-studio-step-00-installation?view=vs-2019

## pytest
https://docs.microsoft.com/ja-jp/visualstudio/python/unit-testing-python-in-visual-studio?view=vs-2019

ソリューションを右クリックし、[プロパティ]を開く。
[テスト]タブの[テストフレームワーク]で【pytest】を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187121/8cfc965b-804d-8a84-4074-aba88ac8b8d8.png)

「Python環境」でpytestをインストールする。
表示させるには、[表示]-[その他ウインドウ]-[Python環境]を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187121/94962ed4-615f-789c-1f30-4bf6861cee24.png)

## logging

標準ではinfoやdebugは出力されない。

```py
import logging

logging.basicConfig(level=logging.DEBUG)
# ファイルにも出力する
#logging.basicConfig(filename+'test.log', level=logging.DEBUG)
logging.debug("デバッグ")
```
IT業界のノンフィクション、オススメ5冊+1

# はじめに
　それほど歴史が長くないIT業界でも素晴らしいノンフィクション本が多数あります。オススメ5冊+1をお届けします。

## [闘うプログラマー][1]
筆頭は、Windows NT開発プロジェクトは、当時としては想像を絶する大変さがわかる。
[1]: https://www.amazon.co.jp/gp/product/4822247570

## [ゼロ・トゥ・ワン 君はゼロから何を生み出せるか][2]
ノンフィクションでもあり、起業家論でもある。
[2]: https://www.amazon.co.jp/gp/product/B00NQ3QONK

## [Google誕生][3]
初期のGoogleのストーリー。[「Google が掲げる 10 の事実」](https://www.google.com/about/philosophy.html) の背景が理解できる。
[3]: https://www.amazon.co.jp/gp/product/4872576446

## [不格好経営―チームDeNAの挑戦][4]
日本で経営する困難さとダイナミックを体感できる。
[4]: https://www.amazon.co.jp/gp/product/4532318955

## [メルカリ 希代のスタートアップ、野心と焦りと挑戦の5年間][5]
今でこそユニコーンと言われるメルカリだが、決して楽な道のりでは無かった。ただし、書籍としての出来は、著者の取材力は高そうだが、文筆力は？
[5]: https://www.amazon.co.jp/gp/product/4822289508

## [トヨタの製品開発][6]
IT業界ではないが、製品開発のノンフィクションとして、プロダクトマネージャーのお手本として、外せない一冊。
[6]: https://www.amazon.co.jp/gp/product/4561520899

#おわりに
　よく書かれているノンフィクションは、まるで自分ごとのように没頭して読んでしまいますので、ご注意を（笑）
render propsを使ってContainer層とPresentational層を分離する

## やりたいこと

「Clean Architecture　達人に学ぶソフトウェアの構造と設計」を読んで、reactのContainer層とPresentational層の分離をちゃんとやりたいなと思い、その方法を考えました

普通に書いていても頑張って意識すれば分離はできるのですが、書き分けるのが手間で、どうも境界が曖昧になってしまっていました
その結果、結局Presentational層にロジックが混ざり込んでしまうのがちょっと悩みだったので、それを解決したいなと思っていました

Clean Architecture的な志向で、層を分離し、依存関係を一方通行にしたいです

下記のように分離したいイメージです

 |Container層|Presentational層
--- | --- | ---
react | Container | UI Component
MVVM | ViewModel | View
Rails | Controller | View

## やり方

サンプルはtypescriptで書いています

```typescript
import { useState } from 'react';

//
// Container層
//
interface IViewModel {
  count: number
  onClickPlus: () => void
  onClickMinus: () => void
}

interface IProps {
  children: (viewModel: IViewModel) => JSX.Element;
}

const CounterContainer = (props: IProps) => {
  const [count, setCount] = useState(0);
  return props.children({
    count,
    onClickPlus: () => { setCount(count + 1) },
    onClickMinus: () => { setCount(count - 1) }
  });
};

//
// Presentational層
//
const CounterUI = () => {
  return (
    <CounterContainer>
      {viewModel => (
        <div>
          <p>count: {viewModel.count}</p>
          <button onClick={viewModel.onClickPlus}>+</button>
          <button onClick={viewModel.onClickMinus}>-</button>
        </div>
      )}
    </CounterContainer>
  );
};
```

このようなrender propsを利用した書き方をすることで、層の分離がしやすくなるかなと思いました

- Container側にUIのコードが混ざっていたらすぐに検知できる
    - というか混ぜるのが難しい
- Presentational側ではContainerから与えられたデータにしかアクセスできない
    - 自然とUI周りのコードだけになっていくはず


## 考察

Clean Architecture的な構成にしたいなと思っており、Container層とPresentational層のディレクトリも分離したいと思っていました
そしてContainer側はPresentational側に依存しない・一切知らなくてOKという状態にしたいと思っていました

今回の書き方ならディレクトリを分離し、依存関係を一方通行にすることができるので、やりたいことは実現できそうでした

その結果、Clean Architectureの恩恵として下記のようなことも容易に実現可能な気がしています

- UIの差し替えが楽そう
    - PCブラウザだろうがReactNativeだろうが、Presentational層の差し替えだけで対応できそう
- UIに依存しないContainer層だけのユニットテストが書きやすい？
- Container層はさらに別のレイヤーへの一方通行の依存もできそう


## 参考

書いた後に「似たようなことやっている人いるだろうなぁ」と思ってググってみたらいました

> The motivation behind the render prop pattern is the separation of concerns between state management and render logic.

https://medium.com/@jacobdfriedmann/render-props-composability-and-performance-74dd4ac881e2
PHPでXML文字列を整形（フォーマット）する

XMLをログ出力するときに、きちんとフォーマットして出力しようと思いました。

結論から言うと以下のコードで実現できました。

```
<?php
use SimpleXMLElement;

// 略

$simpleXmlElement = new SimpleXMLElement($xml);
$dom = dom_import_simplexml($simpleXmlElement)->ownerDocument;
$dom->formatOutput = true;

echo $dom->saveXML();

// 略
```

SimpleXMLElementはPHP5以上なら標準でバンドルされているので、特別な対応をしなくても利用することができます。
git config で設定場所の分からない項目の探し方

# 概要
git で作業していた時 `core.autocrlf` の値がおかしかったので修正しようと思ったら
`system` でも `global` でも `local` でもない場所に設定されていたのでハマってしまいました。
そんな設定場所の分からない項目を探せる、便利なオプションがありました。

# 環境
* Windows 10 Pro
* `git version 2.20.1.windows.1`

# 探し方
結論から言うと `--show-origin` [^1] オプションを使うと、どのファイルから設定されているかが分かります。
`git config -l --show-origin` を実行すると一覧で取得できます。（内容は長くなるので省きます。）
Windows の場合３箇所以上にファイルが存在していました。

また、個別のファイルの確認コマンドと場所は以下の通りでした。

1. `git config -l -f %PROGRAMDATA%\Git\config`
    - 場所： `%PROGRAMDATA%\Git\config`
2. `git config -l --system`
    - Git for Windows を使用している場合
        - 場所： `C:\Program Files\Git\mingw64\etc\gitconfig`
    - SourceTree を使用している場合
        - 場所： `%LOCALAPPDATA%\Atlassian\SourceTree\git_local\mingw32\etc\gitconfig`
3. `git config -l --global`
    - 場所： `%USERPROFILE%\gitconfig`
4. `git config -l --local`
    - 場所： `<Git Repository Path>\.git\config`

特に１番はファイルの場所を知っていないと全く分からないです。
ちなみに項目の設定は以下のようにできます。（実行には管理者権限が必要かもしれません。）
`git config -f %PROGRAMDATA%\Git\config core.autocrlf false`

# 参考
* https://stackoverflow.com/questions/17756753

[^1]: `--show-origin` は git 2.8 以降で使用できるようです。
【RubyonRails】モデルの関連付けについて

##はじめに
　ポートフォリオを作成する中で、モデルの関連付けについてコーディングしてみましたので、備忘録として残します。

####なぜモデルの関連付けを行うのか
　これまで「なぜモデルの関連付けを行うのか」ということについて、あまり意識しませんでしたので、調べてみました。

モデルの関連付けを行うことにより、以下のようなメリットがあるようです。
・コードを簡略化できる
・コードを書かなくても、必要な処理をやってくれる（あるレコードを削除したら、別モデルの関連するレコードを削除してくれる等）

URL(http://d-policy.com/?p=278)


####今回やりたいこと（目的）
　下記モデル関連図において、Userモデルのレコードを削除した際に、Meetingモデル・Relationshipモデルの関連するレコードを削除し、参照整合性を保つこと。

##モデル概要図
|Userモデル|
|---------|
|・id      |
|・name    |
|  以下省略|

|Meetingモデル   |
|---------------|
|・id         　　　　　　　|
|・content    　　　　　　　|
|・userid(外部キー)|
|  以下省略　　　　　　　　　　　　　　|

|Relationshipモデル   |
|--------------------|
|・follower_id(外部キー)|
|・followed_id(外部キー)|
|  以下省略　　　　　　　　　　　　　     　|


##コード
　下記のコードでうまくいきました。

####ポイント
①参照先モデル（Userモデル）側にオプション「dependent: :destroy」を記述
②Meetingモデルの外部キーを任意の値に指定（foreign_key: 'userid'）
　→外部キーを指定しない場合は、自動的に設定されるようです。今回のMeetingモデルの場合だと、外部キーが「user_id」としてSQLが発行されるようです。当該モデルには「user_id」というカラムは存在しないので、任意の値（userid）としました。
参考URL（http://www.coma-tech.com/archives/223/）

③Userモデル-Relationshipモデルの関連付けは、外部キーが２つ存在（follower_id、followed_id）
　参考URL（https://qiita.com/takeoverjp/items/bb56d6a8eae191cd3732）

```ruby:user.rb
class User < ApplicationRecord
  #Meetingモデルとの関連付け
  has_many :meetings, class_name: 'Meeting', foreign_key: 'userid', dependent: :destroy

  #Relationshipモデルとの関連付け
  has_many :relationship_follower, class_name: 'Relationship', foreign_key: 'follower_id', dependent: :destroy
  has_many :relationship_followed, class_name: 'Relationship', foreign_key: 'followed_id', dependent: :destroy
end
```
```ruby:meeting.rb
class Meeting < ApplicationRecord
  belongs_to :user , class_name: 'User'
end
```

```ruby:relation.rb
class Relationship < ApplicationRecord
  belongs_to :user, class_name: 'User'
end
```
【SAPUI5】OData(4) SAPでのODataサービスの作り方 環境編

##はじめに
SAPのバックエンド（ERPなど）からデータを抽出するODataサービスを作るとき、SAP Netweaver Gatewayというサーバが必要になります。
今回の記事では、SAP Netweaver Gatewayの概要についての説明と、SAP Netweaver Gatewayの導入パターンについて説明します。

※OData関連の投稿一覧は以下の記事をご参照ください。
[【SAPUI5】OData(1) ODataとは](https://qiita.com/tami/items/411a226d1ea6bb25b5f1)

##SAP Netweaver Gatewayとは
SAP Netweaver Gatewayは、SAPシステムと他のシステムを接続する際のハブとなるシステムです。
ODataの開発、生成用のツールをはじめ様々な開発用ツールを持っています。
ODataサービスを連携先に公開することで、連携先はプログラミング言語に依存せずに開発ができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/610d2e81-0848-e76b-2e4f-0394eb20692a.png)
[SAP Gateway Foundation (SAP_GWFND)](https://help.sap.com/viewer/68bf513362174d54b58cddec28794093/7.5.13/en-US/)より引用

##SAP Netweaver Gatewayの導入パターン
SAP Netweaver Gatewayの導入パターンには以下の3種類があります。
※SAP HANA Cloud PlatformでODataサービスを公開するクラウドのパターンもありますが、今回は割愛します。

###1. Hub Deployment：バックエンドで開発
SAP Netweaver Gatewayを独立したサーバにインストールし、SAP Netweaver Gatewayがシステム間連携のハブになります。
バックエンドシステムにもGatewayのコンポーネント（NetWeaverのバージョンにより、IW_BEPまたはSAP_GWFND）をインストールする必要があります。
ODataサービスの開発はバックエンドで行い、SAP Netweaver Gatewayから公開されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/fa28c66f-6946-8b10-6eff-1e0b5836e325.png)
[OData – Everything that you need to know (Part 5)](https://blogs.sap.com/2016/02/08/odata-everything-that-you-need-to-know-part-5/)より引用

####メリット
- バックエンドシステムへはSAP Netweaver Gatewayを介して接続するので、安全性が高い
- バックエンド側のDDIC（構造など）やクラスを参照して開発ができる

###2. Hub Deployment：HUBで開発
1.と似た構成ですが、ODataサービスの開発をSAP Netweaver Gatewayで行います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/46ad005d-c2dd-9cd8-3840-ea289ffd4cd6.png)

####メリット
- バックエンドシステムにGatewayのコンポーネントをインストールする必要がない

####デメリット
- バックエンドのデータソースへのアクセスは、BAPIやRFCを使ってのみ可能（テーブルに直接アクセスできない）
- バックエンドのDDIC（構造など）やクラスを直接参照することができない

###3. Embedded Deployment
SAP Netweaver Gatewayを独立したサーバにインストールするのではなく、バックエンドシステムのアドオンとしてインストールする構成です。
ODataの開発と公開はバックエンドで行います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/ba3bfac1-c7de-cbbb-c5aa-9c676366079f.png)

####メリット
- SAP Netweaver Gateway用のサーバの費用がかからない
- 上記2つの構成と比べてサーバ間の連携が減るのでオーバーヘッドが少ない

####デメリット
- 複数のバックエンドシステムがある場合、それぞれにSAP Netweaver Gatewayをインストールする必要がある
- バックエンドシステムのアップグレードサイクルとSAP Netweaver Gatewayアップグレードサイクルが異なる可能性がある（SAP Netweaver Gatewayをインストールしたものの、バックエンドをアップグレードしなければならなくなった、など）
- 外部システムからバックエンドに直接アクセスする構成となるため、追加のセキュリティ対策が必要



##参考
[OData – Everything that you need to know (Part 4)](https://blogs.sap.com/2016/02/08/odata-everything-that-you-need-to-know-part-4/)
[OData – Everything that you need to know (Part 5)](https://blogs.sap.com/2016/02/08/odata-everything-that-you-need-to-know-part-5/)
[SAP NetWeaver - Gateway](https://www.tutorialspoint.com/sap_netweaver/sap_netweaver_gateway.htm)
[Deployment options with SAP Gateway](https://blogs.sap.com/2018/01/23/deployment-options-with-sap-gateway/)

##関連記事
[OData(3) ODataのQuery optionsを使ってみる](https://qiita.com/tami/items/181cabc4cd8c51ce87b2)
[OData(5) SAPでのODataサービスの作り方 開発編-1](https://qiita.com/tami/items/f49a4a6be1ffd83cc87c)
ESLint v5.12.0

前 [v5.11.0] | 次 [v5.13.0]

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">ESLint v5.12.0 has been released: <a href="https://t.co/k3ePrDOMsH">https://t.co/k3ePrDOMsH</a></p>&mdash; ESLint (@geteslint) <a href="https://twitter.com/geteslint/status/1081295549708537856?ref_src=twsrc%5Etfw">2019年1月4日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ESLint 5.12.0 がリリースされました。
小さな機能追加とバグ修正が行われました。

質問やバグ報告等ありましたら、お気軽にこちらまでお寄せください。

> 🏢 [日本語 Issue 管理リポジトリ](https://github.com/eslint/eslint-jp)
> 👫 [日本語サポート チャット](https://gitter.im/eslint/eslint-jp)
> 🏢 [本家リポジトリ](https://github.com/eslint/eslint)
> 👫 [本家サポート チャット](https://gitter.im/eslint/eslint)

# 🚀 本体への機能追加

特になし。

# 💡 新しいルール

特になし。

# 🔧 オプションが追加されたルール

## [#11040]: [sort-imports] ignoreDeclarationSort

`import` 文の並び順について、ステートメントの並び順をソートしないようにする (ステートメント内の変数定義順だけ並び替える) ためのオプションが追加されました。

```js:例
/*eslint sort-imports: ["error", { "ignoreDeclarationSort": true }]*/

//✔ GOOD
import foo from "foo"
import bar from "bar"
```

> [Open online demo](https://eslint.org/demo/#eyJ0ZXh0IjoiLyplc2xpbnQgc29ydC1pbXBvcnRzOiBbXCJlcnJvclwiLCB7IFwiaWdub3JlRGVjbGFyYXRpb25Tb3J0XCI6IHRydWUgfV0qL1xyXG5cclxuLy/inJQgR09PRFxyXG5pbXBvcnQgZm9vIGZyb20gXCJmb29cIlxyXG5pbXBvcnQgYmFyIGZyb20gXCJiYXJcIlxyXG4iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjgsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=)

# ✒️ `eslint --fix` をサポートしたルール

特になし。

# ⚠️ 非推奨になったルール

特になし。

[v5.11.0]: http://qiita.com/mysticatea/items/d843ec4f8efafb0d4623
[v5.13.0]: http://qiita.com/mysticatea/items/afc990fcdabef1d6722e
[#9999]: https://github.com/eslint/eslint/issues/9999
[#11040]: https://github.com/eslint/eslint/issues/11040
[xxxx]: http://eslint.org/docs/rules/xxxx
[sort-imports]: http://eslint.org/docs/rules/sort-imports

<!-- 
![JSCS Icon](http://jscs.info/favicon.ico) JSCS 互換ルールです。
-->
LaravelのQueryBuilder使用時のtimestanpへの日付時刻処理について

#0.前提条件
環境：laravel5.3、cloud9、PHP7.0
laravelのmigrationファイルでは、以下の記載により、"created_at"と"updated_at"のカラムを自動で作成してくれて便利である。

```php:2019_01_03_170250_create_user_table.php

 public function up() {
         Schema::create('table_names', function (Blueprint $table) {
         $table->timestamps();
         }
 }
```
しかし、ORM Eloquentモデルを利用すれば、insertやupdate時に自動でそれぞれのカラムに自動で日付を記載してくれるのだが、QueryBuilderを使用した場合は、どうやら自動的に入れてくれない(NULLになる)ようで、自分で入れる必要がある。

#1.Carbonクラスを利用して日付を入れる。
解決方法としてはCarbonクラスを使うのが手取り早いようだ。

```php

use Carbon\Carbon;

DB::table('table_names')->insert(
    ['created_at' => Carbon::now(),'updated_at' => Carbon::now()]
);
```

とりあえずこれでinsert時の日付時刻処理ができた。update時は以下の通り"updated_at"のみ更新すれば良い。

```php
DB::table('table_names')->insert(
    ['updated_at' => Carbon::now()]
);
```


#2.参考URL
https://www.larajapan.com/2016/11/26/laravel-5-3-%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%97%E3%81%AEdb%E9%A0%85%E7%9B%AE%E5%90%8D%E3%81%AE%E6%8C%87%E5%AE%9A/
https://qiita.com/yudsuzuk/items/ff894bd0b76d4657741d
Kensington Expert MouseをLinux環境で設定する

## 環境

- [Kensington Expert Mouse 7](https://www.kensington.com/p/products/control/trackballs/expert-mouse-wired-trackball/)

## Installtion

LinuxではExpert MouseはドライバーなしでPlug＆Playで動くけどxorgの設定など変えればボタン配置を変えたりスクロールを楽に出来る

以下設定方法

Expert Mouse用のxorg confを追加する

```bash
$ sudo vim /usr/share/X11/xorg.conf.d/50-kensington-expert-mouse.conf

Section "InputClass"
        Identifier "Kensington Expert Mouse"
        MatchIsPointer "on"
        MatchProduct "Kensington Expert Mouse"
        Option "EmulateWheel" "true"
        Option "EmulateWheelButton" "8"
        Option "EmulateWheelInertia" "20"
        Option "ButtonMapping" "1 8 3 4 5 6 7 9 2"
        Option "Emulate3Buttons" "true"
        Option "XAxisMapping" "6 7"
        Option "YAxisMapping" "4 5"
EndSection
```

ファイル作成後一旦ログインしなおす

この状態でボタン配置は

```bash
Back | Forward
-----+--------
Left | Right
```

となっていてこの状態で右上のボタンを押しつつボールを転がすとホイール操作をエミュレーション出来てボールを転がして縦スクロールや横スクロールなどが出来るようになる

しかしこの状態だとホイールクリック（中クリック）が使えないため [easystroke](https://github.com/thjaeger/easystroke/wiki) を使うことで中クリックをエミュレーションさせる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/47983/59f9a05d-a380-dfb5-c617-fe731dc303c5.png)

解説: ボタン8(左上)とボタン9(右上)を連続的に押すことでボタン2（中クリック）をエミュレーションしている
ジェスチャ1と2ではボタンシングルクリックで戻る(Alt+Left), 進む（Alt+Right）をエミュレーションしているがこれは [Synergy](https://symless.com/synergy) でWindowsを操作する際に戻るボタンと進むボタンがWindowsで効かなかったためこうしている

パッチを書く方法もあるみたいだが今回はソフトウェアでエミュレーションしてみた

## 参考

- [Linux\(X11\)でKensingtonのExpert Mouse 7を使う \- emonkak's Blog](http://emonkak.hatenablog.com/entry/2011/12/30/131508)
- [Linux でトラックボールを設定する \- Qiita](https://qiita.com/Lirimy/items/c996163cc2540f603ea9)
【Unity(C#)】ゲームオブジェクトを点滅させる方法

　　
　　
　　
この記事は

**『プログラミング完全未経験からUnityでの開発現場に迎え入れてもらえた世界一の幸せ者』**

の記事です。そのつもりでお読みください。
　　

# ゲームオブジェクトを点滅させる
※点滅させたいゲームオブジェクトにAdd Componentさせるつもりで書いてます。

点滅させるにはmaterialのalpha値(透明度)を変化させます。

unityのColorのalpha値は0～1で設定可能なので点滅させるために
時間変化で0~1の値を取る数値を用意します。

```C#
float alpha_Sin;

void Update()
    {
        alpha_Sin = Mathf.Sin(Time.time) / 2 + 0.5f;
    }
```
↓こういうこと(とても分かり易い図)。赤い線のグラフがalpha_Sinです。

![sin0~1.png](https://qiita-image-store.s3.amazonaws.com/0/244071/7af9ed9d-dccb-b8ee-52f2-0932ffa3002e.png)

Update関数内でalpha値を代入すれば点滅しますが、汎用性に欠けるので
今回はコルーチンを作って好きなタイミングで点滅を開始しやすくしました。
参考:[コルーチン](https://qiita.com/OKsaiyowa/items/d0f59ae0c97b29118a80)

```C#
IEnumerator ColorCoroutine()
    {
        while (true)
        {
            yield return new WaitForEndOfFrame();

            Color _color = this.gameobject.material.color;

            _color.a = alpha_Sin;

            this.gameobject.material.color = _color;
        }
    }
```

好きなタイミングでコルーチンを呼びましょう。
Kaggleのサイト上でKernel (Pythonプログラム) を実行する方法

# はじめに
Kaggleのサイト上でGPU(NVIDIA Tesla K80)を用いてKernelを実行するとが出来ることが分かったので方法を記載しておきます。
Kaggleのアカウント作成やコンペの参加方法がわからない方は、[Kaggle事始め](https://qiita.com/taka4sato/items/802c494fdebeaa7f43b7)で分かりやすく説明されていますので参照してください。

# Kernelを作成する
Kernelを作成する方法は新規に作成する方法と既にあるKernelをFork(コピー)することで作成することができます。他の人が公開しているKernelからもForkすることが出来るので便利です。

#### Kernelを新規作成作成する方法
コンペティションのサイトからKernelを選択し、New Kernelを押すことで作成することができます。作成できるKernelのタイプはScrip(*py)またはNotebook形式(*.ipynb)
![Kernel新規作成.jpg](https://qiita-image-store.s3.amazonaws.com/0/111514/30db2c76-7fb8-9ed4-9ec1-777d3d213277.jpeg)

#### 既にあるKernelをFork(コピー)する方法
他の人が公開しているKernelもForkすることができます。やり方はKernelを表示したときに右上に出てくるForkボタンを押すだけです。以下はTitanic: Machine Learning from Disasterの初心者向け解説 Kernelである[Titanic Data Science Solutions](https://www.kaggle.com/startupsci/titanic-data-science-solutions)をForkして実行してみます。

![Kernel_Forkの仕方.jpg](https://qiita-image-store.s3.amazonaws.com/0/111514/5f30c852-1a62-d058-f9f2-1c84b93e88b6.jpeg)


# Kernelの操作
Jupyter Notebookと同じようにセルを選択して再生ボタンを押すかShift+Enterを押すことでプログラムを実行することができます。注意点と私が理解できている操作の方法を記載しておきます。

#### 注意点
・DataFrame.to_csv()等でファイルをする場合には以下の⑤Commitボタンでプログラムを実行する必要があり①～③のボタンではファイルが作成されない。
・KernelをForkした場合には、input file の pathが異なっていたり、scikit-learnのモジュール名が変更になっててエラーが出ることが多い。


#### 操作の方法
①選択しているセルの実行(Shift+Enterでも同じ)
②①と同じく選択しているセルの実行、このボタンは実行時には停止ボタンになる。
③ページの一番上から下まですべて実行される（実行前にイニシャライズはされない）
④Kernelのイニシャライズ。オブジェクトをすべて削除される。
⑤Commitボタン。Kernelのすべてのプログラムが実行され、ファイルも作成される。
⑥Kernelのダウンロードとアップロード。ダウンロードしたKernelはJupyter Notebookで実行できる。
⑦ファイルの追加。 学習済みのニューラルネットの重みなどをアップロードすれば、Kernelで使用可能
⑧GPUのON/OFFボタン。GPUをONにすると使用できるRAMやDisk容量が少し小さくなり、カスタムパッケージも使えくなるがKeras+Tensorflowでニューラルネットワークの重みを学習するならONにしたほうが断然早い。
⑨Kernelのタイトル。ここでタイトルを編集することが出来る。

![Kernel_操作画面.jpg](https://qiita-image-store.s3.amazonaws.com/0/111514/693fd0f5-3a11-b965-a207-ccbf6f26f708.jpeg)

# Kernelから直接submitする方法

[Titanic Data Science Solutions](https://www.kaggle.com/startupsci/titanic-data-science-solutions)はForkした場合は、そのままCommitするとsubmissionファイルが作成されないため、『submission.to_csv('submission.csv', index=False)』を追加してからsummitしてください。

```
submission = pd.DataFrame({
        "PassengerId": test_df["PassengerId"],
        "Survived": Y_pred
    })

#submission.to_csv('../output/submission.csv', index=False)
submission.to_csv('submission.csv', index=False)
```
Submission済みのKernelを開き、Output　、予測結果(この場合はsubmission.csv)の選択、Submit to Competitionを押すことでKernel上から直接Submitすることができます。
![Kernel_submission.jpg](https://qiita-image-store.s3.amazonaws.com/0/111514/5ee2ccd3-438f-7718-06df-e62b3c9b4973.jpeg)

# おわりに
本格的にKaggleのコンペティションに参加するようになるとRAMやDiskの容量が物足りなくなってくるとは思いますが。初心者のうちはKaggleのサイト上でKernelを実行しながら勉強していくのがよいのではないかと思います。
因みに、NVIDIA Tesla K80はAmazonで価格を見ると約14万円で、Keras+Tensorflowで畳み込みニューラルネットワークの学習をGPU ON/OFFで試してみましたが、１０倍程度の速度差がありました。
【PHP】配列の空判定〜キーが指定されると、値が空でも配列は空と見なされない〜

仕事中にふと気づいたのでメモしておきます。

単純な空の配列は空と見なされます。

```php
<?php
$member = array();

if ($member) {
    echo 'success!';
} else {
    echo 'error!';
}

// 出力結果:error!
```

しかし、``キーが指定され値が空の状態``だと、配列自体は空と見なされません。

``if (!empty($member2))``や``if (isset($member2))``を使用した場合も、同じ判定でした。（こちらは変数の判定ですが。） 

```php
<?php
$member2 = array('id' => '', 'name' => '');

if ($member2) {
    echo 'success!';
} else {
    echo 'error!';
}

// 出力結果:success!
```

ちなみに``var_dump``するとこうなります。
配列自体は存在している・・・という解釈なのでしょうか？

```php
<?php
var_dump($member2);

// 出力結果:
// array(2) {
//   ["id"]=>
//   string(0) ""
//   ["name"]=>
//   string(0) ""
// }
```

もちろん要素を直接指定すれば、空と判定されます。

```php
<?php
$member2 = array('id' => '', 'name' => '');

if ($member2['id']) {
    echo 'success!';
} else {
    echo 'error!';
}

// 出力結果:error!
```

こういう間違いがありそうで怖いな〜と思いました。
Dashboard 年齢算尺Widget「CalcAge」改修事項

年齢計算や西暦・和暦の変換に便利なように，2013年頃に「CalcAge」というDashboard Widgetを作っていました。（良い公開場所があれば教えて下さい。）
<img width="363" alt="スクリーンショット 2019-01-05 13.47.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/192970/02475d0e-1a1f-6fdc-ef9f-fc122e27b00c.png">
改元への対応準備のついでに，（おそらくWebKitのバージョンアップに伴い）動作がおかしくなっていた部分を改修し，ついでに若干の機能変更を加えたので，その備忘録。

# input[@type=range]のスライド中に値を拾う(onchange -> oninput)
従来，スライダーの値の変更は onChange イベントを拾っていました。
作成時にはこれで，スライダーを動かせばドラッグ中にリアルタイムに値が変更されていたのですが，いつの頃からか，onChangeは値の確定時（ドラッグを離した時）だけに呼び出されるようになっていました。動かしている最中に値が分からず不便。
ということで，onchangeに割り当てていたアクションをoninputに変更。

# スライダーの範囲の変更と自動拡張
従来，スライダーの値は1900〜2030の幅で固定していましたが，この横幅で131段階もあると操作がシビアです。
そこで，起動時は1944〜今年+1の幅とし，スライダーが上限or下限に達した場合に，上限or下限を拡張するようにしました。1944を始点にしたのは，戦後生まれ≒団塊について拡張せずに年齢を計算できるようにする狙いです。
<img width="550" alt="CalcAgeスクショ.png" src="https://qiita-image-store.s3.amazonaws.com/0/192970/ce33c1c6-5788-0ce8-8c99-5b241b60d21d.png">
具体的には，値の確定時（上述のonChangeイベント）に`Elemet.value`が`Element.max`や`Element.min`と一致するかどうかを判定し，一致する場合は，上限値は+20に，下限値は前の年号の開始年-1に，拡張します。

```javascript
// スライダーが端まで行った時に処理する。
function judgeExpand(event){
    if(event.target.valueAsNumber == event.target.max){
        event.target.max = Number(event.target.max)+20;
    }else if(event.target.valueAsNumber == event.target.min){
        var i = 0;
        //↓ NENGOは[{title:年号, since:開始年}+]構造の配列。
        while(NENGO[i].since > event.target.valueAsNumber){
            i++;
        }
        event.target.min = NENGO[i].since-1;
    }
}
```
# 新年号への対応
上記コードのコメント欄にもあるように，CalcAgeでは年号を`{title:年号, since:開始年}`の配列の形で持っています。
なので，新しい元号が分かった時点で配列に`{title:"元気モリモリご飯パワー(仮)", since:2019}`を加筆すれば良いだけなのですが，もし今年の４月ごろに忙しかったりすると対応が後回しになりそうです（所詮は自分用ツールなので…）。
と思ったら，どうやら新元号のUnicode予約文字であるU+32FFを`normalize("NFKD")`すれば，新しい元号の文字列を得ることができるみたいです。
→参考文献：[平成の次の新元号の文字列を取得するコード via にせねこメモ](https://nixeneko.hatenablog.com/entry/2018/04/01/000000)
なので，「もしOS側が新元号のU+32FFに対応したら，元号のリストに新元号を書き足す」という処理をすることにしました。動作テストしてないけどたぶん大丈夫なはず…。

```javascript
const NENGO = [
    {title:"平成", since:1989},
    {title:"昭和", since:1926},
    {title:"大正", since:1912},
    {title:"明治", since:1868}
];
if("\u32FF".normalize("NFKD")!="\u32FF"){ //新年号導入後
    NENGO.shift({title:"\u32FF".normalize("NFKD"), since:2019});
}
```

<details><summary>2019-06-17追記：MacOSX 10.14.5では意図どおりに動作せず&#x1F626;</summary>
MacOSX 10.14.5は新元号令和に対応し，U+32FFに「&#x32ff;」(令和の合字）が追加されたのですが，normalize("NFKD")しても合字のままのようです。
`"\u32FF".normalize("NFKD"); //->not "令和" but "㋿".`
![スクリーンショット 2019-06-17 10.37.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192970/cd542821-dade-1fad-46d2-2bfd9ccfe99b.png)
</details>

余談ですが，JavaScriptはconstで定義した配列であっても配列の中身は変更できます。
# 起動時のデフォルト値の変更（出生年を20年前に）
従来，出生年は固定値にしていましたが，現在の20年前の年とすることにしました。
これは，（今のところ）成人年齢が20歳とされているため，「現時点で成人か否か」を判断する際には操作を不要とする狙いです。

# 余談：CalcAgeのUIデザイン
年月日(Date）の比較ではなく，２つの「年」だけを比較することにし，「その年の誕生日前か後か」の判定はユーザーの脳内で行うことにしています。
年月日を入力するのは手間が多く，脳内判定の方が簡易迅速だからです。

背景画像が年輪っぽいのは，年齢をカウントするというwidgetの機能と，"年輪"がスライド操作の際に目印感があるためです。
October CMS プラグイン実装テク：コンポーネントからなるべく早くリダイレクトをかける

リダイレクトするのは早いほうがいい。コンポーネントの処理が終わってからリダイレクトするのと処理前にリダイレクトするのでは、場合によってはレスポンス時間にエライ違いがでる。

## TLTR
結論から言うと、コンポーネントの`init`で`cms.page.init`イベントをフックして、Redirectファサードのtoメソッドを使ってRedirectResponseオブジェクトを返してやればいい。

```php
public function init()
{
    Event::listen('cms.page.init', function () {
        if ( $component->needRedirect() ) {
            return Redirect::to('/path/to/redirect');
        }
    });
}
```

## 詳細
通常、コンポーネントからリダイレクトするには `onRun` で[RedirectResponse][ref1]オブジェクトを返す。

[ref1]: https://laravel.com/api/5.5/Illuminate/Http/RedirectResponse.html

しかし、他にもコンポーネントがたくさん読み込まれていると最悪、多くのコンポーネントの `onRun` が処理されたあとにリダイレクトになる。場合によっては、無駄な処理のためにリダイレクトが遅くなる。

なので、できればコンポーネントの `onRun`が実行される前にリダイレクトしたい。

コンポーネントの他のタイミングと言えば `init` だが、このメソッドの呼び出し元である`\Cms\Classes\Controller::initComponents`は`init`の返り値を期待していない。

どこでRedirectResponseオブジェクトを返せばリダイレクトしてもらえるか、この[Controller][ref2]クラスを見てみる。

[ref2]:https://github.com/octobercms/october/blob/master/modules/cms/classes/Controller.php

コンポーネントからリダイレクトをかける話なので、最低限コンポーネントが初期化されている必要がある。ということで、コンポーネント初期化から後の処理をかいつまんで並べると下記のようになっている

1. コンポーネント `init`
2. レイアウト `onInit`
3. ページ `onInit`
4. `cms.page.init` イベント発火
5. Ajaxハンドラ実行
5. `cms.page.start` イベント発火
6. レイアウトコンポーネント `onRun`
7. ページコンポーネント `onRun`

ここでコンポーネントが直接絡むのがコンポーネントの`init`と`onRun`だが、イベントをフックするという手もあることがわかる。

`cms.page.init` イベント発火部分をみるとコメントに「カスタムレスポンスを返す機会を提供する」と書かれてる。

```php
/**
 * @event cms.page.init
 * Provides an opportunity to return a custom response ...
 */
if ($event = $this->fireSystemEvent('cms.page.init', [$page])) {
    return $event;
}
```

このイベントをフックしてリダイレクトするには下記のようになる。
`Redirect`ファサードの`to`メソッドを使ってRedirectResponseオブジェクトを返してやればいい。

```php
Event::listen('cms.page.init', function () {
    if ( $component->needRedirect() ) {
        return Redirect::to('/path/to/redirect');
    }
});
```

[Octoberドキュメント][ref3]には「イベントフックは`Plugin::boot`に記述するのが一般的」と書かれているが、コンポーネントの`init`がイベント発火よりも前に実行されているので、コンポーネントの`init`に`Event::listen`を記述しても問題ない。この方が、コンポーネントに実装をまとめられてきれいになる。また、このコンポーネントが使用されていないときもlistenしてしまうのを自然に避けられる。

[ref3]:https://octobercms.com/docs/services/events#event-registration

ということで、コンポーネントの`init`で下記のようにすることで、どのコンポーネントの`onRun`が走るよりも前に、コンポーネントの機能を使いつつ、リダイレクトをかけることができる。

```php
public function init()
{
    Event::listen('cms.page.init', function () {
        if ( $component->needRedirect() ) {
            return Redirect::to('/path/to/redirect');
        }
    });
}
```

## 参考
イベントのドキュメント
https://octobercms.com/docs/api/cms/page/init
（すべてが載っているとは限らないので、ソースコードを検索するのをお勧めする。）
lddで依存しているライブラリの一覧を得たい

Dockerでコンテナを作ってる時に、あるプログラムが依存しているライブラリってどれだっけ？となって書いたもの。

ただ`ldd`を使うだけなのでリンク時に解決したライブラリしか見えません。
つまり実行時にdlopenで読むようなライブラリまではわかりません。例えばglibcのnssのようにファイルに書いてある内容によって読むライブラリを決定するようなものとかです。

RHEL 7 で確認。芋づる式に実行して最後に`sort | uniq`で重複を消すだけ。

``` bash:deps.sh
#!/bin/bash

# usage) bash deps.sh /usr/bin/executable-file

function deps(){
  local file=$1
  ldd "$file" | awk '{print $3}' | while read line; do
    if [ "$line" = "" ]; then
      continue
    fi
    echo "$line"
    deps "$line"
  done
}

deps "$1" | sort | uniq
```
ダートグレード競走のスケジュール一覧をiCalendar形式にする

# はじめに

皆さん、競馬、楽しんでますか?(笑)

JRAが重賞スケジュールをiCalendar形式で公開してくれている、という話は[こちらの記事](https://qiita.com/masaminh/items/f2c62af0f132768d29dd)にも書きましたが、NAR(地方競馬全国協会)の方でも[交流重賞のスケジュールを公開してくれている](http://www.keiba.go.jp/dirtrace/schedule.html)…ものの残念ながら通常のwebページでの情報公開でそのままではGoogleカレンダー等には取り込むことができません。

そこで公開していただいている情報をもとにiCalendar形式ファイルを生成するプログラムを書いてみました。

※昨年、自分のブログの方で[公開](https://masaminh.oumanoshasin.com/post-795/)していましたが、2018年専用になっていたため、修正の上、こちらに掲載させていただきます。

# 動作確認環境

以下で動作確認しています。

- Python 3.7.2
- beautifulsoup4 4.7.0
- icalendar 4.0.3
- requests 2.21.0

# 実装

早速ですが、こんな感じに実装しました。
ソースは[GitHub](https://github.com/masaminh/dirtschedule2ics)においてあります。

こちらの記事には何箇所か抜粋して記載します。

## メイン関数

序盤はargparseを使った引数処理なので省略。

```python:dirtschedule2ics.py
    ical = Calendar()
    for race in get_racelist(response.content):
        ical.add_component(race2event(race))

    args.output.write(ical.to_ical().decode('utf-8'))
```

icalendar.Calendarのインスタンスに、race2event(後述)で作成したicalendar.Eventのインスタンスをadd_componentで追加、という動きです。
あとは、Calendar.to_ical()はバイト列を返すので文字列にして出力…という流れです。

## get_racelist、get_race

```python:dirtschedule2ics.py
def get_racelist(html):
    """レース情報のリストの取得."""
    soup = BeautifulSoup(html, 'html.parser')
    race = soup.findAll('li', class_='race')
    year_line = soup.h3.string
    match = re.fullmatch(r'レース一覧（(\d{4})年）', year_line)
    year = int(match.group(1))

    return [x for x in (get_race(x, year) for x in race)
            if not x.course.startswith('JRA')]


def get_race(race, year):
    """レース情報の取得."""
    grade_code = race.get('class')[1]
    grade_table = {'jpn1': 'JpnⅠ', 'jpn2': 'JpnⅡ', 'jpn3': 'JpnⅢ',
                   'g1': 'GⅠ', 'g2': 'GⅡ', 'g3': 'GⅢ', 'jpn1Central': 'JpnⅠ',
                   'g1Local': 'GⅠ'}
    grade = grade_table[grade_code]
    date_string = race.find('p', class_='date').string
    date_match = re.fullmatch(r'(\d{1,2})/(\d{1,2})（.+）', date_string)
    date = datetime(year, int(date_match.group(1)), int(date_match.group(2)))
    name = race.find('p', class_='name').string
    course = race.find('p', class_='course').string.split()[0] + '競馬場'

    Race = namedtuple('Race', ['grade', 'date', 'name', 'course'])

    return Race(grade, date, name, course)
```

BeautifulSoupと正規表現を使った泥臭い処理で1レースずつのレースの情報を切り出す、ということを行っています。
get_raceの最後でnamedtupleを返していますが、今回はPython 3.7系なので、dataclassを使う方がよかったかもしれません。
なお、この予定表にはJRAのダート重賞も含まれており、そのまま使ってしまうと、JRA公開の重賞予定と重複してしまうので、JRAのレースは除外するようにしています。

## race2event

```python:dirtschedule2ics.py
def race2event(race):
    """レース情報をiCalendarのイベントに変換する."""
    event = Event()
    event.add('SUMMARY', race.name + '(' + race.grade + ')')
    event.add('DTSTART', vDate(race.date))
    event.add('DTEND', vDate(race.date))
    event.add('LOCATION', race.course)
    event.add('TRANSP', 'TRANSPARENT')
    return event
```

1つずつのレース情報をiCalendarのEVENTに変換。SUMMARYの文字列がカレンダーでの予定の件名、DTSTARTとDTENDで予定の開始終了、LOCATIONの文字列で場所を表現できます。
[こちらの記事](https://qiita.com/masaminh/items/f2c62af0f132768d29dd)で書いたように、「予定なし」として取り込むため、TRANSPをTRANSPARENTにしています。

# 最後に
競馬もコンピュータを使って快適に楽しみましょう！(笑)
SourceTreeでbitbucketのパスワード要求が頻発する

# 目的
macでSourceTreeを導入してインストール時の要求に従ってbitbucketと連携した。
しかしclone/pull/pushのたびにパスワードを要求されて煩わしいので何とかしたい

# 原因
調べてみたところBasic認証を使っているのが原因のようだ。
<img width="676" alt="68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3138313337352f66636338323662362d356631642d306566372d396439652d3064653365306562316636302e706e67.png" src="https://qiita-image-store.s3.amazonaws.com/0/181375/da23329d-e2a6-0dd8-75e5-9fd3a52e11d1.png">


# 対策
sshの公開鍵をSourceTreeで生成してbitbucketに登録して、SourceTree上でアカウントをsshとして登録する。
まずSourceTree上でssh keyを生成する。
設定メニューのアカウントから認証方法をOAuthにしてプロトコルをsshにしてkeyを生成する
<img width="681" alt="スクリーンショット 2019-01-04 10.45.11.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/181375/acca8745-08ab-aa6a-a9d7-e7bc999db700.jpeg">

生成したkeyをbitbucketのアカウント設定上のOAuth認証に登録する

## ssh key登録
<img width="188" alt="スクリーンショット 2019-01-04 11.01.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/181375/176ac622-cf81-0848-17fd-88cfb17e8b72.png">
<img width="805" alt="スクリーンショット 2019-01-04 11.01.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/181375/10f1ef51-72f5-19e6-9090-def98f845052.png">

## OAuth 設定
特に必要なし。
SourceTreeでアカウント登録する際にbitbucketへ認証のためブラウザが立ち上がるので接続すればOK


参考サイト
https://www.granfairs.com/blog/cto/set-ssh-to-backlog
https://www.granfairs.com/blog/staff/sourcetree-ssh

# 結果
SourceTree上でリモートタブからリポジトリ一覧の取得が「Could not authorize request with the available token. Please re-authenticate.」
というメッセージが表示されてアクセスできない。
試しに、個別にリポジトリをURL指定「git@********.git」でcloneを試みたらできた。push/pullも問題なくできているのでSourceTreeのバグなのかも

今回のパスワード入力を毎回要求されることはこれでなくなったので一旦調査終了。

* 追記
 OAuth認証ではなくBasic認証でもパスワード入力を要求されることはなかったのでBasic認証に変更
TypeScript備忘録

# 型定義

TypeScript備忘録。
ハマったところなどを残していく。
整理とかはする予定なし。

## オブジェクトの配列


```ts
const users: Array<{
  id: number;
  name: string;
  age: number;
}> = []
```

## 連想配列

```ts
const users: { [id: number]: string } = {}
```
草野球の三振率を計算する

三振率は 三振数÷打席数で計算できる。

```:コード:php
<?php

// 三振数
$so=20;
// 打席数
$tpa = 30;

$so_rate = $so / $tpa;

echo "三振率は" . $so_rate . "\n";

```

```:実行結果
$ php so.php
三振率は0.66666666666667
$
```
MacOS でBitnamiツールを自動起動

#Bitnami Wordpressを自動起動する

#参考文献
SkyGliderさんのページ　http://d.hatena.ne.jp/skyglider/20110226/1298737664

###Automatorとログイン項目を使用した方法です。
シェルスクリプト全般に応用可能。

##Automatorアプリの作成
1. Automator.appを起動
1. 「アプリケーション」を選択
1. アクションの「シェルスクリプトを実行」をドラッグ
1. 起動コマンドを入力 → /（インストールディレクトリ）/ctlscript.sh start
1. 任意の場所に保存

##自動起動化の設定(ログイン項目に登録)
1. 「システム環境設定＞アカウント＞ログイン項目」を開く
1. １．で作ったアプリケーションを追加
Python3でTypeError: must be str, not {型}となったときの対応方法

- 環境
    - OS : macOS Mojave バージョン10.14.2
    - Python : 3.6.5

# 事象 : Pythonに `TypeError: must be str, not list` と怒られた

```python:sys.py
import sys

print('Path : ' + sys.path)
print('Version : ' + sys.version)
```

```bash
$ python3 sys.py 
Traceback (most recent call last):
  File "sys.py", line 3, in <module>
    print('Path : ' + sys.path)
TypeError: must be str, not list
```

# 原因 : 文字でないものを文字で扱おうとするから
```bash
$ python3
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 03:03:55) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(type(sys.path))
<class 'list'>
# ↑'str'ではなく'list'です
```

## 対応 : 文字にしてから扱う
```python:sys.py
import sys

sys_path = str(sys.path)
print('Path : ' + sys_path)
print('Version : ' + sys.version)
```

```bash
$ python3 sys.py 
Path : ['/Users/mana/Dropbox/ApacheDcumentRoot', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']
Version : 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 03:03:55) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
```
note 使い始めようとおもったけど はてなブログやMediumに比べてインターフェイスの細部が‥

note 使い始めようとおもったけど はてなブログやMediumに比べてインターフェイスの細部が‥

# note

HTMLからのコピーで箇条書きのリスト情報とかすべて抜けてしまう

![image](https://user-images.githubusercontent.com/13635059/50720390-d3e8fa80-10ef-11e9-849c-8490c3964216.png)

# Medium

1コピペで全部流用できる

![image](https://user-images.githubusercontent.com/13635059/50720394-e95e2480-10ef-11e9-9c9d-af658c79c2cd.png)

# はてなブログ

- 1アクションコピペはできないけどもとがMarkDownならそのまま使える
- 「見たままモード」でのHTMLコピーは画像が抜け落ちてしまうので無理

![image](https://user-images.githubusercontent.com/13635059/50720400-085cb680-10f0-11e9-9512-544ae4e52af5.png)


# 結論

- 情報の移植性が悪い
- 他サービスと併用するユーザーは稀だろうけれど
- ユーザー情報資産へのセンシティブさがここに現れる気がする

---

https://twitter.com/yumainaura

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










<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
macOS Mojaveのクリーンインストール用USBメモリを作る

# 年末年始の道具のメンテナンス
毎年恒例で年明けの正月休み辺りでPC類のメンテナンスをしています。
今回はmacOSのクリーンインストールから行いますが、少し気になったものがありましたのでメモします。

# スッキリきれいに中身をクリア
最近のmacOSはアップデートインストールでも充分の様ですが、仕事のゴミが溜まってしまったMacの中身を大掃除する意味でも、OSクリーンインストールをしておきたいです。

# インストールメディアの作成
Macの「Application」フォルダに「macOS Mojave.app」があることが前提です。
※日本語環境では「macOS Mojaveインストール.app」と表示されます。
※macOS Mojave.appのダウンロードについては割愛します。

10GB程度のUSBメモリを用意します。
※容量については後述。

このUSBメモリに「usb」などの適当な名前をつけておきます。

## ターミナルコマンドの実行
ターミナルクライアントはiTerm 2を使用しています。

```ruby:
sudo /Applications/Install\ macOS\ Mojave.app/Contents/Resources/createinstallmedia --volume /Volumes/usb --nointeraction --downloadassets
```

上記を実行すると下記のような画面が表示されます。

```ruby:
[ユーザー環境]$ sudo /Applications/Install\ macOS\ Mojave.app/Contents/Resources/createinstallmedia --volume /Volumes/usb --nointeraction --downloadassets
Password:
Erasing disk: 0%... 10%... 20%... 30%... 100%
Finding assets to download...
Downloading assets: 0%... 10%... 20%... 30%... 40%... 50%... 60%... 70%... 80%... 90%...
Copying to disk: 0%... 10%... 20%... 30%... 40%... 50%... 60%... 70%... 80%... 90%... 100%
Making disk bootable...
Copying boot files...
Install media now available at "/Volumes/Install macOS Mojave"
[ユーザー環境]$
```
「Install media now available at "/Volumes/Install macOS Mojave"」と表示されたら完了です。

## USBの容量について
Mojaveから追加された機能とのことですが、インストール時の追加コンポーネントなどを予めダウンロードしておきインストールを高速化することができるようです。
上記コマンドの「--downloadassets」というオプションを指定することで、予めダウンロードされます。
Mojave自体が6GB程度あり、追加コンポーネントの容量は未確認ですが最大でも1GB程度と推測されます。
10GBもあれば充分と考えました。

## 参考にしたサイト
macOS Mojaveのインストール用USBメディアを作成する方法 - 正式版編
https://www.softantenna.com/wp/tips/mac-os-mojave-usb-install-media/

以上です。