OmniAICreator/Qiita-1.07M huggingface dataset:
JJUGナイトセミナー 　メモ１（Jakarta EE）

#はじめに

2020年1月22日にJJUGナイトセミナー「Jakarta EE特集」を聴講したので、その内容をまとめてみました。

イベント紹介ページ
https://jjug.doorkeeper.jp/events/102611


#Jakarta EE最前線 -Jakarta EE 8の新機能と今後のロードマップなどなど


###Jakarta EEのリリースの流れ

- 2017年9月　：Java EE8のリリース
- 2019年9月　：Jakarta EE8のリリース
- 2020年6月頃：Jakarta EE9のリリース（予定）

###Jakarta EE が目指すもの

- Java EEに代わるあらたなエンタープライズJava標準をまとめていく
- クラウドネイティブ時代に対応する標準を決める（時代の流れに沿った標準にする）
- ECLIPSE FOUNDATIONでイニシアチブを運営（活気のあるコミュニティを形成）

（目指しているもの）
　オープンソースなどの良いものを取り入れていく
　　ex：Microprofileの運営方法、Docker、Kubernetes

###Jakarta EEの仕様策定の原理原則
Jakarta EEはソースコードの仕様やテストキットの標準をまとめる活動をしているが、
その活動の原理原則は以下の通り。

- オープンに活動する
- リリース頻度向上（頻度はまだ未定）
- 古いAPIをそぎ落とし、新しい仕様を入れる
- 相互依存性の軽減
- テストキットをプロジェクト単位に構築をする
- mavenを標準ビルドツールにする（オープンソースの活用）
- CDIとconfig（方向性未定）の積極的な導入
- JavaSEに対しても、MANIFEST.MFを入れておく

