OmniAICreator/Qiita-1.07M huggingface dataset:
Linux kernel debug用のプロセス一覧出力gdbコマンド

# 概要
[LinuxKernel勉強会](https://linux-kernel.connpass.com/event/87223/)のもくもくタイムに、プロセスの一覧を取得するgdbコマンドを書いた。
せっかくなので忘れないうちにqiitaに上げておく。

# 調査
Kernel内で全プロセスに対して処理を行う場合、
[`for_each_process`](https://elixir.bootlin.com/linux/latest/ident/for_each_process)マクロ関数を使うようなので、その実装を確認。

```
#define next_task(p) \
	list_entry_rcu((p)->tasks.next, struct task_struct, tasks)

#define for_each_process(p) \
	for (p = &init_task ; (p = next_task(p)) != &init_task ; )
```

上記から、`init_task`はグローバル変数として参照できることと、[`struct task_struct`](https://elixir.bootlin.com/linux/latest/ident/task_struct)がもつ`tasks list_head`メンバをたどっていくことで全タスクを参照できそうなことがわかる。
※はじめ名前から勝手に`children list_head`メンバを辿ろうとして迷子になりかけた汗

ということで、それをgdbコマンドとして定義してみた。

# gdbコマンド（gdbスクリプト版）


```
define ktasks
  set $offset = (long)&init_task.tasks - (long)&init_task
  set $task = &init_task
  printf "  PID COMM\n"
  while 1
    printf "%5d %s\n", $task->pid, $task->comm
    set $task = (struct task_struct *)((long)$task->tasks.next - $offset)
    if $task == &init_task
      loop_break
    end
  end
end
document ktasks
Show kernel task list.
end
```

出力はこんな感じ。

```
(gdb) ktasks
  PID COMM
    0 swapper/0
    1 init
    2 kthreadd
    3 ksoftirqd/0
   (中略)
   92 sh
   93 kworker/u2:1
```

中身は[`for_each_process`](https://elixir.bootlin.com/linux/latest/ident/for_each_process)マクロ関数をそのままgdbスクリプトにしただけ。

強いてポイントを挙げるとすれば、

- `list_head`から元の構造体のアドレスを算出するために`offset`を求めている
- その`offset`を使って構造体のアドレスを算出するときに、純粋なアドレスの演算にするためにlongにキャストしてる（キャストしないと「list_headのサイズ」×`offset`だけ戻してしまう）
ぐらいかな。

# gdbコマンド（python版）

もくもくで書いたのはgdbスクリプト版だったけど、もしかしたら読みやすくなるかもという期待と復習を兼ねてpython版も作ってみた。
それがこちら。

```python
import gdb

class InfoKtasks(gdb.Command):
  """Show kernel task list."""

  def __init__(self):
    super(InfoKtasks, self).__init__("info ktasks", gdb.COMMAND_STATUS)

  def invoke(self, arg, from_tty):
    t_long = gdb.lookup_type("long")
    t_task = gdb.lookup_type("struct task_struct")
    init = gdb.parse_and_eval("init_task")
    offset = init["tasks"].address.cast(t_long) - init.address.cast(t_long)
    task = init.address
    print("{0:>5} {1:}".format("PID", "COMM"))
    while True:
      print("{0:>5} {1:}".format(str(task["pid"]),
                                 task["comm"].string()))
      task = (task["tasks"]["next"].cast(t_long) - offset).cast(t_task.pointer())
      if task == init.address:
        break

InfoKtasks()
```

※出力はgdbスクリプトと変わらないので略。

うーん。。。
なんとなくかっちょよくなったような厨二的満足感は得られるものの、読みやすくなったかというと微妙。

- いちいち`gdb.Type`とか`gdb.Value`とかを`gdb`モジュールを使って取得しないといけないのが煩わしい
- アドレス取得・キャスト・構造体のメンバ参照などのシンタックスが当然Cと全然違うので、頭の中で１ステップ変換を挟まないといけない
- 今回のようにベタベタに特定のシンボルの値を出力するコマンドの場合、素直にgdbスクリプトを使った方が筋が良さそう。文字操作や複雑なロジックを表現するpythonで書くメリットが出てくると思うが。


# 感想
- ぼけーっとコード読んでるとなかなか頭に入らないけど、動かしつつデータを解釈するコマンドを作ってると理解が進む（気がする）。
- qiitaにgdbスクリプトモードがなかった。。。ｼｮﾎﾞｰﾝ(´･ω･`)


# リンク
[github](https://github.com/takeoverjp/kernel-debug)
UE4を使ってWindowsのみでARKitサンプル動かすまでの歩み

少し古い話にはなりますが去年の年末にUE4でARアプリを作ってみようと思い立ち、
やってみたはいいけどiPhoneで動くまでに紆余曲折ありました。

どうにか解決して動作確認まで行けましたので、メモ代わりに残します。
似たような事で困っている人の助けになれば幸いです。

あと初投稿ということもあり見た目がアレです。良くないかもです。

**検証した環境**
Windows 10 Home
Unreal Engine 4.18.3
iPhone 8 Plus (iOS 11.3.1)

**事前の準備**
Appleへのお布施こと、Apple Developer Programへの登録。
iTunesのインストール。UDIDの確認のため。
Unreal Engine 4のインストール。


##１．ARKitサンプルをゲット
今回はMacを使わず（持ってないだけ。。）WindowsのみでiOSアプリを作るわけですが。。
そう！Macなくても作れるんです！そう！！Unreal Engine 4ならね！！

詳しくはこちら。EGJのおかず(@pafuhana1213 )さんのスライド
https://www.slideshare.net/EpicGamesJapan/ue4ar-ver-100


というわけで公式ドキュメントを見ながらARアプリのサンプルを作ろうと思っていたわけですが、
早速に公式の言う通りやると上手くいかない罠に引っ掛かり、数日はまりました。
色々とあるのですが今回は最終的に何とかなったので、追々説明します。

まず公式のARKitサンプルはMacがないと動きません。Remote Buildeが必要になります。
そこでTsyoshi MAEHANA(@sandinist )さんの作成されたサンプルを使わせて頂きました。

https://github.com/sandinist/ue4.18.0_arkit_sample

ここにあるプロジェクトを使って事を進めます。
ダウンロードして、プロジェクトを開いておきます。


##２．デプロイへの道のり
そもそもこれで罠ってました。。長い間。。
一度は真剣にMac買った方が早えと購入を検討するほどに。。

てんちょー(@shop_0761 )さんのブログを見ながら進めていました。
http://shop-0761.hatenablog.com/entry/2017/11/10/142525

そして、はじめは下記の公式ドキュメントの通りやってました。
http://api.unrealengine.com/JPN/Platforms/iOS/QuickStart/index.html

結論から言えば、この通りやってもダメだったわけですが、間違いでもないので
初めてiOSアプリを作られる際にはご一読ください。以降は目を通している前提で進めます。

では順を追って、僕の環境でうまくいった手順を記載します。
細かいところは公式ドキュメントで確認しながら進めてください。

1. IPhonePackagerを使って、証明書（CER）を得るための申請書（CSR）と認証キー（KEY）を作ります。
2. Apple Developer Centerにサインインして、申請書（CSR）を提出し、証明書（CER）を取得します。
3. 続けて使用するデバイスを登録します。UDIDが必要になります。iTunesを使って確認しましょう。
4. 続けてApp IDを作成します。「App ID Suffix」の設定は「Explicit App ID」にしてください。
   公式ではワイルドカードのIDを取得するよう書かれていますが、僕はこれでデプロイに成功した試しがありません。
   Macがあればそうでもないのかもしれませんが。。ぬぎぎ。。
5. 続けてプロビジョニングプロファイルを作ります。作ったプロビジョニングはダウンロードしておきます。
6. Unreal Editorを使って、プロジェクト設定からプロビジョニングをインポートします。
7. 続けて証明書（CER）をインポートします。
8. 続けてバンドルIDを設定します。
9. インポートしたプロビジョニングのStatusがValidになっていれば成功です。

と、ここまでまとめて気が付いたのですが、公式ドキュメント更新されてるみたいですね。
手順６～７は以前はIPhonePackagerを使っていたのですが、これがまた罠で。。使うとうまくいかない。。

当時は手順９でStatusがValidにならず、何度かやり直しもしたのですがダメで。。
でも数週間後にプロジェクトを開いたら、何故かValidになっていました。なぜだ。。


##３．まとめ
Windows縛りでやる上で重要と思われるのは、App IDのタイプですかね。。
どの資料見てもワイルドカードなわけですが、うまくいかない。デプロイできない。。
しかもエラー内容がバンドルIDが見つからない系。。
試しにワイルドカードやめてみたら、デプロイできました。ぬぎぎ。

少々納得がいかないところもあったのですが、やりたい事は出来てはいるので
今は気にしないようにして作業を進めています。今は仕事でもないし気楽にいきたい。。

情報が少し古いので、4.19以降で改善されているといいなぁとか淡い
期待を持ちつつ、お開きとさせて頂きます。
dotfilesを簡単に管理するシェルスクリプト

# TL;DR
* ``dotfiles``を簡単に管理するための雛形(dotLINKS)を作った
* https://github.com/zeriyoshi/dotLINKS
* 使用例 : https://github.com/zeriyoshi/dotLINKS_zeriyoshi

# dotfiles
Unix系OSの設定ファイルは``$HOME``以下に``.``(ドット)から始まるファイル名をつけて保存される場合が多く，これらのファイルは``dotfiles``と呼ばれたりしています。
例)``.vimrc`` ``.screenrc``, ``.ssh``

``dotfiles``はあくまでもただのファイルなので，``git``とシェルスクリプトなどを組み合わせてシンボリックリンクを作成することで様々な環境に設定を持ち運ぶことができます。

* [dotfilesを管理しよう](https://qiita.com/massy22/items/5bdb97f8d6e93517f916)

しかしいざ``dotfiles``フローを作ろうとしても専用にシェルスクリプトを書かなければならなかったり，書いたシェルスクリプトが特定のシェルに依存していて動かなかったりなど結構問題が発生するものです。

ということで``dotfiles``を管理する為の雛形的なものを作ってみました。

# dotLINKS
[dotLINKS](https://github.com/zeriyoshi/dotLINKS)は``dotfiles``をより簡単に管理するための雛形となるシェルスクリプトです。

可能な限り``POSIX``標準に準拠するよう書かれており，Unix系のシステム，かつ``Bourne Shell``系のシェル(bash, zsh等)であれば(多分)使用することができます。

## 使い方

### 初期設定

``git``を用いてリポジトリをクローンします。

```sh
$ git clone https://github.com/zeriyoshi/dotLINKS
```

クローンしてきたディレクトリに移動し，``./dotlinks.sh init``を実行します。

設定するリモートリポジトリのURLを聞かれるので，GitHubなどで作成した自分用の``dotfiles``リポジトリのアドレスを指定します。

```sh
$ ./dotlinks.sh init
  Checking git installed status...OK
  Your dotLINKS remote repository : ここ
```

次に``home``以下に必要な``dotfiles``をコピーまたは作成してください。

``.ssh``などのディレクトリになっているものもそのままコピーするだけでOKです。

一通り作成したら``./dotlinks.sh link``を実行することでシンボリックリンクが作成されます。

特に問題なさそうなら``git add home``したあと``git commit``して``git push -u origin master``してあげれば完了です。

### 別の環境で使用する

``dotfiles``を使用したい環境で初期設定で設定したリモートリポジトリを``clone``した後，``./dotlinks.sh link``するだけで完了です。

### シンボリックリンクを削除する

シンボリックリンクを削除するには``./dotlinks.sh unlink``を実行してください。不要になったディレクトリがあればそれも自動で削除されます。

### dotLINKSを更新する

``./dotlinks.sh upgrade``を実行することで``dotLINKS``自体を更新することが出来ます。

**自身で``dotlinks.sh``を編集していた場合には使用できません。**手動で``merge``する必要があります。

### 注意点
秘密鍵やSSH接続先など知られてはまずいものをGitHubへ``commit``しないように注意しましょう。

### その他
``./dotlinks.sh usage``または単に``./dotlinks.sh``として実行すると使用可能なコマンドと説明が表示されます。

```sh
dotLINKS version 0.0.4 (https://github.com/zeriyoshi/dotLINKS)

Usage:
 ./dotlinks.sh [command]

Commands:
 init                 Initialize dotLINKS.
 link                 Link symbolic links.
 unlink               Unlink symbolic links.
 upgrade              Upgrade dotLINKS.
 version              Show version.
 usage                Show usage.
```

# 参考
シェルスクリプト上にもコメントで記載しておりますが，``dotLINKS``を作成する上で次の記事を参考にさせて頂きました。この場にてお礼させていただきます。

* [実行中のシェルスクリプトのパスの取得](https://qiita.com/komeda-shinji/items/67081ef81e79281b2c7b)
* [シェルスクリプトを自己文章化する](https://qiita.com/suttang/items/d4b4474e93c8e74ae515)
vim8.1.1 カラースキームの簡易適用手順

vimのupdate（8.1.1）が原因なのか現状不明だけど
`dein`を利用して適用していたvimのカラースキームが**読み込まれなくなっていた**ので
取り急ぎカラースキームを反映させる応急処置の作業メモ

# 参考
>
[vimのカラースキーム (colorscheme) を "molokai" に設定する](https://qiita.com/godgarden/items/9bded65665834438cc3e)

# vimのカラースキーム適用作業

自分の場合は
[`lucius`](https://github.com/jonathanfilip/vim-lucius)のカラースキームを適用させたいので。。。

（他のカラースキームでも、`GitHubのURL`と`カラースキーム名`を置換えればなんでも対応可能かと）

※ vimにデフォルトで添付されている物に関しては**git clone の必要はない**です。
`.vimrc`内に`colorscheme 名称`の1行を設定するだけで適用されるかと。
>[vimエディタにデフォルトで添付しているカラースキーム](http://nanasi.jp/colorscheme/default_install.html)

```zsh:ディレクトリ準備(.vimとcolors)
cd ~/.vim
mkdir colors

#.vim が存在しなければ作成
#mkdir -p ~/.vim/colors
#cd ~/.vim

pwd
#/Users/ユーザ名/.vim
```
```zsh:githubから設定ファイルを取得
#gitから最新のみ複製
git clone --depth 1 https://github.com/jonathanfilip/vim-lucius
#ファイル移動
mv vim-lucius/colors/lucius.vim ~/.vim/colors/

vim ~/.vimrc
```
`.vimrc`内の最初に下記1行を追記。（**先頭行でないと反映出来なかった**。。。）

```zsh:~/.vimrc
colorscheme lucius
```
```vim:~/.vimrc
"必要に応じて色種類の設定
set background=dark
let g:ligthline = { 'colorscheme': 'lucius' }
```

保存して閉じ（**:wq**）、再度vimで開いて反映されてるか確認

```zsh
vim ~/.vimrc
```

とりあえずこれでカラースキームは
読み込めた。。。
knowledgeのデータベースをPostgreSQLに変更する

# 概要
Ubuntu16.4にインストールしたknowledgeのデータベースをPostgreSQLに変更する。

前回の続きである。
https://qiita.com/mokrai/items/41728f2474ae1d9b5547

# ベース
下記の手順がベースになる。
https://information-knowledge.support-project.org/postgresql-ja

# 手順
## PostgreSQLインストール
 * apt installで適当に
 * pg_hba.confの設定をする。

```
# Tomcatと同じサーバで動かすなら下記のエントリだけあればいいはず
host    all             all             127.0.0.1/32            trust
```

## PostgreSQLのユーザとデータベース作成

```
$ sudo su - postgres
$ createuser appuser -d -l -P
$ createdb knowledge -U appuser
```

## JDBCドライバインストール
 * インストールしたJavaとPostgreSQLのバージョンにあわせたものをダウンロードする
    * https://jdbc.postgresql.org/download.html
 * ここに移す
    * /usr/share/java/

## JDBCドライバのクラスパスを通す
 * たぶん、`/opt/tomcat8/bin/setclasspath.sh`に追記する

```
# ファイル名は実際のものと合わせる
CLASSPATH=$CLASSPATH:/usr/share/java/postgresql-9.3-1103.jdbc3.jar
``` 

### メモ
追加しなくても（むしろjarを置かなくても）、PostgreSQLに接続することはできた。warの中にPostgreSQLのJDBCドライバらしきものが含まれていたので、それが使われているのかもしれない。

## 実際の接続先を変更する
 * ブラウザから管理者ユーザでログインし、システム設定あたりから、データベースの変更を行う
 * 入れる情報は下記。ユーザにパスワードを設定していなかったら入力しなくていい。スキーマも同様。

```
user: knowuser
password:
schema:
```

### メモ
「org.postgresql.Driver(9.3-1103-jdbc41)」が自動で選択されている。（変更不可）
これがwarに含まれているやつかも。そうなると、PostgreSQLのバージョンも9.3にしたほうがいいのかもしれない。


## 確認
てきとうに記事など登録して、データベースに接続してみればいい？
今回は、commentテーブルがすぐ見つかったので、それを見た。


# 参考
https://qiita.com/htakeda/items/b4247144cb51edeaedec
MCP 70-532 : Microsoft Azure ソリューションの開発

前回の記事（[MCP 70-533 : Microsoft Azure Infrastructure Solutions の実装](https://qiita.com/onooooo/items/3debc6b22ca06b38dc08)）につづいて「MCP 70-532 : Microsoft Azure ソリューションの開発」に先日合格しました。
※2018年5月時点の内容です。

#試験概要
- 150分
- 50問
- 合格ライン 700点/1000点
- ¥21,103 JPY（公式サイト上に記載された価格）

前回同様、[isaオンラインショップ](https://www.isa-onlineshop.net/products/detail.php?product_id=10188)で再受験付きのMicrosoft Azure Exam Packバウチャーを購入しました。

#試験範囲
[公式サイト](https://www.microsoft.com/ja-jp/learning/exam-70-532.aspx)参照。

- Azure Resource Manager仮想マシンの作成と管理（20〜25％）
- ストレージとデータ戦略の設計と実装（25〜30％）
- アイデンティティ、アプリケーション、およびネットワークサービスを管理する（10〜15％）
- Azure Compute, Web, and Mobile Servicesの設計と実装（35-40％）

70-533の受験時と比べて意表を突かれた印象はありませんでした。でもClassicの範囲も出題されたような。。

#結果
734点
やばかったです。所要時間も、70-533のときは1時間ほどでしたが今回は2時間じっくり時間をかけました。率直に言って70-533より難しかったです。そして疲れた・・・

#問題の構成
すでにうろ覚えですが、たしかこんな感じでした。

- 6問〜7問からなるケーススタディが2セット　計13問
- このソリューションは目的を満たすか？という質問にYES/NOで回答する設問が3問×3セット　計9問
- 一般的な選択問題やコードの穴埋め問題　計19問くらい？
- 6問程度からなるケーススタディが2セット　計12問くらい？

全部で53問くらい？

それぞれ次のセクションにすすむと、後戻り・見直し・回答の訂正ができません。さらにYES/NOで答える2択問題は「次へ」を押すともう戻れません。なかなかのプレッシャーです。

#勉強方法
70-533とほぼ同じです。

##[Pluralsight](https://pluralsight.com/)
体系だった知識を学びます。

##[Whizlabs](https://www.whizlabs.com)
前回同様、怪しげな問題集は効果が高いと思われます。

##Azureの公式ドキュメント
70-533のときには気にしなくてよかった「.NETでの実装」を気にする必要があります。[Azure 上の .NET アプリでのストレージの使用に関するチュートリアル](https://docs.microsoft.com/ja-jp/dotnet/azure/dotnet-tutorials-services-storage?view=azure-dotnet)などで.NETのコードに慣れておくのが良いです。

#まとめ
70-533 → 70-532 ときたので、次は 70-535 : Architecting Microsoft Azure Solutions ですね。[Whizlabs](https://www.whizlabs.com)でざっと問題を眺めてみたところ、70-532より「広く浅く」といったかんじでそんなに難しくなさそうな印象。ただし新しめな試験ということもあり、怪しげな問題集がどこまで信用できるか、という問題もあり。
さらに70-535の試験はまだ日本語化されていないため、日本語化を待つか英語で受験するか、悩ましいところです。
爆速で netlify を使いたいなら、 DNS サーバーは netlify Managed DNS を使おう

netlify の爆速の最強さのひとつに、ほっといても CDN がある。とってもお手軽。

この CDN が爆速を支えていると言っても過言ではない（ですよね？）

少しググるとなぜだか、お名前.com のネームサーバーで Aレコードで指定をしていたり、cname で subdomain を指定しているものがあったが、 お手軽お気楽 CDN が使えなくなるのはもったいない。

Beta て書いてあるので、もしかしたら前は使えなかったかも？

## DNS設定
設定は account > DNS zoons に DNS があるので、ネームサーバーは netlify のを使っていく。
https://app.netlify.com/account/dns

ドメインサービスで DNS サーバーを指定をする前に、下記サイト設定画面からカスタムドメインで、yoursite に Domains を指定しておく。
https://app.netlify.com/sites/{{yoursite}}/settings/domain

そうすると、グレーの文字でカスタムドメインが追加される。


僕はムームドメインをつかっていたので、ネームサーバ設定変更 ＞ 取得したドメインで使用する の部分で下記を、ネームサーバを設定。
https://app.netlify.com/account/dns/{{yourdomain}}

```
dns1.p06.nsone.net
dns2.p06.nsone.net
dns3.p06.nsone.net
dns4.p06.nsone.net
```

こちらが正常に設定されると、先程のグレーの文字のカスタムドメインが、緑になりアクティブになります。

あとは netlify がいい感じにやってくれるので、爆速サイトが簡単に手に入ります。

ぜひ、DNS サーバーは netlify Managed DNS を使いましょう！

## おまけ
僕は、サブドメインで heteml サーバー、メールもhetemlサーバーで利用していたので、下記の２つレコードも設定しました

```
Type A
Host: admin.nishida.lol
Value: 157.7.44.179
TTL: 3600
```

```
Type:MX
Host: nishida.lol
Value: mx.hetemail.jp
TTL: 3600
Priority: 10
```

※ heteml はサーバーの契約時期によって、MXレコードが違うので注意です。
https://heteml.jp/support/faq/1602.html
Ubuntu on Windowsビルド速度

#はじめに
Javaやらnode.jsの大き目のプロジェクトを開発していて、開発環境として、WindowsとLinuxどっちがいいのかという話がでました。この中で Ubuntu on Windowsを使うことで、両方のいいところを使えるんじゃないかと提案してみましたが、Ubuntu on Windowsはディスクアクセスが遅く、ビルドが遅いから使うのをためらうという話が出たので実際に計測してみました。比較用にVirtual Box(以下VBox)も用意。

#評価環境
- ビルド対象は Elasticsearch のソース(5/18版）を[github] (https://github.com/elastic/elasticsearch)から。長めのビルドが走るならなんでもよかったので特にElasticsearchであることに意味はありません。
- Javaによるビルドなので、Windows/Linuxどちらもやってることはそんなに変わらないのではないかと考えます。なお、Javaは Oracle Java 10を使用
- ビルド環境は、ホスト CPU 16 Core、 メモリ16GB、 SSD。VBoxは CPU 8Core, メモリ8GBでホストと同一マシン上に構築。
- ビルドコマンドは `gradlew clean assemble` これを各条件につき3回ずつ実行して、実行時間を見る。初回のgradlewはmavenとか色々ダウンロードしてくるので、初回の結果は無視。
- 同一のソースコードに対して、Windowsから直ビルド、Ubuntu on Windowsでビルド、VBoxのUbuntu18でビルドの3パターンを試す
 
# 評価結果その１

|Windows  |Ubuntu on Windows  |Ubuntu on VBox  |
|---|---|---|
|13:08  | 14:14 | 5:36 |
|12:55  | 12:56 | 5:41 |
|13:11 | 12:45|5:36|

単位は　分：秒

## 考察
ここまでやってみて、Windows/Ubuntu on Windowsが妙に遅いことが分かりましたが、ちょっとこの結果に違和感も感じました。そもそもVBoxは今回このためだけに用意したまっさらな環境であるというアドバンテージもあります。

ビルドは細かいファイルが作成・削除・変更が走るのでこういうファイルをいちいち見に行くようなものってことでWindows Defenderのリアルタイムファイル保護を外すことにしました。あまりセキュリティを落とすわけにもいかないので、ビルド用のフォルダだけスキャンの例外にするのがよいでしょう。

### リアルタイムスキャンの除外方法
- https://support.kaspersky.co.jp/common/windows/13341)
- https://121ware.com/qasearch/1007/app/servlet/relatedqa?QID=018507


# 評価結果その2
ビルド用フォルダのリアルタイムスキャンを止めたことで大きく改善したことがわかりました。VBoxは、VBoxのディスクを保存しているフォルダのスキャンを外しましたが改善は見られませんでした、あまり細かくI/Oをフラッシュしていないので影響が少ないのでしょう。

|Windows  |Ubuntu on Windows  |Ubuntu on VBox  |
|---|---|---|
|8:24  |8:35 | 5:37 |
|8:13  | 8:14 | 5:37 |
|8:28 | 8:21|5:38|

単位は　分：秒

#まとめ
- ビルドする分には、Windows直でのビルドも、Ubuntu on Windowsもそんなに速度は変わらなかった。
- リアルタイムスキャンの有無がビルド時間に大きく影響する。git用のフォルダをスキャン例外に登録するなどの対策が有効。
- VBoxでのビルドはホストでのビルドに比べて遜色ない。今回はこの目的のためだけに作ったVMのため余分なツールが入っておらず、むしろホストより早かった。
- VBox上に本格的に開発環境をセットアップしていくことで同程度に近づいていくと予想します。
PyBrainのimport時のエラー「ImportError: cannot import name 'expm2'」の対処法

#原因

原因はscipyで削除されたexpm2をpybrainがインポートしようとしてること
インポートする文をかえてあげるだけで良い

#解決法
<b>C:\Users\Anaconda3\Lib\site-packages\pybrain\toolsにある「functions.py」の
「from scipy.linalg import inv, det, svd, logm, expm2」　→　「from scipy.linalg import inv, det, svd, logm, expm」にしてあげるだけ</b>
GitHubコマンドまとめ

# GitHコマンド備忘録
* `git config --global user.name=""` - ユーザ名の設定
* `git config --global user.email=""` - メールアドレスの設定
* `git config --list` - コンフィグ一覧
* `git init` - リポジトリ初期化
* `git status` - リポジトリ状態確認
* `git add` - git管理するファイルをステージ領域に追加
* `git commit　-m` "コメント" - 記録
    * `git commit --amend` - コメントメッセージを修正 
* `git log` 
    * `git log --oneline` - コミットログを一行で表示
    * `git log --pretty=short` - コミットメッセージを１行目のみ表示
    * `git log -p [ファイル名]` - ファイルの差分を表示
    * `git log --graph` - ブランチを視覚的に表示
    * `git log -n 数値` - 数値分のログを表示
* `git diff` - ワークツリーとステージ領域のコミットの差分確認
    * `git diff HEAD` - ワークツリーと最新コミットの差分確認
* `git branch` - ブランチ一覧
    * -aオプション： リモートリポジトリの情報も表示
* `git checkout ブランチ名
    * `git checkout -b ブランチ名` - ブランチ作成
    * `git checkout -` - 1つ前のブランチへ切り替え
    * `git checkout [ファイル名]` - ワーキングディレクトリの変更を打ち消す★
    * `git checkout -b ブランチ origin/ブランチ` リモートブランチをチェックアウト
* `git merge ブランチ名` - 現在のブランチに、指定したブランチをマージ
    * `git merge --no-ff ブランチ名`
    * `git add コンフリクトファイル` - コンフリクト解消後
    * `git commit -m "コメント"` - コミット
＊ `git reset` - ブランチを戻す
    * `git reset --hard ハッシュ値` - ブランチを分岐前に戻す
＊ 歴史を押しつぶして修正
    ＊ `git rebase -i　DEAD^2`
* `git commit` - コミット
    * `git commit --ament` - コミットメッセージを修正
* `git rebase -i` - 歴史を押し潰して改修
    * `git rebase -i HEAD~2` - HEADERの２つまでの歴史を改修
        * Commands:
            * p, pick = use commit
            * r, reword = use commit, but edit the commit message
            * e, edit = use commit, but stop for amending
            * s, squash = use commit, but meld into previous commit
            * f, fixup = like "squash", but discard this commit's log message
            * x, exec = run command (the rest of the line) using shell
* `git log --graph`
* `git remote add origin` リモートリポジトリ登録
* `git push -u origin master` リモートリポジトリのmasterに反映
    * -uオプションは、ローカルブランチのupstreamをorigin masterに関連付けるという意味
* `git clone リポジトリのブランチURL` リモートリポジトリからブランチを取得
* `git pull origin ブランチ名` リモートリポジトリの最新データを取得
* `git clean` - 未追跡のファイルを一掃。 -n, --dry-run のオプションで試し打ちできる


## git revert と git reset の違い
`git revert` は打ち消し処理が履歴に残るが、`git reset <file | commit id>`は残らない

## sshで
* 鍵作成

```bash
ssh-keygen -t rsa -C "account@example.com"
```

* SSH Key をクリップボードにコピーする

＜Mac＞

```bash
pbcopy < ~/.ssh/id_rsa.pub
```
＜Win＞

```bash
clip < ~/.ssh/id_rsa.pub
```

* 疎通確認

```bash
ssh -T git@github.com
```
GitHub知識0でも GitHubWebPagesでwebページを公開する方法

githubwebpagesを利用して静的なwebサイトを公開する方法を説明します。
と言っても多くの方が同じ内容にふれているので、今回私が実際にやってみて
つまずいた点も含めて説明したいと思います。
めちゃくちゃ簡単なのにも関わらず、かなり時間がかかった人が書いてるので
これを見れば挫折することは無いかなと思います。

・ github知識0で大丈夫です
・コミット等には githubデスクトップアプリを使用したのでterminal恐怖症の人でもできます
・webの資材（htmlなど）が元々ある状態からでもできます

環境がMacなので用語とかがそれになってしまってます。
脳内で置換して読んでください。。。

#Step1
まずは githubに登録してください
[GitHub](https://github.co.jp/)

#Step2
リポジトリを作成します。

<img width="1440" alt="スクリーンショット 2018-05-19 23.02.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/190926/e5ea5ead-2203-dc65-c02b-dbcae48d41a5.png">
<font color="red">**[気をつけること]**</font>
リポジトリ名をユーザー名. github.ioにして下さい。
*エラーでてるのはもう同じ名前で作成済みだからです
<img width="1023" alt="スクリーンショット 2018-05-19 23.09.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/190926/adf8dc5f-8020-b6d7-ce8d-923fad1f823d.png">

#Step3
 githubデスクトップアプリをダウンロードします。
[GitHub Desktop](https://desktop.github.com/)

#Step4
リポジトリのクローンを作成します。
先ほど作成したリポジトリはgithub上のものでしかないので
ローカル環境（あなたのPC）用を作成します。
基本的には、htmlなどをここに入れて後でgithub上のリポジトリに反映する、という感じです。

デスクトップアプリを立ち上げて「Clone a repository」をクリックして下さい。
後は画像の通りです。
*エラーは既に(略)
![スクリーンショット 2018-05-19 23.30.26.png](https://qiita-image-store.s3.amazonaws.com/0/190926/e3848342-d183-66e3-772a-56c3407b3989.png)

#Step5
次にクローンにhtmlなどを入れて、コミット（ローカルのリポジトリに反映）します。
Summaryはそのコミットの題名？
Descriptionはコメントだと思って下さい。
書かなくてもいけたはずですが、とりあえすそれぞれ
「first commit」
「初めてのコミットです。」
とでもしとけばいいんじゃないですかね。

<font color="red">**[気をつけること]**</font>
html名は「index.html」にして下さい。(画像とかcssファイルとかは何でも大丈夫です。)
![スクリーンショット 2018-05-19 23.39.09.png](https://qiita-image-store.s3.amazonaws.com/0/190926/d17a090a-e76d-b941-160c-9dcbc897fabd.png)

#Step6
githubのリポジトリにプッシュします。
これでgithub上に反映されます。
反映されると誰でも見れる状態になるので注意(設定で非公開にできるような。。。)

![スクリーンショット 2018-05-19 23.58.08.png](https://qiita-image-store.s3.amazonaws.com/0/190926/9ab1e731-f8f0-f47a-72a5-0e6e23ceb156.png)

#Step7
 githubの自分のリポジトリのsettingからアドレス踏んだら公開されているはずです。
10分くらい時間かかる時もあるっぽいんで飛べなかったら少し待ってみましょう！
それでもダメならつまづいた点を再確認してみて下さい。
それでもダメならここのコメント書いたら優しい有識者の方が教えてくださるかも！

#つまづいた点

- リポジトリ名はユーザー名. github.ioにすること
- html名はindex.htmlにすること

#最後に
いかがだったでしょうか？
初投稿で色々不足、間違いあるかも知れません。。。。
画像も後半差し込めなかったのでそこんところも後で追記したいと
思っています。。。。
リポジトリ名出しちゃってるんであれなんですけど、自分のポートフォリオサイト作りたくて作業途中です、汚くて申し訳ないです。。。。

以上、読んでくださってありがとうございました！

#参考にしたサイト

- [エンジニアだけどポートフォリオサイト作ってみた](https://qiita.com/musou1500/items/24ed32d7f5b0a6377bc5)
- [Qiita マークダウン記法 一覧表・チートシート](https://qiita.com/kamorits/items/6f342da395ad57468ae3)
VS Codeへのリモートリポジトリの設定

# VS Code へのリモートリポジトリの設定
- 現状、GUIで設定することができない。
- 従って、ターミナルから以下のコマンドを実行して設定する必要がある。
  1. git remote add origin {$REPOSITORY_NAME}
  1. git push -u origin master
第5話 五次方程式と解の公式

この記事は[仮面ライダービルドの数式](https://qiita.com/izmktr/items/e26a624e79bce3edccc9)の第5話です。

```math
\arg_n min⁡[S_n∉{solveable}]=5
```
「代数的解法が存在しない最小の次数は5である」という意味です。
五次方程式以降は解の公式が存在しない、という言い方で知っている人が多いでしょう。

代数的解法とは、四則演算とべき乗(平方根や立方根なども含む)だけを有限回使った式を指します。
有限回なので無限級数を使って答えを出しましたものは含みません。
代数的解法という制限を無くせば、五次方程式の解を求める方法は幾つか考案されています。

ですから、解の公式が存在しないという話は、代数的解法とはなんなのか、
それはどういうことができるものなのかという、やや退屈な話になってしまいます。
なので、イメージだけ掴む感じでいきます。

二次方程式の解の公式を簡単にするとこんな感じです。

```math
x_1=\frac{-b+\sqrt{b^2-4ac}}{2a}=\alpha + \beta\\
x_2=\frac{-b-\sqrt{b^2-4ac}}{2a}=\alpha - \beta
```
二次方程式なので答えは２つあります。
そして、２つの数を作って、それを足せばx1、どちらかを引けばx2となります。

普通は、数の小さい方がx1、大きいほうがx2となりますが、
βの値に-1をかければ、x1とx2の値を交換することができます。

次に三次方程式の解の公式です。

```math
\begin{align}
x_1&=\alpha + \beta\\
x_2&=\alpha \omega+ \beta \omega^2\\
x_3&=\alpha \omega^2+ \beta \omega
\end{align}\\
\small
※\omega = \frac{-1+\sqrt{3}i}{2}
```
ωは3乗すると1になる数です。

二次方程式は円を書いて180度の角度にある点です。
三次方程式は楕円を書いて、円なら120度の角度にある点、ということを意味する式です。
そして、反転や回転をすることで、それぞれの値を交換することができます。

四次方程式を解く場合、無理やり因数分解して、二次方程式２つの積の式に変形します。
4という数がたまたま2の2乗だったからこの方法が使えます。

ところが五次方程式となると、72度の角度とするにしても、
そんな点が作図できない事が多いですし、無理やり因数分解もできません。
また、解の入れ替えもできそうにありません。

この、「それぞれの解を交換できる」という条件が代数的解法の根本で、
すべての式に足し算や掛け算をすることで答えの入れ替えができるはず、
それができない(と思われる)五次方程式には解の公式が作れない、という考えです。

ざっくりとした説明ですが、だいたいこんな感じです。
SourceTree とGitHubの連携失敗を乗り越える、なおBitbucket

みなさんSourceTree使えていますか？

私は最近になって**SourceTree**について知り、色々と試して使っています。
しかし、色々といじっていたことでSourceTreeがリモートレポジトリと連携が取れなくなってしまいました。
結局人に教えていただいたことで解決したのですが、今回はその備忘録としてSourceTreeとGitHubの連携失敗を乗り越える解決策について書いていきたいと思います!

#そもそもSourceTreeとは

>SourceTreeはWindowsとMacに対応したGit無料クライアント
Sourcetree により Git リポジトリの操作が簡単になるのでコードを書くことに集中できます。

（引用：https://ja.atlassian.com/software/sourcetree）

ターミナルで管理していたリポジトリをgithubやbitbucketへコミット、プル、プッシュなどを**コマンドを打たず**行うことができます。

ウィンドウやアイコンなどをマウスで操作して、キーボードで文字入力を行うタイプの仕掛けが使われていることから、SourceTreeは**GUI (Graphical User Interface)** のシステムであるようです。

反対に、ターミナル内でコンピュータを操作する場合はキーボード入力と画面の文字表示のみでコンピュータを操作することになり、このような仕掛けを**CUI (Character User Interface)** と言うようです。

（参考：http://www.cc.kyoto-su.ac.jp/~hirai/text/cui.html）

#どんなエラーが出ていたか

SourceTreeからGitHubへプッシュしようとすると以下のようなエラーが出ました。

```
Pushing to https://github.com/'user_name'/'repository_name'.git
remote: Invalid username or password.
fatal: Authentication failed for 'https://github.com/'user_name'/'repository_name'.git/'
```

こんな感じのエラーが連続して出ていました。
ユーザーネームやレポジトリネームは各々のものですね！
Invalidって出ているので、とりあえず無効。

聞く話によると、SourceTreeとGitHubの認証が失敗しているのでは？
ということでした。

#エラーの解決策

助言により、認証が失敗しているということで解決策として、以下のことを実施しました。

**GitHubのリモートブランチを一旦削除して、追加!!**

#リモートブランチ削除の仕方

まずはリモートブランチを削除するために、ターミナルにて、扱っているプロジェクトに移動します。
cd ◯◯ って感じのあれですね。
そのあとに、
`git remote rm origin`
をしました。
（参考：https://qiita.com/yuu_ta/items/519ea47ac2c1ded032d9）

削除できているかどうかは、SourceTreeの左側のリモートというところから確認できます！
私の場合はきちんと削除できていました！

#リモートブランチ追加の方法

削除できていたので、次はもう一度設定し直します。
追加するためのコマンドは以下のようになります。

```
git remote add origin https://'github.user_name'@github.com/'github_user_name'/'repository_name'.git
```
こちらもgitHubのユーザーネームやレポジトリネームは各々のものになります。

このアドレスは、GitHubとSourceTreeを連携させたいレポジトリのクローンボタンを押すと出てきて、
Popular repositories>レポジトリ選択>codeの"clone or download"（緑のボタン）>コピー
という流れなはず。

注意していただきたいのが、コピーした際は****で囲んだところがないこと！忘れず入れましょう！

`https://**'github.user_name'@**github.com/'github_user_name'/'repository_name'.git`

（参考：https://techacademy.jp/magazine/10268）

また、長いコマンドを打ち込む際は、いきなりターミナルに打って反映させるのではなく、メモか何かに打って確認してからコピーしてエンターを押しましょう！何が起こるかわからないので！

#今回の反省

今回の反省として、**初心者が新しくツールを触った際によくわからないような設定に手を出してはいけない**と思いました！
また、何か不安な操作をした際には**記録を取っておきたい**とも…説明も読まないとダメですね、反省。

自分で今回解決できなかったのは残念ですが、**わからないことがあったら早めに聞ける人に聞いておきたい!**


#ちなみにBitbucketの存在…

Githubと同じくして、Bitbucketも登録していたのですが、こちらも連携できなくなっていました（）

なお、こちらの解決は図れていません…
時間をかけるのも勿体無いと思ったので、今はとりあえずGithubのみで管理していこうかと思います！

のちのち解決できるようになったらしよう！
また、どんな問題がおきていたのかについてもゆくゆく気が向いたらまとめます！

自分用にまとめたこの記事ですが、どなたかのお役に立てれば幸いです…
それでは！
Unityで作る最強(当社比)のシーン管理 その2

# 階層構造

今回は階層構造について説明します。

[その1](https://qiita.com/jonigata/items/c47c813c530e66ae67d7)で何回か述べた通り、`Router`を持つヒエラルキーは入れ子構造にできます。

![nested_router.png](https://qiita-image-store.s3.amazonaws.com/0/18886/bf1efca8-a428-c416-fd16-032891785a64.png)

これによって、

`/PageA/a/e`
`/PageA/b/f`
`/PageB/c`
`/PageB/d`
`/PageC`

というパスでアクセスできることになります。もちろん、末端ノードでない`/pageA`、`/PageB`、`/PageA/a`、`/PageA/b`にも`JumpTo`できます。

# enterとleave

パスヒエラルキーに含まれる各`Router`は、enterとleaveという内部イベントを処理します。この知識はトリガを扱うときにも必要になることがあるので説明しておきます。

おおむね、`JumpTo`である場所に来たらその場所にenterが、ある場所から離れるとその場所にleaveが発生すると考えて下さい。

例えば、まず

```
Routing.JumpTo("/PageA/a/e");
```
したとしましょう。次に、

```
Routing.JumpTo("/PageA/b/f");
```
したとします。

このとき、`/PageA/a/e`でleaveトリガが発生し、`/PageA/b/f`でenterトリガが発生します。

## 中間ノードにおけるenter/leave

routeneではさらに、上記のケースで、中間ノードである`a`や`b`でもleave/enterが発生します。`/PageA`ではenterもleaveも発生しません。この動きをファイルシステムのディレクトリにたとえて言うと、cdで一手ずつ相対移動するときの最短距離でのみ処理が行われると考えればよいかと思います。

例えば、`/PageA/a/e`から`/PageA/b/f`への移動は、

```
  % cd ..
  % cd ..
  % cd b
  % cd f
```
となります。`cd ..`したときに移動前の場所でleaveが、`cd <dir>`としたときに移動後の場所でenterが発生します。

# 実装方法

routeneでは、このイベントの伝播のために、UniRxを使っています。具体的には、Router.csの以下のような定義によってです。

```
    [NonSerialized] public BehaviorSubject<Plan> enter =
        new BehaviorSubject<Plan>(null);
    [NonSerialized] public BehaviorSubject<Plan> leave =
        new BehaviorSubject<Plan>(null);
```

`Routing.JumpTo("/A/B")`のような要求がきたとき、`Routing`はこれを識別子のリスト`["A","B"]`に分解し、concreteRouterに渡します。

受け取ったRouterでは、リストの先頭を消費してのこりを`this.enter`にUniRxのイベントとして発行します。子`Router`は親の`Router`のenter/leaveを`Start`時に自動的に`Observe`しますので、同様に再帰的に処理していきます。

なぜこのような構造にしたかというと、動的なmountを実現するためです。そのあたりは次回説明します。

leaveについては、enterと同じようなことを前回与えられたパスに対してenterの前に行うことで実現されます。
bitnami Redmineのインストール手順書

#bitnami Redmineのインストール手順書

インストール・セットアップが簡単で非常に優れた
bitnami Redmineの手順書を以下に示す。

## インストーラ取得
下記のページよりインストーラを取得する。<br>
[bitnami Redmine](https://bitnami.com/stack/redmine/installer)<br><br>
![download.png](https://qiita-image-store.s3.amazonaws.com/0/110729/729364e8-dd07-2fd3-8fbe-00da993b4217.png)
![download2.png](https://qiita-image-store.s3.amazonaws.com/0/110729/f836a148-9d85-5a6b-6a0d-056fd05c6a90.png)
<br>

## インストール実行
![installer.png](https://qiita-image-store.s3.amazonaws.com/0/110729/94c28459-883c-5f8b-3d68-af72d6720f9d.png)
を実行する。
<br>
![language.png](https://qiita-image-store.s3.amazonaws.com/0/110729/f0f4fc5e-c9ea-a0a8-d363-aad83788d8f2.png)
「Japanese - 日本語」を選択する。
<br>
![confirm.png](https://qiita-image-store.s3.amazonaws.com/0/110729/e9c9ecb8-075d-2caf-6534-76e5c8e2d000.png)
「はい」を押下する。
<br>
![setup1.png](https://qiita-image-store.s3.amazonaws.com/0/110729/e6ac9753-1d02-ea10-3360-c0cc6aea4048.png)
「次へ」を押下する。
<br>
![setup2.png](https://qiita-image-store.s3.amazonaws.com/0/110729/ec7c313e-38ad-e77f-a895-54f0cd657efa.png)
「次へ」を押下する。
<br>
![setup3.png](https://qiita-image-store.s3.amazonaws.com/0/110729/bc045a0a-cb82-c8ae-1fab-ed037cad033c.png)
「フォルダを選択」でインストール先を設定し、「次へ」を押下する。
<br>
![setup4.png](https://qiita-image-store.s3.amazonaws.com/0/110729/42c0e1b9-fb34-d937-5a36-aae49953af99.png)
任意で入力し、パスワードを8文字以上入力し「次へ」を押下する。
<br>
![setup5.png](https://qiita-image-store.s3.amazonaws.com/0/110729/3108b840-c659-1cff-2832-1feae819f580.png)
「日本語」を選択し、「次へ」を押下する。
<br>
![setup6.png](https://qiita-image-store.s3.amazonaws.com/0/110729/3e82e460-6619-2d05-6f00-3097f039f9f0.png)
「次へ」を押下する。
<br>
![setup7.png](https://qiita-image-store.s3.amazonaws.com/0/110729/2c18344e-e728-d8dc-f7ba-0b67c47c7513.png)
「次へ」を押下する。
<br>
![setup8.png](https://qiita-image-store.s3.amazonaws.com/0/110729/fea3d060-96f7-a33b-94f2-ae8e7422eecf.png)
「次へ」を押下する。
<br>
![setup9.png](https://qiita-image-store.s3.amazonaws.com/0/110729/39003c11-f579-2dce-4ab0-350ce9e8afea.png)
しばらく待つ。
<br>
- ![setup10.png](https://qiita-image-store.s3.amazonaws.com/0/110729/0adffcab-1501-183d-6810-bbed8e0f8e51.png)
「終了」を押下する。
<br>

## 詳細設定
ポート設定
![start1.png](https://qiita-image-store.s3.amazonaws.com/0/110729/b077e02a-f34b-2716-bd57-9064ebc902fa.png)
他のアプリとポートが競合しないように変更する。
Bitnami Redmine Stack
　=> Manage Serversタブ
で
「Apache Web Server」
　=> 「Configure」
を押下する。
<br>
![configure1.png](https://qiita-image-store.s3.amazonaws.com/0/110729/895231e7-a75b-4f22-ee3b-65b34e4aaf08.png)
ポートを8090など入力して、「OK」を押下する。
<br>
![configure2.png](https://qiita-image-store.s3.amazonaws.com/0/110729/9c7ead1c-5315-0974-23c1-4e10b1c44fa5.png)
サーバプロセス再起動の為、「はい」を押下する。
<br>
![application1.png](https://qiita-image-store.s3.amazonaws.com/0/110729/b8c77dfb-76c3-e840-620a-6021f25dc90f.png)
「Go to Application」ボタンを押下する。
<br>
![application2.png](https://qiita-image-store.s3.amazonaws.com/0/110729/3e07f709-391a-571c-5684-78949cd56c64.png)
「Access Redmine」リンクを押下する。
<br>
![application3.png](https://qiita-image-store.s3.amazonaws.com/0/110729/f149a4f1-abf6-6607-6e26-d10f081bf756.png)
無事起動したことを確認する。
Doma2のエンティティクラスの日付/時刻型について

# この話題の前提
- Doma2を使います。
- Doma-GenでEntityを自動生成します。
- UTCとは、エポック秒とします。
- DBのTIMESTAMP型は、UTC（エポック秒）を保管できるものとします。

# 参考にさせて頂いたサイト
- https://qiita.com/dmikurube/items/15899ec9de643e91497c

# DBのTIMESTAMP型(日付と時刻)を、エンティティクラスでは、どの型で扱うか？

DBのテーブルに、TIMESTAMP型(日付と時刻)があるとき、どの型で扱うべきか迷いました。
ご意見をお願いいたします。

## Doma2でサポートしている日付/時刻型
Doma2では、日付/時刻型として、次のリンク先の型をサポートしています。
http://doma.readthedocs.io/ja/stable/basic/#id4

その中で、日付＋時刻を扱う場合は、次のいずれかの型になります。
- java.time.LocalDateTime
- java.sql.Timestamp
- java.util.Date

## Doma-Genで生成される型

Doma1時代のDoma-Genでは、TIMESTAMP型(日付と時刻)に対応する型は、java.sql.Timestampでした。
http://doma.seasar.org/extension/doma_gen_gen_task.html#EntityConfig

しかし、Doma2のDoma-Genでは、java.time.LocalDateTimeになっています。
http://doma-gen.readthedocs.io/ja/stable/gen/#entityconfig

## java.time.LocalDateTimeの問題だと思う点

次のサイトに詳細がありますが、java.time.LocalDateTimeは、日時をUTCで保持するのではなく、`タイムゾーン情報を一切含まない日付時刻`で保持します。
https://qiita.com/dmikurube/items/15899ec9de643e91497c#javatimelocaldatetime

DBのTIMESTAMP型(日付と時刻)では、日時をUTCで保持するので、java.time.LocalDateTimeで扱ってしまうと、タイムゾーン情報が欠落してしまいます。

ちなみに、PostgreSQLでは、内部的にUTCで保管されています。
https://www.postgresql.jp/document/9.6/html/datatype-datetime.html

## java.sql.Timestampを使うのがよい？
java.sql.Timestampは、UTCを保持できるため、タイムゾーンを指定すれば、そのタイムゾーンでの日時が決まります。
つまり、システム内部で日時をUTCで取り回していれば、出力の際には、タイムゾーンを指定して、そのタイムゾーンの日時表現に変換できます。
そういった意味で、java.sql.Timestampを使うのがいいのかなと思います。

対して、java.time.LocalDateTimeの場合は、`タイムゾーン情報を一切含まない日付時刻`が、どのタイムゾーンの日時表現かを意識して取り扱う必要があります。
例えば、DBも、システムも、日本のタイムゾーンのみのように、１つのタイムゾーンに限定できるのであれば、事が足りるのかもしれません。

# Doma-Genで、TIMESTAMP型(日付と時刻)に対応する型を、java.sql.Timestampにする方法

## カスタムのGenDialectクラスを用意する。
使用するDBのGenDialectクラス（この例では、PostgreSQLのGenDialectクラス）を継承して、カスタム用のクラスを用意します。

```java
/**
 * PostgreSQL用の方言をカスタマイズするクラス
 */
public class CustomPostgresGenDialect extends PostgresGenDialect {
    public CustomPostgresGenDialect() {
        // タイムゾーン付きのtimestampは、java.sql.Timestampにマッピングする。
        classNameMap.put("timestamptz", Timestamp.class.getName());
    }
}
```
## Doma-Genのトップレベルパラメーターに指定する。

トップレベルの`genDialectClassName`に、上記のクラスを指定して、Doma-Genを実行します。（タスク実行時のクラスパスに、指定したクラスを含める必要があります。）
http://doma-gen.readthedocs.io/ja/stable/gen/#id2
電気系プログラミングガチ素人が、Xamarinでアプリ開発する話　6日目~OSごとにコンパイルのオプションを変える、継承~

#まえがき
この記事は「Skype工学勉強会」の「アプリ作成部屋　Xamarin」での活動をまとめて記録したものです。参考書が、マイクロソフトさんから布教されておりますので、そちらを和訳しつつ、まとめて記事にしていく流れになっております。
しかし、当方、タグの通り、「電気系」の学生で「ガチ素人」であるため、先輩にまさかりを投げてもらいながら、覚えていく所存でございます。また、もし他に指摘点などございましたらぜひともよろしくおねがいします。

↓Xamarinの布教用PDF、Kindle版もございますので、英語読める方、ぜひとも。
https://blogs.msdn.microsoft.com/microsoft_press/2016/03/31/free-ebook-creating-mobile-apps-with-xamarin-forms/

[初日](https://qiita.com/sanbongazin/items/4b9609b60a8894ebfdbd)

#SAPでアプリをもっと作ってみようぜ
##iOSのみでPaddingを実行してみよう！
このコーディングは継承を理解していれば理解がしやすくなります。

```
継承とは

犬 ＝＞　哺乳類の継承
人間＝＞哺乳類の継承
test_sapPage（数ある中のページの一つ）＝＞ContentPage（これを親とした全てのまとめ上げた総体の事）
```

のようですね！
以下にソースコードを書きます！

```C#
using Xamarin.Forms;

namespace test_sap
{
	public partial class test_sapPage : ContentPage//部分的にクラスを宣言できるのがPertial。
	{

		public test_sapPage()
		{
			Content = new Label
			{
				Text = "Greetings, Xamarin Forms"
			};

			//InitializeComponent(); 
#if _IOS_ //iOSがターゲットのOSの際には、実行されるもの
			Padding = new Thickness(0, 20, 0, 0);
#endif 
		}
    }
}

```
<b>大体がこういう思想で作られている</b>そうですので、是非とも覚えましょう♪

実行した結果は、以下のようになりました！
###Android
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244181/55761993-d99b-e1c2-f3c8-60030ccd77fe.png)
ちゃんと実行されてますね！（確認）

###iOS
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244181/a17c67da-4e7c-9b56-0352-e1d50df5edc3.png)
あれ、文字が・・・（困惑）

以下に記述を変えてみました

```
Padding = new Thickness(200, 20, 0, 0);
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/244181/a17c67da-4e7c-9b56-0352-e1d50df5edc3.png)
変わんない・・・

#アンダーバーは２本にしましょう
こうしないと、うまく有効になりませんでした！（＃ifの場所以降のPaddingがコメントアウト状態でした）
みなさん！！２本です！！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244181/3070382f-3709-c432-b397-c94d5a19db5c.png)

#あとがき

*　継承を学ぶと、フレームワークの基礎を学べる
*　動くかどうかは、実際にデバッグして、比較しないと、ひどい目にあうぞ！
*　ログ出力をすると、GitBlameが汚れるので、ブレークポイントを挟もう！教祖様（私じゃないよ）とのお約束だ！

というところでした！
筋トレは良いぞ！自己評価が低い人は、自分をいじめ抜く事で、リフレッシュできるぞ！
という事で、筋トレすると、ソースコードの書く速度が上がるかも？
Ubuntu 16.04 にknowledgeをインストール

# 概要
[knowledge](https://information-knowledge.support-project.org/ja/)をEC2上のUbuntu16.04にインストールする。
knowledgeとはオープンソースの情報共有サービスで、いわゆるQiitaクローンとも言われるサービスである。

# 手順
## EC2を立ち上げる
 * OSをUbuntu16.04をする
 * セキュリティグループはTCPの8080も許可する（インバウンド）

## Java8のインストール

```
# jreでいいかも
$ sudo apt install openjdk-8-jdk
```

## Tomcatのインストール
 * まずはTomcatの実行ユーザとなるユーザを作成

```
# ログインシェルの設定が必要かは不明
# knowledgeはデフォルトでホームディレクトリ配下にファイルを作成するのでホームディレクトリも作成する
$ sudo useradd -m -s /bin/bash tomcat
```

 * Tomcatのダウンロード、インストール

```
$ cd /usr/local/src
$ sudo wget http://ftp.tsukuba.wide.ad.jp/software/apache/tomcat/tomcat-8/v8.5.31/bin/apache-tomcat-8.5.31.tar.gz
$ sudo tar xvzf apache-tomcat-8.5.31.tar.gz
$ sudo cp -rp apache-tomcat-8.5.31/ /opt/
$ sudo chwon -R tomcat:tomcat /opt/apache-tomcat-8.5.31
$ cd /opt
$ sudo ln -s apache-tomcat-8.5.31 tomcat8
```

## knowledgeインストール

```
$ cd /usr/local/src
$ sudo wget https://github.com/support-project/knowledge/releases/download/v1.12.0/knowledge.war
$ sudo chown tomcat:tomcat knowledge.war
$ sudo mv knowledge.war /opt/tomcat8/webapps/
```

## 起動

```
$ sudo su - tomcat
$ /opt/tomcat8/bin/catalina.sh start 
```

## アクセス

 * ブラウザから下記にアクセスする
    * http://[IPアドレスorFQDN]:8080/knowledge/
Repeat-RNN の実装に関するメモ

##ポイント
* LSTMをベースに Repeat-RNN を実装し、（トイデータを用いて）パフォーマンスを検証。
* Repeat-RNN と Attention モデルから同等の学習パフォーマンスが得られることを確認。
* 今後、別タスク、別データで追加検証。

##レファレンス
[1. Comparing Fixed and Adaptive Computation Time for Recurrent Neural Networks](https://arxiv.org/pdf/1803.08165.pdf)
##検証方法
* モデルがデータの規則性を理解する（正解率98％以上に達する）までに要したイテレーション回数をチェックする。
* 複数回の試行の平均と標準偏差をパフォーマンスの指標とする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/254604/232e0045-19f3-8293-e439-ba7118b13d7b.png)
　　　　　 　 　          （参照論文より引用）

##データ
入力 $x(t)$：

```math
x(t) = \begin{pmatrix}
s(t)\\
m(t) 
\end{pmatrix} \\
s(t) \in \{0, 1, 2, 3, 4\}\\
m(t) \in \{0, 1\},\quad \sum_{t=1}^{T} m(t) = 2
```
出力 $y$：

```math
y = \sum_{t=1}^{T} s(t) m(t)
```
例：

```math
s = [2,3, 1, 0, 4]\\
m = [0, 0, 1, 0, 1]\\
\rightarrow\
y = 5
```

##検証結果
数値計算例：

* T = 7
* サンプル数：1,000　（ トレーニング：500、テスト：500 ）
* バッチサイズ：30
* 隠れ層のユニット数：30 　( Attention 付きでは 24 ）
* オプティマイザー：Adam
* 試行回数：5回

|データ | 指標 |Base  | Repeat | Attention |
|:-:|:-:|:-:|:-:|:-:|
|トレーニング  | 平均  |314.80   |327.40 |308.20   |
|   |標準偏差   |28.51   |14.39   |37.76   |
| テスト  |平均   |NA   |389.00  |399.90   |
|   |標準偏差   |NA   |29.69   |31.92   |

Base： Repeat、 Attention なしの LSTM
Repeat：  $\rho=2$
Attention： スコア関数に Dot Product を使用した基本形

##サンプルコード
```python
  def inference(self, x, length, n_in, n_units, \
                     n_out, batch_size):
    h = tf.zeros(shape = [batch_size, n_units], \
                     dtype = tf.float32)
    c = tf.zeros(shape = [batch_size, n_units], \
                     dtype = tf.float32)
    
    list_h = []
    list_c = []
    
    with tf.variable_scope('lstm'):
      for t in range(length):
        if t == 0:
          x_ = x[:, t, :]
          # 1st pondering
          x_1 = tf.concat([x_, tf.ones(shape = \ 
                 [batch_size, 1], dtype = tf.float32)], \
                 axis = 1)
          h, c = self.LSTM(x_1, h, c, n_in + 1, n_units) 
          
          tf.get_variable_scope().reuse_variables()
          # 2nd pondering
          x_2 = tf.concat([x_, tf.zeros(shape = \
                 [batch_size, 1], dtype = tf.float32)], \
                 axis = 1)
          h, c = self.LSTM(x_2, h, c, n_in + 1, n_units) 
        
          list_h.append(h)
          list_c.append(c)
        
        else:
          tf.get_variable_scope().reuse_variables()
          x_ = x[:, t, :]
          # 1st pondering
          x_1 = tf.concat([x_, tf.ones(shape = \
                 [batch_size, 1], dtype = tf.float32)], \
                 axis = 1)
          h, c = self.LSTM(x_1, h, c, n_in + 1, n_units) 
          
          # 2nd pondering
          x_2 = tf.concat([x_, tf.zeros(shape = \
                 [batch_size, 1], dtype = tf.float32)], \
                 axis = 1)
          h, c = self.LSTM(x_2, h, c, n_in + 1, n_units) 
        
          list_h.append(h)
          list_c.append(c)
        
    with tf.variable_scope('pred'):
      w = self.weight_variable('w', [n_units, n_out])
      b = self.bias_variable('b', [n_out])

      pred = tf.add(tf.matmul(list_h[-1], w), b)

      return pred
```
UITableViewCellのnumberOfRowsInSectionとcellForRowAtIndexpath



```
//何行表示させるか
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
	return 10
}


//行に何を表示させるか
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
	let cell = UITableViewCell(style: .value1, reuseIdentifier: "Cell")
	cell.textLabel?.text = "たろう"
	return cell
}

```
Jupyter notebook に仮想環境の Kernel を追加して切り替えて使うための設定

## 前提
- Anaconda 環境
- 仮想環境それぞれに jupyter notebook がインストールされている

## できるようになること
- どの環境（root, 仮想環境全て）で Jupyter notebook を起動しても、カーネル選択で他の仮想環境を選択すれば選択した仮想環境上で notobook 上のコードを実行できる

## 方法
- コマンドラインで Jupyter notebook にカーネルを追加したい環境を activate
- 以下のコマンドを実行

```
python -m ipykernel install --user --name=XXXX --display-name=YYYY
```

**コマンドの説明:**

- anaconda を PC の全ユーザーに対してではなく user インストールした場合 `--user` を付加
- `--name=XXX`
  - XXXX には設定ファイルを保存するディレクトリ名を入れる
  - 既に同一のディレクトリが存在する場合上書きされてしまうので注意
  - 保存先ディレクトリのパスは, 後述
- `--display=name=YYYY`
  - jupyter notebook 上で表示するカーネルの名前を入れる

## kernelの追加先
Anaconda を user 環境にインストールしている場合のみ記載

- Mac, Linux
  - ~/user/local/share/jupyter/kernels
- Windows
  - C:user/ユーザー名/AppData/Roaming/jupyter/kernels

もし上記と違った場合も類推して周辺を探せば見つかるはず
お好み焼きで学ぶ名前空間

#お好み焼きとは
小麦粉とキャベツなどを焼く定番のご飯ですね。作り方や具材によって呼び方が変わります。キャベツとネギと山芋とかが入ったのを「関西風」とか、麺が乗ってるのを「広島風」と呼んだりしますね。

僕の住んでる地域では「関西風」お好み焼きが一般的です。ので、お好み焼きといえば、いわゆる「関西風」お好み焼きでした。一方、広島の人はお好み焼きというと「広島風」お好み焼きのことを指すようになります。

これは名前空間の関係にあります。

#それぞれの名前空間
「お好み焼き」と一言で言っても「関西風」とか「広島風」という呼ばれ方をします。この「関西」とか「広島」は名前空間と呼ばれます。それぞれの名前空間でのお好み焼きの宣言は次の様になります。
####・関西の人の名前空間

```c++
namespace 関西 {
    class お好み焼き {
        ...
    }
}
```

####・広島の人の名前空間

```c++
namespace 広島 {
    class お好み焼き {
        ...
    }
}
```

それぞれの「お好み焼き」クラスは、「関西」、「広島」という名前空間に属しています。つまり、同じ名前のクラスですが別物として宣言されました。


#名前空間の使い方
####・ 東京の人同士の会話
東京出身のA君とB君がお好み焼きの話をしています。二人はお好み焼きの話をあまりしないので、誤解がないように注意しながら「関西風」とか「広島風」を付けてお好み焼きを呼びます。

すると、それぞれのお好み焼きの宣言はスコープ解決演算子を使って以下のようになります。

```c++
//　関西風お好み焼きインスタンス
関西::お好み焼き k_okonomiyaki = new 関西::お好み焼き();

// 広島風お好み焼きインスタンス
広島::お好み焼き h_okonomiyaki = new 広島::お好み焼き();
```
　
ここで、スコープ解決演算子「::」を「〇〇風」と訳せば、それぞれが「関西風お好み焼き」、「広島風お好み焼き」を指していることがわかりやすいです。
　
　

####・関西の人と東京の人の会話
東京出身のA君は、大阪出身のCさんともお好み焼きの話をしました。もちろん、「関西風」お好み焼きのことを話すので、ここではわざわざ「関西風」とつける必要はありません。
　
そこで、「関西」という名前空間をusing宣言してみましょう。

```c++
// "関西"のusing宣言
using namespace 関西;

//　関西風お好み焼きインスタンス
お好み焼き k_okonomiyaki = new お好み焼き();

// 広島風お好み焼きインスタンス
広島::お好み焼き h_okonomiyaki = new 広島::お好み焼き();
```

　

先ほどの例と違って、「関西」という名前空間のusing宣言がされているので、わざわざ「関西::」と付けなくても関西風お好み焼きを参照できるようになりました。これからたくさん出て来る関西風お好み焼きの参照をするのが少し楽になり、冗長でなくなりました。

広島風お好み焼きは先ほどと同様に「広島::」と付けています。

　
　

####・広島の人と東京の人の会話
東京出身のA君は、今度は広島出身のDさんとお好み焼きの話をしました。Dさんは「広島風」お好み焼きの話をするので、「広島」という名前空間をusing宣言するのが良さそうです。

```c++
// "広島"のusing宣言
using namespace 広島;

// 関西風お好み焼きインスタンス
関西::お好み焼き k_okonomiyaki = new 関西::お好み焼き();

//　広島風お好み焼きインスタンス
お好み焼き h_okonomiyaki = new お好み焼き();
```
　

これで広島風お好み焼きの参照を「お好み焼き」だけでできるようになりました。シンプルでいいですね。
　
さっきとは逆に、関西風お好み焼きの参照には「関西::」をつける必要があります。
　
　

####・関西の人と広島の人の会話
大阪出身のCさんと広島出身のDさんが出会ってしまいました。二人は熱い「お好み焼き談義」に華を咲かせようとしましたが、うまく会話が噛み合いません。なぜでしょうか。
　

```c++
// "関西""広島"のusing宣言
using namespace 関西;
using namespace 広島;

//　関西風お好み焼きインスタンス（？）
お好み焼き k_okonomiyaki = new お好み焼き();

// 広島風お好み焼きインスタンス（？）
お好み焼き h_okonomiyaki = new お好み焼き();
```
　
　
それぞれの名前空間に「お好み焼き」というクラスが存在するので、どちらを参照するかわからずに名前の衝突が発生しています。これではうまく会話が進まないので少なくとも一方はusing宣言はやめてスコープ解決演算子を使うほうがよいです。
　
しかし、片方だけにusing宣言を使うと、誤って違う方のお好み焼きを参照したり、もう一方が不公平に感じたりするかもしれません。最初の例の様に両方ともスコープ解決演算子を使って会話を進めましょう。


#まとめ
名前空間のusing宣言は便利だけどむやみに使うと衝突するから気をつけようね、って話でした。

お好み焼きの名前空間についてまとめてみました。味噌汁とかラーメンとかでも同じことが言えそうですね。いろんな地域の人がいると名前空間がごちゃごちゃになりやすいので、スコープ解決演算子「〇〇風」をしっかり使って会話をするのがいいでしょう。

#余談
広島の方曰く、広島の名前空間の人に「広島焼き」を参照しようとするとひょんな例外を投げられることがあるそうです（AngryExceptionなど）。つまり非推奨ということですね。呼び出さないように気をつける、もしくは例外処理をしっかりしましょう。
アラートを表示する

```
func showAlert () {
	let alertDialog = UIAlertController(title: "タイトル",
																			message: "メッセージが入ります",
																			preferredStyle: UIAlertControllerStyle.alert)
	let button = UIAlertAction(title: "ボタンタイトル",
														 style: UIAlertActionStyle.default) { (action) in
															//ここにボタンが押された時のアクションの処理を書く
															
															
	}
	alertDialog.addAction(button)
	present(alertDialog, animated: true, completion: nil)

}
```
ESLintとPrettierを導入する

## 概要
ESLintとPrettierを導入します。
[Airbnb JavaScript Style Guide
](https://github.com/airbnb/javascript)を使用するための設定まで行います。

## 環境
 - Mac OS X Sierra 10.12.6
 - Node.js v10.1.0
 - npm 5.6.0
 - ESLint 4.19.1

## 導入手順

###NPMを使用して、ESLintのインストール

```
$ npm install eslint --save-dev
```

### 設定ファイルの作成
以下のコマンドを実行することで、対話形式で設定内容が質問され、設定ファイル`.eslintrc.js`が作成されます。

```
$ ./node_modules/.bin/eslint --init

? How would you like to configure ESLint?
  Answer questions about your style
❯ Use a popular style guide
  Inspect your JavaScript file(s)

? Which style guide do you want to follow?
  Google
❯ Airbnb
  Standard

? Do you use React? (y/N)N

? What format do you want your config file to be in? (Use arrow keys)
❯ JavaScript
  YAML
  JSON
```

質問の中で`Airbnb`のスタイルガイドを使用すると答えているため、`eslint-config-airbnb-base`についても自動的にインストールされます。

### ESLintの実行
以下のコマンドで実行できます。

```
$ ./node_modules/.bin/eslint yourfile.js
```

### package.jsonにESLint実行コマンドを追加
`./node_modules/.bin/eslint`ではなく、`lint`コマンドで実行できるように`package.json`を修正します。
以下を追加してください。

```diff:package.json
  "scripts": {
-   "test": "echo \"Error: no test specified\" && exit 1"
+   "test": "echo \"Error: no test specified\" && exit 1",
+   "lint": "eslint yourfile.js"
  }
```

`yourfile.js`については、適宜変更してください。

### コマンド実行
以下のコマンドで実行します。規約違反があった場合、メッセージが表示されます。

```
$ npm run lint
```

### package.jsonにfixオプションの実行コマンドを追加
fixオプションを追加することで、規約に違反したコードをある程度自動で修正してくれます。

package.jsonにfixオプションの実行コマンドを追加します。

```diff:package.json
  "scripts": {
-   "lint": "eslint yourfile.js"
+   "lint": "eslint yourfile.js",
+    "lint:fix": "eslint --fix yourfile.js"
  },
```

### コマンドの実行

以下のコマンドで実行します。規約違反のコードが自動的に修正されます。
ただし、全てのコードが修正される訳ではないので注意してください。

```
$ npm run lint:fix
```

### globalsプロパティの設定
ここまでの設定のままだと、[no-undef](https://eslint.org/docs/rules/no-undef)ルールによって、`document`などのグローバル変数・関数がとエラーとなります。
そのため、`.eslintrc.js`に`globals`オプションを追加します。
以下のように追加します。

```diff:.eslintrc.js
+ "globals": {
+   "document": true
+  }
```
キーは変数名を指定(`document`)し、値は(`true` or `false`)は書き込み可能かどうかを指定します。
`ture`を指定した場合、書き込み可能となります。

###NPMを使用して、Prettierのインストール

```
$ npm install prettier eslint-config-prettier eslint-plugin-prettier --save-dev
```
###`.eslintrc.js`の設定

Prettierを適用するための設定を追加します。

```diff:.eslintrc.js
-    "extends": "airbnb-base",
+    "extends": [
+        "airbnb-base",
+        "plugin:prettier/recommended"
+    ],
```

また、`airbnb`の設定ルールと被るため、`singleQuote`だけオプション設定します。

```diff:.eslintrc.js
+    "rules": {
+        "prettier/prettier": [
+            "error",
+            {"singleQuote": true}
+        ]
+　　   }
```
react-native-dom の何がすごいのか

react-native-dom とは
---

https://github.com/vincentriemer/react-native-dom

experimental と書いてあるが普通に動く。デモを見ると React Native で提供されている仮想 DOM は大体動くといった感じ。

https://rntester.now.sh/

2018 年の React Europe で発表された資料。

https://rndom-slides.vincentriemer.app/
https://www.youtube.com/watch?v=aOWIJ4Mgb2k

これの何がすごいかというとブリッジの仕組みにのっとって構築されているところだ。 Native First と言っている。


ブリッジの仕組み
---

iOS のブリッジの仕組みは次でまとめているので参照のこと。

https://speakerdeck.com/januswel/discussion-about-the-bridge
https://qiita.com/janus_wel/items/93de843cc2243370fce4

Android は軽くググったら↓が本質的なことを書いていた。

http://toshi0383.hatenablog.com/entry/2017/02/11/210723

要は React Native の基本設計として React 界と Native 界を結ぶブリッジというものがあり、そのブリッジは次の責務を持っている。

- JavaScript 実行スレッドの開始
- レンダリングスレッドの開始
- 各ネイティブモジュール用スレッドの開始
- JavaScript からネイティブ機能を呼び出す際、キューへのタスク追加
- ネイティブから JavaScript を呼び出す際、キューへのタスク追加

JavaScript スレッドとその他スレッドはそれぞれ機能呼び出しを媒介しているキューが存在していて、キューに積まれたタスクを各スレッドが消化していって JS 層とネイティブ層の連携がなされている、という理解をすればいい。


react-native-dom の設計
---

上述のブリッジの責務を、次のように実現している

- Web Worker をスレッドとして使っている
- レンダリングスレッドを Yoga の DOM 実装ベースで作っている
  - https://github.com/vincentriemer/yoga-dom

つまり React Native の設計思想に照らして DOM というネイティブプラットフォーム向けの実装をした、というパッケージになる。ちなみに yoga-dom は WebAssembly で提供されているようだ。


これがもたらすもの
---

じゃあ実際にどんなうれしいことがあるのかというと多分次になる。

- Learn Once, Write Anywhere
- コンポーネントベース開発の加速
- 実行速度

### Learn Once, Write Anywhere

React.js が掲げている思想で、一度 React.js の流儀を学んだらどのプラットフォームでも書けるというもの。現状でも react-dom と React Native で実現できてはいるが、 react-dom を使う場合は Webpack や Parcel など React Native packager 以外の技術に習熟する必要があった。

これは次のように利点として掲げられている。

> Built with the same bundler used for existing React Native platforms: Build both the "native" main and JS threads with the Metro Bundler along with all the developer experience features it provides.

フレームワークとして easy 寄りの選択ではあるが、「感覚を持ち回せる」というのは開発効率に直結する。

また、 React Native はクロスプラットフォーム開発の基盤として Write Once, Run Anywhere の文脈で語られることが多かったが、流石に Web アプリも含めて 1 source で対応しようとする人間はいないだろう。文脈が違いすぎるので UI 設計レベルで別物になるはずだ。

ただ、次の利点であるコンポーネントの流用が加速することで開発効率の上昇も見込める。

### コンポーネントベース開発の加速

atomic design でいうところの atoms や molecules まではプラットフォーム共通のコンポーネントを作り込んで流用ということがしやすくなる。つまり Web アプリとネイティブアプリで同じ見た目を持つボタンを共有しやすくなるので CI に準拠しやすくなるなどの利点がある。

organisms や templates など、画面コンポーネントを含む大きなコンポーネントは各プラットフォームで作り込むべきだが、境界さえしっかりと認識していればコンポーネントベースの恩恵を余すところなく享受できるようになるのは強みだ。

### 実行速度

クライアントサイド Web アプリで特に苦労することなくマルチスレッドが使える。これだけで夢が広がる。

> Multithreaded by default: Following the exact same architecture as React Native on mobile, all of your react components/app logic are run in web worker, leaving the main thread to entirely focus on rendering.

たとえば機械学習などの重い計算処理を別スレッドにディスパッチするなど、いくらでも用途がある。


選択肢としてアリなんじゃないか
---

まだファイルサイズが大きいから production ready ではないよ、と書かれていること、速度のチューニングをこれからすることを考えると、確かにまだ使っていくのは難しいかもしれない。 React Europe での講演資料の中に次をやっていきたいと書いてあった。

- Async/Multithreaded Layout
- More WebAssembly
- First-Class PWA Support
- WebGL Renderer

ただし、アプローチとしてまっとうであることは理解できる。

どう転ぶかわからないのは今まで CSS で担保されてきた表現力を Yoga や独自レンダリングによってどこまで引き出すことが可能なのか、という点。 CSS をフルに使っていきたい、という場面以外では production ready にさえなれば選択肢としてアリなんじゃないか、と思う。