###仕様策定のプロセス
今までのJavaEEとは異なる。
ECLIPSE FOUNDATIONが持っている仕様プロセス
「[Eclipse Foundation Specification Process（EFSP）](https://www.eclipse.org/projects/efsp/) 」を踏襲している。

<dl>
  <dt>今までのプロセス</dt>
  <dd>仕様を決めてから開発・実装するため、フェーズが分離している</dd>
  <dt>今後のプロセス</dt>
  <dd>ラフな仕様を決めたら開発をし、実装と同時並行で仕様を固めていく</dd>
</dl>
開発を常に中心においているため、リリース速度を上げることが可能。

###Jakarta EEのロードマップ

<dl>
  <dt>Jakarta EE8</dt>
  <dd>・ネームスペースは「javax.* 」</dd>
  <dd>・Java EE8の仕様をそのまま移行 </dd>
  <dd>・オープンソースTCK（技術互換キット）を利用可能</dd>
  <dd>・プロセスの確立</dd>
  <dt>Jakarta EE9</dt>
  <dd>・Jakarta EE8から新しい仕様追加なし</dd>
  <dd>・ネームスペースを全面移行：「javax.* 」 →　「jakarta.* 」</dd>
  <dd>・古くなった仕様の削除とオプション化</dd>
  <dd>・jdk11への互換性を保証する</dd>
  <dt>Jakarta EE10</dt>
  <dd>・未定</dd>
</dl>

**Jakarta EE9でネームスペースを変える理由**
　ApplicationServerやIDEなどの製品や環境の移行をスムーズに行うため

**Jakarta EE9で仕様の削除とオプション化するもの**
　削除対象（Java EE8でオプション化したもの）
　　- Jakarta XML Registries
　　- Jakarta XML RPC
　　- Jakarta Deployment
　　- Jakarta Management
　オプション化対象（次のVerで削除？）
　　- Jakarta Enterprise Bean 2.x and 1.x client view
　　- Jakarta Enterprise Web Services
　Java SE8からの移行追加仕様
　　- Jakarta XML Binding
　　- Jakarta Activation
　　　※Java SE8で削除されたものがJakarta EE9で復活する可能性あり

**その他Jakarta EE8からJakarta EE9での変更点**
・Jakarta EE9は、Jakarta EE8への後方互換性は保証しない
・仕様自体は変わらないが、各使用のバージョン番号が更新（インクリメント）される。
　例）Jakarta Servlet 4.0.3　→5.0

**Jakarta EE9のリリース内容**
　https://www.eclipse.org/lists/jakartaee-platform-dev/msg00702.html

###Jakarta EE8　補足

Java EE8～Jakarta EE9は変更がないため、長期間同じ仕様となる(2017～2020)

Jakarta EE8のチュートリアルはGlassFishのGithubにある
　https://github.com/eclipse-ee4j/jakartaee-tutorial（英語）

Jakarta EE8のサンプルアプリ開発（30分ほどでできる模様）
　kickstart a jakartaEE8 application
　https://medium.com/@hantsy/kickstart-a-jakarta-ee-8-application-d1b6ff32213b（英語）

#まとめ

- Jakarta EEはこれから10年、20年先まで使うエンタープライズjava標準
- Spring、MicroProfileやその他との使い分けは続く（連携の可能性あり）
- Jakarta EEはJava EEと同じ特質を持つことから、主な要件はミッションクリティカルであり長期的に運用可能であり、安定稼働すること
ローソンで買った冷凍お好み焼き（豚玉）を袋から出してから冷凍庫に仕舞うべき理由

　　　買って来た冷凍お好み焼き（豚玉）を『外袋から取り出してから冷凍庫にしまう』メリットを複数の論点から検証してみた。

　　　<a href=./0a2e3b8bbd41b75ef02e>-->関連記事</a>（qiitaに冷凍食品の保存ノウハウを展開し、凍結解除されるまで。）

#####１.Batch process
　　　日曜日に２パックの冷凍お好み焼き（豚玉）を買い、火曜日と木曜日に一つづつレンチンして食べる場合。
　　　→袋のまま冷凍庫に入れると、２回に分けて袋を破る必要性が生じる。
　　　→とりわけ、冷凍庫,レンジ,皿が近接した地点にあり、ゴミ箱だけが少し離れた場所にあるなら、冷凍庫およびレンジとゴミ箱との間を２往復しなければならない。
　　　→冷凍庫に入れる前に袋から出すのであれば、開ける手間、捨てる手間は一括で処理できる。

#####2.容量削減
　　　お好み焼き（豚玉）の袋の中には窒素と思われる気体が封入されており、また、丸い形状の中身を四角い外装で覆っているため、お好み焼き（豚玉）そのものの容量に比べ高度にかさ増しがされている。
　　　→冷凍庫というpreferentなcapacityに、カチカチの冷凍食品という決してFlexibleでないものを格納するprocessは、よりsensitiveに扱われるべきだ。
　　　→8sizeのdivision４つに5sizeのdetailは計4つしか格納できないが、一つひとつを4sizeに圧縮すれば２倍格納できる。

#####3.可視性
　　　調理されたお好み焼き（豚玉）のdynamicなgraphicsは販売者が店頭において購買者の購買意欲を刺激する意味でこそ効果を発揮するが、購買者が購買後に管理、識別する上では殆ど役に立たない。
　　　→それどころか、引き出し式ならともかく扉開閉式の冷凍庫に冷凍お好み焼き（豚玉）が正面を向いて収納される可能性は非常に低く、専ら側面がreference対象となり得る。
　　　→この場合、外袋にpackagingされたお好み焼き（豚玉）よりも、clearな包装を施されたoriginalのお好み焼き（豚玉）の方が瞬時に識別され易いのは言うまでもない。

#####4.Accessibility
　　　お好み焼き（豚玉）の外装は摩擦抵抗が強く、取り出す際、tightに密着した他のobjectをwrapしてしまう危険性がある。
　　　→それと比較して、内袋に使われている素材の摩擦係数は低く、隣接したobjectから容易にslideできる。
　また、気体とともに外袋に封入されたお好み焼き（豚玉）よりも、内袋だけの状態の方がより平面的で安定性もある。
　　　→例えば、お好み焼き（豚玉）の上に雪見だいふくを載せたまま片手で冷凍庫から取り出し、レンジの天面に置いた後に雪見だいふくだけを片手で戻すといったAdvanced controlも可能になる。

#####5.カプセル化
　　　ローソンの冷凍お好み焼き（豚玉）にはsauce,鰹節,青のりが同封されているが、これらが冷凍で保存される事の有用性は乏しい。
　　　→むしろ、souceなどは特に、レンチンする訳にもいかないし、せっかく温めたお好み焼き（豚玉）に冷たいまま掛けて味を損ねてしまうのは非常にナンセンスだ。
　　　→鰹節や青のりにも言える事だが、食べる直前にcold startさせるよりは常温のまま、お好み焼き（豚玉）そのものとは別途保存しておくのがベターだろう。
　　　買って帰ったその時に外袋から中身を取り出すことで、それが可能になる。

#####6.Indicating
　　　冷凍お好み焼き（豚玉）そのものと区別したsauce,鰹節,青のりを食器棚の奥に仕舞ったり、調味料の入った引き出しに無造作に放るとなれば本末転倒だ。できれば電子レンジの天面や、普段よく使っている皿の上にでもstand-byさせておきたい。
　　　→これらがindicaterの役割を果たし、冷凍庫の中にお好み焼き（豚玉）がある事をいつでもnotificationしてくれる。
　　　→ただし、sauceや鰹節を掛けるのを忘れ、別売のマヨネーズだけでお好み焼きを食べてしまった場合には、逐次正確な情報への修正とupdateが不可欠となる。

#####7.おわりに
　　　...以上を全て読んだ上で、尚も冷凍お好み焼き（豚玉）を袋から出さずにそのまま冷凍庫へ仕舞おうという人は、おそらくnative coder？（機械語をいじくっているという意味ではなく、apiを好まず力技に頼る暇人の意。）には向いていない。apiをフル活用し、効率的でストレスフリーなengineer lifeを送られたし。

　　　※冷凍お好み焼き（いかえび玉）についても同じ仮説と推論が成り立つのかも知れませんが、当方は魚以外の魚介類が嫌い（魚は大好き。蟹と鰻はいける。）なため検証できておりません。どなたか代わりにご検証の上、加筆頂ければ幸いです。
【SeleniumBasic】Chromeタイムアウトを変更する

この記事は、Excel+SeleniumBasic+GoogleChromeでスクライピングしている方に向けた記事です。

##driver.Timeouts.PageLoadの値=タイムアウト(ミリ秒)

driver.Timeouts.PageLoadの値を変更すると
任意のタイムアウト(ミリ秒)となる。

    Dim driver As New ChromeDriver
    URL = "任意のURL"
    driver.Timeouts.PageLoad = 10000   '10秒
    driver.Get URL

PageLoadを-1にするとタイムアウトなしとなる

    driver.Timeouts.PageLoad = -1　　　　'-1にするとタイムアウトなし

デフォルトは60000(60秒)である

    driver.Timeouts.PageLoad = 60000    '60秒(デフォルト)

Chromeの読み込みタイムアウトを変更する方法についての記事は以上です。
「procs：新しいプロセス表示・検索ツール」の更新紹介

# はじめに
ちょうど1年ほど前に「[procs：新しいプロセス表示・検索ツール](https://qiita.com/dalance/items/388d98c99ae2857d73e6)」の初期バージョンを公開しました。その後54回のリリースを経て、昨日v0.9.0になりました。
ちょうどきりがいいのでこの1年間のアップデート内容をまとめて紹介します。

# 特徴

[procs](https://github.com/dalance/procs)はpsコマンドの代替となるプロセス一覧の表示ツールです。主な特徴は以下の通りです。

* 色・単位付きの表示
* キーワードによる絞り込み
* psで表示できないカラムに対応
 * TCP/UDPポート
 * ディスクのRead/Write速度
 * Dockerコンテナ名
* ページャ対応
* topのような定期更新モード
* ツリービュー

![55446704-ab43a480-55fb-11e9-81dc-e3ac1a1e2507.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84296/5f0e5181-813b-e909-f8fc-a3d40117610a.png)


# アップデート

## Linux版の大幅な高速化
これは高速化を頑張ったというより異常に遅い箇所を見過ごしていたものです。最近気づいて修正したところ10倍ほど高速化しました。
体感できるレベルの差があるので、古いバージョンをご利用の方は最新版へのアップデートをお願いします。

## macOS/Windows対応
初期リリースではLinuxのみ対応でしたが、macOSとWindowsにも対応しました。ただしLinux版より表示できるカラムが若干少なくなっています。

## 各種パッケージ提供

いくつかのパッケージマネージャに対応して簡単にインストールできるようになりました。

* Nixpkgs
* snapcraft
* homebrew
* Alpine Linux
* Cargo

具体的なコマンドは[こちら](https://github.com/dalance/procs#installation)にまとまっています。

## 新しいカラム

psに存在しないカラムをいろいろ追加しました。一覧は[こちら](https://github.com/dalance/procs#kind-list)。
個人的にはDockerコンテナ名表示をよく使っています。

![55446681-91a25d00-55fb-11e9-943d-5b5caeb23c62.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84296/bad34783-51f1-5aee-e603-97c6962ca578.png)


## ページャ対応

出力をページャ（デフォルトはless）に通すようにしたので狭い画面でもスクロールするなどして見やすくなりました。
パイプを通す場合は自動で無効化されます。

## 定期更新モード
topコマンドのように定期更新されるモードを追加しました。
`procs -w 10`で10秒ごとに更新されます。
キー入力でソートするカラムを変更できることもできます。

## ツリービュー
プロセスの依存関係をツリーで表示することができます。

![55446692-9ff07900-55fb-11e9-8b66-a8432df0a8e1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84296/9f6937b4-b1eb-5837-042a-d998cbe1dda3.png)
Vue.jsかNuxtJSでassetsに入れた画像を動的に表示させる

# 環境
- NuxtJS v2.11.0
- TypeScript v3.7.5

# 問題
リストで管理している画像ファイルを動的に書いてもうまく表示されない

# コンポーネント部分
以下のように画像のファイル名リストを文字列で持っていたとする。

```ts
import { Vue, Component, Prop } from 'vue-property-decorator'
@Component({})
export default class ImageUnit extends Vue {
  @Prop()
  imageNames: Array<string>
}
```

# テンプレート部分

```html
<template>
  <dl>
    <dt>Image: </dt>
    <dd v-for="(imageName, index) in imageNames" :key="`image-${index}`">
      <img :src="`@/assets/${imageName}`" alt="`image-index`">
    </dd>
  </dl>
</template>
```

このように書いても、HTMLに直接上記のURLが表示され、画像は出なかった。
staticディレクトリに入れるという手もあるが、Nuxtで管理できないのは困るので別の方法を考えた。

## 解決策
以下のURLを参考にし、一度モジュールをバインドすればOK。
正常に`/_nuxt/assets/hogehoge.png`画像が表示された。

https://ja.nuxtjs.org/guide/assets/#webpack

```html
<template>
  <dl>
    <dt>Image: </dt>
    <dd v-for="(imageName, index) in imageNames" :key="`image-${index}`">
      <img :src="require(`@/assets/${imageName}`)" alt="`in-${index}`">
    </dd>
  </dl>
</template>
```
Mac標準のリモート接続でラズパイに繋ぐ方法

![vnc_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/8e2e39a7-00da-e43b-ab9c-987b41f3160e.png)

# Mac標準のサーバへ接続でラズパイに接続
　Macには標準でリモート接続機能があります。メニューの「移動」->「サーバに接続…」 or 「Command+K」で起動できます。

<img width="613" alt="vnc_02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/5e1453ec-1eea-9b8e-8150-93acb9cfdba0.png">

　~~VNCやSambaで接続できて、とても便利なのですがラズパイにリモート接続（VNC）しようとすると、Raspbain標準のRealVNCには接続できないという問題があります。~~

　Raspbian標準のRealVNCでも設定を変えるだけで、リモート接続できます。本記事のコメント欄に記載がありますので参考にしてみて下さい。こちらが一番簡単で手軽だと思います。

　ここから先は、TightVNCというVNCソフトをセットアップする方法です。よく設定する割にやり方を忘れるので、自分のメモのためにソフトのインストールから、自動起動の設定までをスクリプト化して記事にまとめました。

## ラズパイへのTightVNCセットアップ
　以下2行で、インストールから自動起動の設定が一気に行われます。

```sh
$ git clone https://github.com/karaage0703/raspberry-pi-setup && cd raspberry-pi-setup
$ ./setup-tightvncserver.sh
```

　途中、VNC接続の際のログインパスワードを求められるので、パスワードを入力(Input)と確認(Verify)の2回入力して下さい。

　その後に聞かれる、見るとき専用のパスワード（View only password）は、「N(No)」でスキップしてOKです。

　最後に再起動したら、後はMac標準のリモート接続機能で接続できるようになります。

　「Command+K」で以下の画面が起動します。

<img width="613" alt="vnc_02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/5e1453ec-1eea-9b8e-8150-93acb9cfdba0.png">

　ラズパイのIPアドレスが、192.168.0.100だったら、以下の通り入力して下さい。

```
vnc://192.168.0.100:5901
```

　ホスト名でも接続可能です。ラズパイのホスト名が「raspberrypi」のときは以下となります。

```
vnc://raspberrypi.local:5901
```

　パスワードを聞かれるので、TightVNCを設定したときに入力したパスワードを入力して下さい。

　成功したら、以下のようにリモート接続ができます。

![vnc_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/8e2e39a7-00da-e43b-ab9c-987b41f3160e.png)

## 初心者向け・ハマった時の情報
　上記のスクリプトで何をやっているか知りたい。うまく設定できないという方は、以下の記事を読むと解決するかもしれません。初心者向けに丁寧に解説がされています。

[macOSとRaspberry Pi でVNC通信はFinderでOK](https://raspida.com/tightvnc-mac2rpi)


## まとめ
　Mac標準のリモート接続で、ラズパイにリモート接続する方法を簡単にまとめました。

　今回のようなちょっとしたテクニックの他、ブログでラズパイで作ったものを公開などしているのでよろしければこちらもご覧下さい。

[Raspberry Piで作ったもの・やったことまとめ](https://karaage.hatenadiary.jp/entry/2015/09/10/073000)


## ラズパイ標準のRealVNCで接続する方法
　コメントにもあるように、ラズパイの標準のVNCでも、設定を変えることでMac標準のリモート接続でつなぐことができました。具体的な手順は、コメントを参照ください。

　アドレスにポート番号は不要で `vnc://raspberrypi.local`で接続できます。

<img width="613" alt="vnc_mac_raspi.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/5fda4a26-a390-cade-11e1-f6a8b1a27116.png">

　設定後は、再起動しましょう。再起動しないと「リモートコンピュータのソフトウェアが、このバージョンの画面共有と互換性がないようです。」というエラーが出る場合がありました。

　自分の環境でRealVNCのOptions画面を開こうとすると`Unable to configure options for VNC`と表示される問題が発生したときもありました。xtermに依存があるらしく、xtermをインストールすると治りました。コマンドは以下です。

```sh
$ sudo apt install xterm
```

参考： [Unable to configure options for VNC Server](https://oss.alanood.ae/knowledgebase/209/Unable-to-configure-options-for-VNC-Server---UNIX.html?language=danish)

## 関連記事
https://qiita.com/karaage0703/items/f133eacf166ee76a07f2

## 変更履歴
- 2022/02/14 再起動に関して追記
(Ruby2.7.0 )Ruby on Railsをうまくインストール出来ないとき(Windows)

#WindowsでRuby2.7.0を使っているとRailsのインスールが出来ない（2020.1.24）
Progateが一通り終わって、**Ruby on Railsの環境構築**をしようとしたらエラーが表示されて**インストールがうまくいかない。**


それはなぜか。


**Ruby2.7.0にnokogiriのバージョンが追いついていないから！！！**

エラーメッセージ（コピペし忘れた）を読んでみると、
**「お前のバージョンだとRuby2.3までしか対応してねーよ。nokogiriのバージョンを1.8.5にあげやがれ**（確か1.8.5。細かい数字はうろおぼえ）。」
みたいなことが書かれていた。

ということでまずnokogiriのバージョンを上げた。

```tarminal
gem install nokogiri -V '1.8.5'
```
よし、これでRailsをインストールできる！！！！

```tarminal
gem install rails
```

...またエラー出た。

今度は
**「お前のnokogiriのバージョンだとRuby2.6までしか対応してねーよ」**
みたいなことが書いてある。。。



エラーメッセージを見てみると（コピペするの忘れてた)、
**「nokogiriの最新バージョンがRuby2.6までしか対応していないよ」**

と、いうようなメッセージが表示された。

よし、じゃあRubyのバージョンを2.6に下げよう。
ということで色々調べた結果、**uru**というサービス？アプリ？を入れるとバージョンが簡単に変更できるらしい。
**（他にもあるけどこれが一番簡単）**

ということで、
[WindowsのRubyのバージョンをuruで切り替える方法【初心者向け】](https://techacademy.jp/magazine/18732)
を見ながら**ulu**をインストール。

**↑↑**

```
uru admin add C:\Ruby21-x64\bin --tag Ruby21
uru admin add C:\Ruby22-x64\bin --tag Ruby22
```
ここの記述を

```
uru admin add C:\Ruby26-x64\bin --tag Ruby26
```

**Ruby26に書き換える**

そしてバージョン変更したいと書く。

```
uru ruby26
```
変更完了！！！
あとは

```
gem install rails
```

いっけーーーーーーー

```
Fetching thread_safe-0.3.6.gem
Fetching zeitwerk-2.2.2.gem
Fetching rack-2.1.1.gem
Fetching activesupport-6.0.2.1.gem
Fetching concurrent-ruby-1.1.5.gem
Fetching tzinfo-1.2.6.gem
Fetching rack-test-1.1.0.gem
Fetching i18n-1.8.2.gem
Fetching mini_portile2-2.4.0.gem
Fetching nokogiri-1.10.7-x64-mingw32.gem
Fetching crass-1.0.6.gem
Fetching loofah-2.4.0.gem
Fetching rails-html-sanitizer-1.3.0.gem
Fetching rails-dom-testing-2.0.3.gem.......................
```

できてるっぽい！！！！

最後に確認のため、

```
rails -v
```
そうすると

```
Rails 6.0.2.1
```

うおおおおおおおおおお
できたーーーーーーーーーー

##環境 = Windows + Ruby2.7.0　で使っている人で困っていたら参考にしてみてください！！！！！
レスポンシブ設計　キホンの基本　part1~display:flex;


CSSでレスポンシブなサイト作成のキホンについてやっていきますが、

その中でも超基本から。

このような構図があったとします。![スクリーンショット 2020-01-24 1.02.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572382/efe8672a-e055-aebb-b5b0-0d46772a4bd0.png)
※見にくいかもしれませんがcontainerは青色の部分を指しています。

この図のように、何もしないと要素は縦並びになってしましますよね。

レスポンシブにするためにはまず親要素のcontainerにdisplayをflexを設定します。

ちなみに、子要素の幅(width)は均等にするため、各子要素にflexを１に設定します。




```style.css
 .container {
display: flex;
}
.boxA {
flex: 1;
}
boxB {
flex: 1;
}
```
そうすると、こうなります。![スクリーンショット 2020-01-24 1.15.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572382/a1eaf4d4-b97a-658f-99e1-6b50f6178be6.png)

子要素が横並びになます。

デフォルトでは子要素の高さ(hieght)は同じで、幅(width)はコンテンツによって変わります。

今回の場合は、flex:1;を設定しているので、幅は均等です。

これがレスポンシブのキホンの基本です。

では次回は親要素のcontainerの幅を設定して、折り返す方法を書いていきたいと思います。

→ 続き：　https://qiita.com/zakaryo/items/25bf9ee73cbf52167262
Gitコマンド実行時に、XcodeとiOSのライセンス同意を求められた場合の解決法 

#起きたこと
GithubからLaradocのファイルをコピーしようとするエラーが出た。

```
Agreeing to the Xcode/iOS license requires admin privileges, please run “sudo xcodebuild -license” and then retry this command.
```

ライセンスに同意してくれと言われる。

#解決策
エラーコードにもあるように、sudo xcodebuild -licenseを叩く

```
$ sudo xcodebuild -license
```
パスワードを聞かれるので、入力。下記が表示される。

```
You have not agreed to the Xcode license agreements. You must agree to both license agreements below in order to use Xcode.

Hit the Enter key to view the license agreements at '/Applications/Xcode.app/Contents/Resources/English.lproj/License.rtf'
```
『Xcodeのライセンス契約に同意していません。 Xcodeを使用するには、以下の両方のライセンス契約に同意する必要があります。 Enterキーを押して、「/ Applications / Xcode.app / Contents / Resources / English.lproj / License.rtf」にあるライセンス契約を表示します』
と書いてあるので、Enter押下。

ライセンス契約がEnter押下で読み進める。全部英語でむちゃくちゃ長い。

```
By typing 'agree' you are agreeing to the terms of the software license agreements. Type 'print' to print them or anything else to cancel, [agree, print, cancel] 
```
『「同意する」と入力すると、ソフトウェア使用許諾契約の条項に同意したことになります。 それらを印刷するために「印刷」と入力するか、キャンセルする他の何か、[同意、印刷、キャンセル]』

上記が出たら、agreeを入力し、Enterを押下。

```
You can view the license agreements in Xcode's About Box, or at /Applications/Xcode.app/Contents/Resources/English.lproj/License.rtf
```
『ライセンス契約は、Xcodeのバージョン情報ボックス、または/Applications/Xcode.app/Contents/Resources/English.lproj/License.rtfで表示できます。』

再度、Gitコマンドを打ってみると実行できました！
【解決策】formにカラムが設定されない！？

Webアプリを開発していて、routesとcontroller、viewを何度も見直したのにformを検証で見てみると何故かカラムが設定されない時に以下の方法で解決しました。

#before
      = form_with model: @message, url: job_messages_path(@job), local: true do |f|
        = f.text_field :text
#after
      = form_with model: @message, url: job_messages_path(@job), local: true do |f|
        = f.text_field :text, name: "message[text]"

下の行に、name:"テーブル名[カラム名]"を書き足せばカラムが設定され、値を入れることができました!!
GCPのセミナーに参加してきました【備忘】


# はじめに
今日（1/23）に[クラウドエース社のGCPのセミナー](https://www.cloud-ace.jp/event/200123/)に参加してきました。
最初に断っておくとこれはセミナーレポートではなく、セミナーの内容で重要だと思ったり、セミナーに関連して調べたことをまとめる備忘記事です。

ちなみに自分はGoogle Cloud Platform（以降GCP）はほぼ素人です。
（昔AWSの案件だと聞いて面接に行ったらガッツリGCPの案件で、軽く門前払いされたことがあるぐらいです）

# Google Cloudとは
Google Cloudは大きく下記2つで構成されています。
① Google Cloud Platform（クラウドのコンピューティングサービス）
② G Suite（グループウェアサービス。GmailやGoogle Driveなど）

今回のセミナーは①についてでした。

# GCPの強み
① 全世界のリージョンとプライベートネットワークで接続されている
　※つまり、他リージョンへの通信でもパブリックネットワークに出ないので、セキュリティが高い
② ライブマイグレーション機能によりメンテナンスでのダウンタイムが発生しない。
　※たとえばAWSではパッチ適用などのメンテナンスを行う場合、メンテナンスウィンドウで停止時間を指定する通知がある
　※また、GCPはGoogle自前のサーバー筐体で稼働しており、世界有数のH/Wメーカーでもある（3位とか4位と言っていた）
③ BigQuery（DWH）はインスタンスを起動せず、クエリ単位での課金となるため、他社クラウドに比べてコストメリットがある

あとはAI（Cloud AutoMLなど）に力を入れていたり、オンプレやマルチクラウド上のアプリケーションを一元管理するサービス（Anthos）を売りにしているようです。

[Cloud AutoML](https://cloud.google.com/automl/?hl=ja)
[Anthos](https://cloud.google.com/anthos/?hl=ja)

# GCPの勉強方法
オンラインコンテンツとしてはcourseraが一押しのようです。
月額のサブスクリプションで、大半が英語（日本語は一部）のコンテンツですが、日本語字幕もあってなかなか有用そうでした。

https://ja.coursera.org/

あとはQwiklabでハンズオンができるので、実践訓練としてはオススメとのこと。
https://www.qwiklabs.com/?locale=ja

それ以外だとCloud OnAirというGoogleのエンジニアがサービスの説明をするライブ動画もあるそうです。
ちょうど今日（1/23）もやっていたので観ましたが、Chronicle Backstoryというセキュリティサービスについて解説とデモをやっていました。

https://inthecloud.withgoogle.com/jp-onair-19/archive.html


# その他（今後について）
自分としてのベースはAWSに置きたいと思っていますが、せっかくなのでGCPのアソシエイト資格ぐらいは取りたいと思っています。
勉強時間としてはGCP専業のクラウドエースの人が平均1ヶ月ぐらいと言っていたので、アソシエイト資格と言ってもエントリーレベルのさっと取れるようなものではないと思うので、気長にやっていこうと思います。
transformについて[html, css]

#はじめに
「transformは何ができるのか」
「transformはどんな時に使うのか」
ということについて書いていきたいと思います。

transform自体を使ったことがない人も多いと思いますが、
Webデザインをしていく中で必ず目にすることになると思います。

そんなtransformについてまとめていきたいと思います。

#transformについて
transformを使用することによって、デザインに移動、回転、伸縮、傾斜の効果をつけることができます。二次元的な動きだけではなく、三次元的な動きにも対応しています。

#transformの種類
transformには4つの関数が用意されています。

1. translate()　「移動」
2. rotate()　「回転」
3. scale()　「伸縮」
4. skew()　「傾斜」

#transformの使い方
それぞれの関数にX,Y,Z,3Dが用意されています。
`translateX()`のように()の前にX,Y,Z,3Dを記入することでその軸に対して関数を使用することができます。
また、`translate(X,Y,Z)`のように記入してもそれぞれの軸に対して関数を使用することができます。

```html:index.html
<div class="transform">Transform<div>
```
```css:style.css
.transform{
    padding: 10px 20px;
    background: #59b1eb;
    text-align: center;
    color: #fff;
    width: 30%;
}
```
このhtml,cssに対して、transformを使用していきたいと思います。
わかりやすくするために`:hover`,`transition`を使用していきたいと思います。
hoverはカーソルを要素に置いた時に適用されるようにする要素です。
transitionはtransformを適用するにあたり、開始から終了までの時間を決めることができます。
###translate
translateは要素に移動の効果を追加することができます。

```css:style.css
.transform{
    padding: 10px 20px;
    background: #59b1eb;
    text-align: center;
    color: #fff;
    width: 30%;
    transition: 1s;
}

.transform:hover{
    transform: translate(20px,20px)
}
```
`.transform`に`transition: 1s;`を追加し
`.transform:hover{
    transform: translate(20px,20px)
}`を新たに追加しました。
動きを確認してみてください。
Ｘ軸方向に20px、Ｙ軸方向に20px動くのが確認できたかと思います。
###rotate
rotateは要素に回転の効果を追加することができます。

```css:style.css
.transform:hover{
    transform: rotateX(360deg)
}
```
rotateを使用する場合`px`ではなくdegree「度」を表す
`deg`を使用します。
このコードの場合Ｘ軸に対して360度回転します。確認してみてください。

```css:style.css
.transform:hover{
    transform: rotateY(360deg)
}
```
この場合Ｙ軸に対して回転するのが確認できるかと思います。
###scale
scaleは要素に伸縮の効果を追加することができます。

```css:style.css
.transform:hover{
    transform: scale(1.5,1.5)
}
```
値には`px`も`deg`も使用しません。
1.5と書けば要素の1.5倍、2.0と書けば要素の2倍になります。また、-2.0と書けば要素の1/2倍になります。
このコードではＸ軸、Ｙ軸共に1.5倍になるのが確認できると思います。
###skew
skewは要素に傾斜を持たせることができます。
他の要素と異なり、Ｘ軸Ｙ軸に対してしか使用できない特徴があります。また、値には`deg`を使用します。

```css:style.css
.transform:hover{
    transform: skew(30deg,30deg)
}
```
他の要素と異なり、Ｘ軸Ｙ軸に対してしか使用できない特徴があります。また、値には`deg`を使用します。

###transform-originについて
`transform-origin`を使用することによって、要素の変化の基準点を設けることができます。

```css:style.css
.translate:hover{
    transform: rotate(45deg);
    transform-origin: top left;
}
```
基準点の設定方法ですが、
-　絶対指定（px）
-　相対指定（%）
-　位置指定（top, center,left等）

の3つがあります。
ざっくりで良いなら位置指定、細かく決めたいなら絶対指定、相対指定を使用するという風に分けたら良いと思います。
![transform-origin_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551593/1cc9a5a1-c9e2-36e6-446f-7510e2d905de.png)

#まとめ
transformはマスターするとWebデザインの幅がとても広がります。
基礎的な使用方法でも十分幅が広まります。
ぜひマスターしましょう。
windows 増設したHDDに書き込むとき異常に重くなる

# 結論
ウイルス対策ソフトが悪かった
ウイルス対策ソフトをアンインストールすると直った

# 症状
*  増設したHDDに大量のファイルを書き込もうとすと速度50MB~0KBといったように安定しない
*  書き込みが始まると何もできないぐらい重たい
*  書き込みが99%で止まる
*  書き込みキャンセルしても重い状態が続く
*  しかしzipやrarなどで圧縮して書き込むと通常通りのスピードで書き込める
*  書き込む意外に増設したHDDの中の大きなファイルを削除したり移動しても変化はみられない
*  増設したHDDからOSが入ったHDDにファイルを写しても遅くはならない
*  タスクマネージャーやリソースモニターをみても読み取り書き込みでディスクを混乱させているものは見当たらない(windows updateが悪いならここでわかる)

# 考察
外部への書き込みだけしかも複数となる、それに加え書き込む速度が安定しないことからファイル一つ一つが何かを読み込んでいるとしか考えられた。結果裏で動いているのはウイルス対策ソフトぐらいなものだったのでタスクを落とそうとしたのだが落ちなかったのでアンインストールすることにした。結果この症状はなくなった。
NATについて無知だったので少し調べた

# NATってなに？
「NAT越え」「NATの設定を...」などは聞いたことがあったが、実際に「NATが...だから...だよね?」って聞かれて困ったので少し調べた。

## NATの役割
そもそもNATとはNetwork Address Translationの略でIPアドレスを変換する技術である。Network Address Translationという名前がとてもわかりやすい。
一般的には企業内のLANのプライベートIPアドレスをインターネット内の識別子であるグローバルIPアドレスに変換する際に使われる。

ここまではなるほど、「確かにそうだな。プライベートIPで通信しないよなー。」ってなりました。

しかし、ここで思ったのが、**「パケットは飛んでいくけど、パケットが帰ってくるとき、どこに帰ってきたらいいかわからなくね?」**ということでした。

LANの中のノードからNATを経由してインターネットへパケットを出すときは、相手のグローバルIPアドレスを指定しているため問題なくパケットは届くものの、相手からパケットが帰ってくるときには行きで使ったNATまでは帰ってくるものの、そこからNATさんが「どこにこのパケット送ったらいいの???」ってなってしまいそうです。

## NAPT

この問題を解決したのが、NAPT（Network Address Port Translation）です。NATにPortという単語が入ってきました。言葉の通り、LAN内のノードがNATを経由してインターネットと通信を行う際に、それぞれのノードにポート番号を振ることで、LAN内のPCを識別するというものです。

これで、LAN内のノードの識別を行うことができるようになったため、1対多の通信を行うことができるようになりました。NATではこの識別ができなかったため、1対1の通信しか行うことができませんでした。

##本当にNATは1対1の通信しかできないのか?
「NAPTを使わないと、1対多の通信はできないのか。NATってしょぼいのか。。。」と思ったがそうではないらしい。

### 動的NAT
動的NATでは、１つまたは複数のグローバルアドレスをNAT用に割り当て、LANからインターネット側へ通信しようとするホストへ先着順で1対1のペアとして変換します。
割り当てたグローバルアドレスの数と同数のノードが同時にインターネットとの通信可能することができるようになります。

NATに割り当てられたグローバルIPアドレスよりLAN側へ通信しようとするノードのほうが多く、グローバルアドレスがすべて使用されているときは、プライベートIPアドレスとグローバルIPアドレスの関連付けができません。そのため、
既存のセッションが終了すると、また先着順で空いたグローバルIPアドレスと1対1のペアとして関連付け、アドレス変換処理が行われます。

## まとめ
プライベートIPアドレスとグローバルIPアドレスがLANからインターネットに通信するときに、変換されるのは知っていたが、その役割を持っていたのがNATさんであることがわかった。
LocalStack で AWS CLI の練習をする

[LocalStack](https://github.com/localstack/localstack) とは、AWS のリソースのモックをローカルに作成するツール。
LocalStack は AWS CLI の練習をするのに最適なのではと思い立ち実験してみた。


## 前提

- Docker がインストールされていること
- AWS CLI がインストールされていること（AWS CLI のイメージへのエイリアスでも可）


## LocalStack のコンテナ作成

LocalStack の Docker イメージを使用することでコマンド1発で LocalStack 環境が出来上がる。

```bash
docker run -itd --rm -p 4566:4566 localstack/localstack:latest
```

**※ docker run のオプションの説明**

- `-itd` : `-i -t -d` の略。ざっくり言うと「バックグラウンド」で「起動しっぱなし」にする
- `--rm` : コンテナ停止時にコンテナを削除
- `-p` : ホストとコンテナとのポート疎通設定。 `4566:4566` は「ホストの 4566 ポート」と「コンテナの 4566 ポート」を疎通させる設定


## 動作確認

localstack で作成されたリソースは http://localhost:4566 に公開される。（ localstack v0.11.0 からの変更点）
`--endpoint-url=http://localhost:4566` を設定することで localstack で作成されたリソースにアクセスできる。

※ [AWS CLI の Docker イメージ](https://hub.docker.com/r/amazon/aws-cli) を使用している場合、 `localhost` でホストOSにアクセスできないため、以下の手順の `localhost` を  `host.docker.internal` に読み替える。

### パラメータストア作成

```bash
aws ssm put-parameter \
    --name sample-param \
    --value sample-value \
    --type String \
    --endpoint-url=http://localhost:4566
```



### パラメータストア取得

```bash
aws ssm get-parameter --name sample-param --endpoint-url=http://localhost:4566
```



### S3 バケット作成

```bash
aws s3 mb s3://sample-bucket --endpoint-url=http://localhost:4566
```



### S3 バケット一覧取得

```bash
aws s3 ls --endpoint-url=http://localhost:4566
```



### S3 ファイルアップロード

```bash
touch test.txt
aws s3 cp test.txt s3://sample-bucket/ --endpoint-url=http://localhost:4566
rm test.txt
```



### S3 バケット内のオブジェクト一覧取得

```bash
aws s3 ls s3://sample-bucket --endpoint-url=http://localhost:4566
```



### S3 バケット内のオブジェクト削除

```bash
aws s3 rm s3://sample-bucket/test.txt --endpoint-url=http://localhost:4566
```

## まとめ
- LocalStack を使えば AWS CLI を試す環境が簡単に作れることが分かった
- 一部 AWS サービスのモックは 有料版 LocalStack が必要になるが、主要サービスは無料版で十分まかなえる
- LocalStack で心置きなくコマンドを実行して AWS CLI に慣れていきたいと思う


## 参考ページ

- `docker run` のリファレンス
    https://docs.docker.com/engine/reference/commandline/run/

- LocalStack のリポジトリ
    https://github.com/localstack/localstack

- `aws ssm` のリファレンス
    https://docs.aws.amazon.com/cli/latest/reference/ssm/index.html

- `aws s3` のリファレンス
    https://docs.aws.amazon.com/cli/latest/reference/s3/index.html

- host.docker.internal の説明
    https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds
【C++Builder】TDBGridから選択した1行の情報を取得する方法

データベースはMySQLを使用。
事前準備は[こちら](https://qiita.com/taka_tofu/items/ee828a895161e6a64bde)を参照

## そもそもやりたかったこと

- DBGridに表示させた表から1行選択したい
- 選択可能なのは1行のみ
- 選択した行の情報を取得したい

ただ、1行選択して選択した行にある情報を参照したいだけなのに、情報がほとんどなくて困ったのでメモしておく。

## やり方

- TDBGridのプロパティからOptionを選択する。**dgRowSelect**をTrueにする。**dgMultiSelect**はFalseにする。これで、1行のみ選択できるようになる。


- 数値の取得方法

```
int id=DBGrid1->DataSource->DataSet->FieldByName("id")->AsInteger;
```
FieldByNameのパラメタにはカラム名を渡す。

- 日付の取得方法

```
TDateTime date=DBGrid1->DataSource->DataSet->FieldByName("regdate")->AsDateTime;
```

- 文字列の場合

```
AnsiString str=DBGrid1->DataSource->DataSet->FieldByName("name")->AsAnsiString;
```
Land of Lisp 13章（Web サーバを作ろう！）でhello-request-handlerを正しく表示する方法

（**2020年2月3日追記**：コードの後半を修正、19章のdod-request-handlerの記述を追加）

# 現象
Land of Lispの13章は、ローカルでWebサイトを立ち上げることが目標になっているが、リクエストハンドラを本に載っている通り以下のコードを書いてしまうと、2020年現在、macOS Catalina環境下では、Chromeでは「127.0.0.1 から無効な応答が送信されました（ERR_INVALID_HTTP_RESPONSE）」というエラーが返ってきてしまい、FirefoxではHTMLコードがそのまま画面に表示されてしまう。
15章以降では、Webサーバが正しく立ち上がる前提で話が進むので、ここで詰まってしまうとコードを走らせることができなくなってしまう。

```scheme
(defun hello-request-handler (path header params)
  (if (equal path "greeting")
      (let ((name (assoc 'name params)))
	(if (not name)
	    (princ "<html><form>What is your name?<input name='name' />
</form></html>")
	    (format t "<html>Nice to meet you, ~a!</html>" (cdr name))))
      (princ "Sorry... I don't know that page.")))
```

# 解決法
以下の記事で起きている現象と性質は同様で、解決法も同じであった（lambdacadabraさんに深謝）。
https://lambdacadabra.blogspot.com/2016/11/land-of-lispwebfirefox.html
主要なコードの変更点は、**HTMLコードの前にレスポンス行と改行を2つ出力するようにした**という点。
それに応じて、URL相違の際に表示されるテキストの前後にもhtmlタグを追加している。
これで、Chrome, Firefoxいずれでも正しく表示されるようになった。
記事中では「ChromeではHTMLがきちんと解釈されて入力フォームなどが普通に表示される」とあるが、記事投稿時（2016年）の後Chromeの仕様変更があり、エラーを吐くようになったのかもしれない。

```scheme
(defun hello-request-handler (path header params)
  (if (equal path "greeting")
      (let ((name (assoc 'name params)))
	(if (not name)
	    (progn ; 追加
	      (princ "HTTP/1.1 200 OK") ; 追加
	      (terpri) ; 追加
	      (terpri) ; 追加
	      (princ "<html><form>What is your name?<input name='name' />
</form></html>"))
	    (progn ; 追加
	      (princ "HTTP/1.1 200 OK") ; 追加
	      (terpri) ; 追加
	      (terpri) ; 追加
	      (format t "<html>Nice to meet you, ~a!</html>" (cdr name)))))
      (progn ;; Added
        (princ "HTTP/1.1 200 OK") ;; 追加
        (terpri) ;; 追加
        (terpri) ;; 追加
        (princ "<html>Sorry... I don't know that page.</html>")))) ;; 変更

```

# 参考：19章に登場する同様のハンドラ（dod-request-handler）の修正方法
19章で書くDice of Doomのハンドラにも同様の変更が必要なので、下記に変更後のコードを記しておく。

```scheme
(defun dod-request-handler (path header params)
  (if (equal path "game.html")
      (progn (princ "HTTP/1.1 200 OK") ;; 追加
	     (terpri) ;; 追加
	     (terpri) ;; 追加
	     (princ "<!doctype html>")
	     (tag center ()
	       (princ "Welcome to DICE OF DOOM!")
	       (tag br ())
	       (let ((chosen (assoc 'chosen params)))
		 (when (or (not *cur-game-tree*) (not chosen))
		   (setf chosen nil)
		   (web-initialize))
		 (cond ((lazy-null (caddr *cur-game-tree*))
			(web-announce-winner (cadr *cur-game-tree*)))
		       ((zerop (car *cur-game-tree*))
			(web-handle-human
			 (when chosen
			   (read-from-string (cdr chosen)))))
		       (t (web-handle-computer))))
	       (tag br ())
	       (draw-dod-page *cur-game-tree* *from-tile*)))
      (progn (princ "HTTP/1.1 200 OK") ;; 追加
	     (terpri) ;; 追加
	     (terpri) ;; 追加
	     (princ "<html>Sorry... I don't know that page.</html>")))) ;; 変更
```
matplotlibの散布図で連続的に色付けをする

matplotlibの散布図を連続的に色付けする方法のメモ．

ポイントとしては
1. cmapを用いて連続する実数をRGBの連続値に変換する
2. `plt.scatter()`で提供されている`facecolors`や`edgecolors`の引数を使う
の２つです．

(20/01/24 10:34追記)
コメントでもっと簡単な方法を教えていただき，下のコード例を修正しました．
@kochory さん、ありがとうございます！


## コードの例

回帰問題用のデータセットBoston housingの低次元埋め込みと目的変数(今回の例では物件価格)を散布図で可視化しました．

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.manifold import TSNE

X, y = load_boston(return_X_y=True)
tsne = TSNE(n_components=2, random_state=0)
embX = tsne.fit_transform(X)

# 20/01/24 10:34 頂いたコメントをもとに修正
plt.scatter(embX[:, 0], embX[:, 1], c=y, cmap='coolwarm')

# 以下は追記前のコードです
# ポイント1: yをRGBAの配列に変換する
#cm = plt.get_cmap('coolwarm')   # matplotlibのcolormapを取得
#normalized_y = (y -y.min()) / (y.max() - y.min())   # 目的変数yを0~1に正規化
#color_levels = (normalized_y * 256).astype(int)     # yをさらに0~255に変換
#colors = [cm(cl) for cl in color_levels]            # cm(cl)はRGBAのtupleを返す 
# ポイント2: facecolorsの引数を指定する
#plt.scatter(embX[:, 0], embX[:, 1], s=10, facecolors=colors)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118119/2b29be43-86c4-2ee7-74ed-620e3b6dd15d.png)


## 参考URL
- cmapの一覧: https://matplotlib.org/examples/color/colormaps_reference.html
【C++Builder】TDBGridで表示するカラム名を任意の文字に変更する

データベースはMySQLを使用。

## やりたかったこと
データベースから取得した情報をTDBGridに表示させると、データベースのカラム名がそのまま表示されてしまう。そのままだとユーザが分かりにくいので、名称を変更したい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/13b093eb-38c8-96f0-346b-453e4372dddd.png)


## 設定方法

1. TFDConnectionのプロパティConnectedをtrueにする
2. TFDQueryのアイコンをダブルクリックし、FireDACクエリエディタを表示する
3. 表示したいテーブルのSelect文を書く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/4d020262-30ae-1776-d73f-c5378d77e594.png)
4. TFDQueryのプロパティActiveをtrueにする。SQL文の実行結果が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/25956c02-14ab-22ec-5e74-3a43f1f5d049.png)

5.TDBGridをダブルクリックする。Columnsの編集ウィンドウが表示されるので、「すべてのフィールドを追加」ボタンを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/8475e0b6-eb18-8d6c-5a32-bcf95cb442db.png)

6.表示文字列を変更したい項目を選択し、プロパティのTitle.Captionを変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/26fb4943-bff6-677d-3788-c84bd2576d37.png)

変更されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/af951ce1-e87f-c0ea-f507-a71815bd366f.png)
時系列データから取り出せる特徴量

時系列データを分析する際に、部分時系列を取り出して特徴量を取り出すということをする場合があります。下記のような特徴量を抽出することが出来ます。

```python
from scipy import fftpack, signal
import scipy
import numpy as np
import matplotlib.pyplot as plt


def pentropy(y, fs):
    f, Pxx = signal.periodogram(y, fs)
    pk = Pxx / np.mean(Pxx)
    S = scipy.stats.entropy(pk)
    return S


def generate_features(y, x, fs=1, order=5):
    """
    Parameters
    ----------
    y : np.ndarray
        波のデータ
        
    x : np.ndarray
        時刻など
    
    fs : int
        サンプル周波数
    
    order : int
        ピーク検出の間隔

    Returns
    ----------
    np.ndarray
        特徴ベクトル
    """
        
    # norm
    L1 = np.linalg.norm(y, ord=1)
    L2 = np.linalg.norm(y, ord=2)
    
    # mean
    mean = np.mean(y)
    
    # Standard deviation
    std = np.std(y)
    
    # skewness
    skew = scipy.stats.skew(y)
    
    # kurtosis
    kurtosis = scipy.stats.kurtosis(y)
    
    # mad
    mad = np.linalg.norm(y - mean, ord=1)
    
    # percentile
    percentil_calc = np.percentile(y, [0, 1, 25, 50, 75, 99, 100])
    
    # relative_percentile
    relative_percentile = percentil_calc - mean
    
    # value range
    max_range = percentil_calc[-1] - percentil_calc[0]
    
    # asymmetry
    v_max = relative_percentile[-1]
    v_min = relative_percentile[0]
    asymmetry = v_max + v_min

    # ピーク値のインデックスを取得
    maxid = signal.argrelmax(y, order=order)  # 最大値
    minid = signal.argrelmin(y, order=order)  # 最小値
    
    # max height of peaks
    max_height = np.max(y[maxid])
    
    # min height of peaks
    min_height = np.min(y[minid])
    
    # peak height diff
    peak_width = max_height - min_height
    
    # mean value of peak's width
    x_p = np.append(x[maxid], x[minid])
    mean_width_all = np.mean(x_p)
    
    # number of peaks
    num_peak = len(x_p)
    
    # max, min and their diff, mean of peak's width
    diff1 = np.diff(x_p)
    width_max = np.max(diff1)
    width_min = np.min(diff1)
    width_diff = width_max - width_min
    width_mean = np.mean(diff1)
    width_median = np.median(diff1)
    
    # spectral entropy
    se = pentropy(y, fs)

    # merge to features (15features)
    features = np.concatenate([np.asarray(
        [L1, L2, mean, std, skew, kurtosis, mad, max_range,
         asymmetry, max_height, min_height, peak_width,
         mean_width_all, num_peak, width_max, width_min, width_diff,
         width_mean, width_median, se]
    ), relative_percentile])

    return features


x = np.linspace(0, 10, 100)
yorg = np.sin(x)
y = yorg + np.random.randn(100)*0.5

features = generate_features(y, x, order=5)
```
Windows展開サービスでキャプチャーも自動化する

備忘録。
##環境
Windows server 2016にDHCP,DNS,Windows展開サービス（WDS）を起動させ、Windows10展開のためのマスター作成中。
SysprepをかけてシャットダウンしたマスターPCから、イメージをキャプチャーする。
##WDSでキャプチャー用ブートイメージを作成する
ブートイメージを登録したら、右クリック→キャプチャーイメージの作成
![スクリーンショット (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566744/4e3aad74-7ff9-5024-b9a5-040d7b937c5f.png)
適当に名前を付けて保存
![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566744/7b0bf5da-b5eb-414a-a916-b7cdf9bb6788.png)
このイメージから起動するとGUI操作でイメージをキャプチャーできる。

##wdscapture.inf
このイメージをエクスポートしてwimファイルとして保存し、Dismでマウントすると Windows\System32　配下にwdscapture.infという設定ファイルが保存されている。あとは設定項目を入力していけばいい。
![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566744/27285d53-df34-348b-77e9-ff37abfe269a.png)

[Capture]ではキャプチャーイメージの設定。Unattend=Yesにすると完全自動化されるが、入力漏れがあるとキャプチャーが進まないので全部入力する必要があるっぽい。
[WDS]ではサーバーにコピーを保存するときの設定。あらかじめユーザー名・パスワード等を入力しておけば、キャプチャー時にはすでにログオンされた状態になっている。

参考：[Automating the Image Capture Wizard](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771321(v=ws.10)?redirectedfrom=MSDN)
##注意点
・WDSではSysprepをかけた状態でないとキャプチャーできない。
・キャプチャーイメージは一旦マスターPCに保存されるので、あらかじめパーティションを切ってDドライブ等を用意しておきたい。Cドライブ下にも保存できるらしいが、精神衛生的に。
・PXE起動時にブートイメージを選択するが、選択ミスを防ぐためにキャプチャー時はセットアップ用のブートイメージを無効にしておきたい。
Rspecと Factoryの使い方

#Rspecとは？
**Rspec**とは自動テストをしてくれる言語。になります。
UIテストをいちいちせずとも、
「ページの遷移」、「モデルバリデーション」、「if分の条件分岐による処理の確認」...
などなど、人間がやるには面倒なことを自動でやってくれるのが**Rspec**になります！

#準備
今回は比較的簡単な、
「コントローラーによる画面遷移確認テスト」
のコードを書いていこうと思います

また、ログイン後の処理定義をするコードを書きますが、そのログイン処理を**Devise**を使ってやるものとします

##導入するGemインストール
今回使うのは**Rspec**と**Factory_bot**というGemを使います
内容については後ほど解説しますので、まずはインストールしましょう！！

```ruby:Gemfile
group :development, :test do
  gem "rspec-rails"
  gem "factory_bot_rails"
end
```

##rspecを設定・書くためのファイルを作成

```
$ bundle exec rails generate rspec:install
```

##deviceログインの簡略化
###controller_macros
spec/support/controller_macros.rbににログイン処理を簡略化させるためのコードを記載します
ファイルがない場合のファイルを作成してください

```ruby:spec/support/controller_macros.rb
module ControllerMacros
  def login_admin(admin)
    @request.env["devise.mapping"] = Devise.mappings[:admin]
    sign_in admin
  end

  def login_user(user)
    controller.stub(:authenticate_user!).and_return true
    @request.env["devise.mapping"] = Devise.mappings[:user]
    sign_in user
  end
end
```

###rails_helperで読み込み設定
先ほどのコードを読み込ませるために、spec/rails_helper.rbに以下文を追記します

```ruby:spec/rails_helper.rb
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
```

#実装
ここからファイルに必要なコード書いていきます

##テストするためのモデルを作成
**spec/fatories**このディレクトリに作成していモデルデータを記載していきます。
今回はユーザによる画面遷移テストを作りたいので、まずユーザーファイルを作成。

**spec/fatories/users.rb**

その後中身を書いていきます

```ruby:**spec/fatories/users.rb**
FactoryBot.define do
  factory :user do
    name { "test" }
    email { "user@email.com" }
    password { "password" }
    password_confirmation { "password" }
  end
end
```

今回はユーザー必要最低限な情報だけにしておきます
ここはかくじ必要なカラム等追加していただければと思います！

##テストコードの記載
ここから肝心なテスト内容を記載するところです

テストコードを書く場所は
**spec/controllers/users_controller_spec.rb**
ここになります！
コントローラー内での画面遷移テストしかできないので、他のモデルが絡むときは
随時それ対応するコントローラーでかきましょう！

```ruby:spec/cotrollers/users_controller_spec.rb
require 'rails_helper'

describe UsersController, type: :controller do
  before do
    @user = FactoryBot.create(:user)
  end
  context 'ログイン後' do
    before do 
      login(@user)
    end
    
    it 'トップ画面にいく' do 
      get :index
      expect(response).to have_http_status "200"
    end
  end
  
  context '未ログインの場合' do
    it 'トップに行くと302(エラー)が返される' do 
      get :index
      expect(response).to have_http_status "302"
    end
    it 'トップに行くとuserログインページにリダイレクトされる' do 
      get :index
      expect(response).to redirect_to new_user_session_path
    end
  end
end
```

・describe
　→コントローラーしていし、**type**でもコントローラーと指定する
　→モデルの場合typeはmodelになる

・before do
　→テスト実行前の準備する場所
　→今回で言うとここでユーザーの情報を作成して、@userに代入してuserのデータを扱えるようにしている

・contxt
　→実行する前提条件の定義を日本語わかりやすく、みやすくする
　→実行範囲内を定義する意味もある

・it
　→実際にテストする内容

・get: :index
　→ルーティングで定義てしてる**getメソッド**の**indexアクション**に遷移すると定義

・expect(response).to have_http_status "200"
　→要するに成功したら200って返ってくきてるよね？？という確認
　→ここがtrueかfalseかでテスト結果を判定している

##実行
```

$ rspec
```
以上で実行完了

#まとめ
以上でコントローラーテストの簡易的な説明になります
まずは簡単なところからはじめて徐々にできる範囲を伸ばしていきましょう！！
敵をロックオンする機能を実装する

![u3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368850/08bcda9e-fbbb-878e-7bf5-1a3479dda52f.png)

アクションゲームなどでよくある敵をロックオンするような機能を実装していきたいと思います。

# ロックオンする敵
まずどの敵をロックオンするかですが、
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368850/849e91df-d731-9097-1859-2db7bc97a105.png)

プレイヤーの正面ベクトルとプレイヤーからエネミーに伸びるベクトル間の角度θを求めて、
プレイヤーとエネミーの距離を掛けます。出た値が一番低い、すなわち距離が近くてプレイヤーの正面に居る敵をロックオンするようにします。
**a = (θの絶対値)×(プレイヤーとエネミーの距離)**
  **aの値が一番低い敵をロックオンする**

```C++:Player.cpp
	std::vector<Enemy*> m_enemyList;  //エネミーの配列
    Vector3 m_position   //プレイヤーの座標
    bool m_isRockOn = false;

	//プレイヤーの向いている角度を計算します
	float degreep = atan2f(forward.x,　forward.z);
	//計算して出た暫定的に一番小さい角度を記憶する変数です
	float degreemum= M_PI * 2;
    for(Enemy* enemy : m_enemyList)
    {
        Vector3 pos = m_position - enemy->GetPosition();
		//プレイヤーとエネミーの距離が一定外だったら下の処理をスキップします。
		if (pos.Length() >= 500)
	        continue;
		//プレイヤーとエネミーを結ぶベクトルを出します
		CVector3 pos2 = enemy->GetPosition() - m_position;
		//y座標、すなわち高さを0にします
		pos2.y = 0.0f;
		//ベクトルを正規化します
		pos2.Normalize();
		//プレイヤーとエネミーを結ぶベクトルの角度を計算します
		float degree = atan2f(pos2.x, pos2.z);
		//ここら辺のif文要らない可能性が微レ存、「プレイヤーの正面のベクトルの角度」と
		//「プレイヤーとエネミーを結ぶベクトルの角度」の差を計算します
		if (M_PI <= (degreep - degree)) {
			degree = degreep - degree - M_PI * 2;
		}
		else if (-M_PI >= (degreep - degree)) {
			degree = degreep - degree + M_PI * 2;
		}
		else {
			degree = degreep - degree;
		}
		//求めた角度にプレイヤーとエネミーの距離に応じて補正をかけます、距離が長いほど補正は大きいです(値が大きくなります)
		degree = degree + degree * (pos.Length() / 500) * 0.3f;
		//求めた値を比較していき、一番小さい値を決めていきます
		if (fabs(degreemum) >= fabs(degree)) {
			degreemum = degree;
 		}
    }
	//求めた一番小さい値が一定値より小さい場合、ターゲッティングをオンにします
	if (fabs(degreemum) <= M_PI / 3) {
		m_isRockOn = true;
	}
	//逆に一定値より大きい場合、ターゲッティングをオフにします
	else {
		m_isRockOn  = false;
	}
```

# カメラ
ロックオンした時のカメラの挙動ですが、カメラの注視点を敵の座標に、カメラ自体の座標はプレイヤーより敵から離れた座標に設定します。
![b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368850/03d612dc-4e60-182b-e82a-13da26c015d2.png)


```C++:Camera.cpp
    Vector3 m_position;   //カメラの座標
    Vector3 m_target;   //カメラの注視点
    Vector3 m_playerPosition;   //プレイヤーの座標
    Vector3 m_enemyPosition;   //ロックオンするエネミーの座標
 
    //注視点はエネミーの座標にします。
    m_target = m_enemyPosition;
    //エネミーからプレイヤーに伸びるベクトルを求めます。
    Vector3 pos = m_playerPosition - m_enemyPosition;
    //カメラの高さは一定にしたいので、y成分を0にします。
    pos.y = 0.0f;
    //ベクトルを正規化します。
    pos.Normalize();
    //スカラーを掛けます
    pos *= 50.0f;
    //カメラがどれだけプレイヤーの座標より高いかを設定します。
    pos.y = 50.0f;
    //プレイヤーの座標に求めたベクトルを足して、カメラの座標とします。
    m_position = m_playerPosition + pos;


```
ArrayListのnewとclear()では挙動が異なる

地味にハマってしまったので。

# はじめに
Javaでリストを扱う時、よくArrayListをnewして使うと思います。

```hoge.java
List<String> list = new ArrayList<>();
```

そのArrayListを使い回したいという時にGoogle先生に聞いてみると、

1. newする
2. ArrayList.clear()メソッドを使う

の2通りをオススメされると思います。そして、両者の違いについては特に触れられず、強いて言えば「実行速度が違うよ」と言っていくらかQiitaの記事がヒットすると思います。

しかし、実際のところは速度だけではなく、挙動にも異なる点があります。

# newとclear()の違い
1次元リストから要素を2つずつ取り出して2次元リストを作る場合を想定します。

以下にサンプルコードを示します。
まずはnewした場合からです。

```sample.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TestArraylist {
    public static void main(String args[]) {
        // 出力用の2次元リスト	
        List<ArrayList<String>> sampleLists = new ArrayList<>();
        // sampleListsに要素を追加するための一時的なリスト
        ArrayList<String> listA = new ArrayList<>();
        // 適当なサンプル
        List<String> listB = Arrays.asList("AA", "BB", "CC", "DD", "EE", "FF");

        // 要素数が2のリストを作ってsampleListsに追加する
        for (int i = 0; i < listB.size(); i++) {
            if (i % 2 == 0) {
                listA.add(listB.get(i));
                continue;
            }
            sampleLists.add(listA);
            listA.add(listB.get(i));
            // new前の確認
            System.out.println(sampleLists);

            // 一時的なリストをnewする
            listA = new ArrayList<>();
            // new後の確認
            System.out.println(sampleLists);
        }
    }
}
```
これを実行すると・・・

```
[[AA, BB]]
[[AA, BB]]
[[AA, BB], [CC, DD]]
[[AA, BB], [CC, DD]]
[[AA, BB], [CC, DD], [EE, FF]]
[[AA, BB], [CC, DD], [EE, FF]]
```
ちゃんと目的通りのリストが出来上がっていることがわかります。

一方、newの代わりにclearメソッドを使ったとします。上記サンプルの`listA = new ArrayList<>();`をclearメソッドを用いたコード`listA.clear();`に書き換えた時の出力は・・・

```
[[AA, BB]]
[[]]
[[CC, DD], [CC, DD]]
[[], []]
[[EE, FF], [EE, FF], [EE, FF]]
[[], [], []]
```
このように、**確かに追加したはずの要素がclearメソッドを呼び出すたびに要素0のリストとなってしまい、次にclearメソッドを呼び出すまで新たに追加した要素がすべてのリストに追加されてしまいます**。

# おわりに
ググってみると配列の要素を消すのはどちらを使ってもよいというページがたくさん出てくるので油断してしまいますが、実際は上記のような異なる挙動をしているので注意が必要です。
Pythonでsorted関数やgroupby関数へdefを渡すときの注意点？？

  Pythonを勉強しているのですが、ハマってしまって、1時間ぐらい立ち往生しました。
一応解決したのですが、どうしても腑に落ちなくて、もしこのメカニズムがわかる方がいらっしゃったらご教示いただけると嬉しいと思い、書きます。

以下は、選手名とブロックの組み合わせで、ロサンゼルスとニューヨークの選手を混ぜて、AブロックとBブロックにそれぞれ分けるプログラムです。

```ruby:groupLeague.py
import itertools
LA = [('Jake', 'B'), ('Elwood', 'A')]
NY = [('James', 'A'), ('Carry', 'B'), ('Steven', 'B')]
data = itertools.chain(LA, NY)

def getSortKey(item):
    return item[1]

grp = itertools.groupby(sorted(data, key=getSortKey(data), getSortKey(data))
```
しかし、これを実行すると、
TypeError: 'itertools.chain' object is not subscriptable
とエラーで弾かれてしまいます。

さっぱりわからず大ハマリしたんですが、別のサンプルプログラムを見て直した所、動作しました。
最後の行の、

```
grp = itertools.groupby(sorted(data, key=getSortKey(data)), getSortKey(data))
```

を、

```
grp = itertools.groupby(sorted(data, key=getSortKey), getSortKey)
```
と、getSortKeyの引数を除いたところ、正常に動作しました。

とりあえずプログラムは動いたんですが、このメカニズムがさっぱりわかりません。
groupbyの2つ目の引数「key部」としてkey値の他に「keyを取得できる関数」を指定できるというのはわかるのですが、関数を指定する場合、なぜ引数を書かなくて良い(というか引数を書いたらエラー)になるのでしょうか？？動作を確認する限りでは、第一引数の「iterable部」(sorted～)が自動的に引数として扱われていると思うのですが、ドキュメントにはそれらしい記述は何もありませんでした。

【参考】
[Pythonドキュメント itertools --- 効率的なループ実行のためのイテレータ生成関数](https://docs.python.org/ja/3/library/itertools.html#itertools.groupby)

sorted関数も同様です。key=getSortkeyの部分で、引数は自動的に第一引数のdataを取っているように見えるのですが、そのメカニズムがわかりません(ドキュメントにもやっぱり記載はありませんでした)。

【参考】
[Pythonドキュメント 組み込み関数 sorted ](https://docs.python.org/ja/3/library/functions.html#sorted)

これ、引数を取らないで良いのってどういうメカニズムなんでしょうか…？？
調べてみたけどどうしてもわかりませんでした。
多分初歩的な質問だと思うので大変恐縮ですが、ご存じの方はご教示いただけますと大変助かります。

この手のトリッキーな仕様って、どうやって対処したら良いんだろう…。
【C++Builder】FireDACでFDQueryを使用してSQL文を発行

C++BuilderのFireDACを使ったデータベースアクセスの方法について調べても、Delphiのサンプルコードばっかりでパラメタ設定の方法に苦労したので書いておく。

使用しているのはC++Builder10.2
MySQL 5.7.29

C++BuilderからMySQLを使用する設定方法は[こちら](https://qiita.com/taka_tofu/items/9d7e1dfec5bb45e9d7e2)

# 事前準備

1.TFDConnectionとTFDQuery、TDataSource、TDBGridを画面に貼る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/2c96c56d-509e-473c-67e3-8b525311758a.png)

2.TFDConnectionの設定
TFDConnectionのアイコンをダブルクリックし、接続エディタでデータベースの情報を設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/e7d2e87c-52f6-6e97-bfa3-6da577aaa42a.png)

3. TFDQueryのプロパティのConnectionに先ほど張り付けたFDConnectionが設定されていることを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/1b997c0e-4714-351e-a390-d35e3e57ce36.png)

4.TDBGridのDataSourceに先ほど張り付けたDataSourceを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/c3daa546-8cef-b329-a7fb-43b36bdd1d61.png)

5.DataSourceのDataSetに先ほど張り付けたFDQueryを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274481/2941fbd7-c863-56a5-4c3e-a78f2a3320b8.png)

## SQL文のパラメタ指定方法

例えば、ボタンを押すとテキストエディタに入力した文字列をデータベースから取得したい場合は以下のようにする。

```
FDQuery1->SQL->Text = "select * from test where name = :name";
FDQuery1->ParamByName("name")->Value= Edit1->Text;
FDQuery1->Active=true;
```

数値を指定するときも同じ

```
FDQuery1->SQL->Text = "select * from test where id = :id";
FDQuery1->ParamByName("id")->Value= Edit1->Text.ToInt();
```

別の指定方法もある

```
FDQuery1->SQL->Text = "select * from test where id = :id";
FDQuery1->Params->ParamValues["id"]=Edit1->Text.ToInt();
```

パラメタが日付の場合はこんな感じ

```
TDateTime today=Now();
TDateTime befor1year=today-TDateTime(1,0,0);
FDQuery1->SQL->Text = "select * from test where registdate between :from and:to";
FDQuery1->Params->ParamValues["from"]=befor1year.FormatString("yyyy-mm-dd");
FDQuery1->Params->ParamValues["to"]=today.FormatString("yyyy-mm-dd");
```

以上

参考ページ
 [コマンドの実行FireDAC](http://docwiki.embarcadero.com/RADStudio/Rio/ja/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E5%AE%9F%E8%A1%8C%EF%BC%88FireDAC%EF%BC%89#TFDConnection_.E3.81.AE.E4.BD.BF.E7.94.A8)
Vue.js のディレクティブの記述を膨らませないために

# 概要
本記事では、Vue.jsのディレクティブって便利だけどなんかかさばって可読性が・・という方に
改善する方法を**v-bind**を例にして紹介していきます。

## 元のコード
aタグに対して2つのv-bindが設定されています。
2つくらいなら・・と思うかもしれませんがこれが膨張していくと恐ろしいことになります。

```html:index.html
<div id="app">
  <a :href="url" :id="number">リンク</a>
</div>
```

```js:index.js
new Vue({
  el: '#app',
  data: {
    url: 'https://sample.com',
    number: 23
  }
})
```

## 改善
ひとつのオブジェクトにまとめることができます。
画面上の表示はなにも変わりません。

```html:index.html
<div id="app">
  <a v-bind="{href: url, id: number}">リンク</a>
</div>
```

```js:index.js
new Vue({
  el: '#app',
  data: {
    url: 'https://sample.com',
    number: 23,
  }
})
```

## さらに改善
dataの中にオブジェクトとして持たせておいて、html上では**bindObject**とバインドさせているだけになりました。こちらも画面上の表示はなにも変わりません。
こちらの方がhtmlに記載する量が少ないのでVue.jsを書く上での理想の形です。そして管理もしやすくなりますね。

```html:index.html
<div id="app">
  <a v-bind="bindObject">リンク</a>
</div>
```

```js:index.js
new Vue({
  el: '#app',
  data: {
    bindObject: {
      url: 'https://sample.com',
      number: 23,
    }
  }
})
```

## 最後に
可読性を下げず、チームでも個人でも管理しやすい形でコーディングできるように自分ももっと気をつけていこうと思います。
riot.js webpack でHellow World

## 背景

仕事で簡単なLP構築をする機会があった。
暫くフロンエンドを触っていなかったので勉強も兼ねて前々から気になっていた[riot](https://riot.js.org/ja/)を動かしてみる。

## 作業ログ

まずはプロジェクトフォルダ以下にpackage.jsonの作成

```
$ npm init
```
webpack関連パッケージ インストール
※webpackはJSファイルをまとめる高機能なモジュールバンドラーの1つ

```
$ npm i webpack webpack-cli webpack-dev-server
```

riot関連パッケージ インストール

```
$ npm i riot @riotjs/hot-reload　@riotjs/webpack-loader @riotjs/compiler
```

[クイックスタート](https://riot.js.org/ja/documentation/)を参考にファイルの準備

index.html

```
<html>
<head>
    <meta charset="UTF-8">
    <title>Riot app</title>
</head>
<body>

<div id="app"></div>

<script src="public/bundle.js" charset="utf-8"></script>
</body>
</html>
```

app.riot

```
<app>
    <p>{ props.message }</p>
</app>
```

main.js

```
import * as riot from 'riot'
import App from './app.riot'

const mountApp = riot.component(App)

const app = mountApp(
  document.getElementById('root'),
  { message: 'Hello World' }
)
```

webpackの設定ファイルの用意webpack.config.js

```
const path = require('path')
const webpack = require('webpack')

module.exports = {
    entry: './main.js',
    output: {
        path: path.resolve(__dirname, 'public'),
        publicPath: '/public/',
        filename: 'bundle.js'
    },
    devtool: 'inline',
    module: {
        rules: [
            {
                test: /\.riot$/,
                exclude: /node_modules/,
                use: [{
                    loader: '@riotjs/webpack-loader',
                    options: {
                        hot: true
                    }
                }]
            }
        ]
    }
}
```
ここまでのファイル構成はこんな感じ

<img width="336" alt="スクリーンショット 2020-01-23 19.05.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172074/a369fe8b-8f20-1bf3-c647-9c04d5fbacd1.png">

webpack-dev-serverで動作確認

```
./node_modules/.bin/webpack-dev-server --port 8080
```
http://localhost:8080/ にアクセス
<img width="273" alt="スクリーンショット 2020-01-23 18.58.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172074/e6614c1f-9c4b-2ae6-5f1f-abae74e334c0.png">

デプロイ用にbundle.jsの作成

```
$ ./node_modules/.bin/webpack
```
出力したbundle.jsとindex.htmlをサーバにアップすればサーバでも動くはず。

## 所感

ネットに情報があまり転がっていない印象。
また、v3からv4で大幅な変更があったようで数少ないネット記事を頼りに Hellow World を表示するのにも想像以上に時間をかけてしまった(笑)

このままriot.jsでサイト構築するかは要検討。