OmniAICreator/Qiita-1.07M huggingface dataset:
LINE BOT（雑談）を作る

#A3RTを使って雑談LINEBOTを作る

前回作成した[LINE BOT（オウム返し）を作る](https://qiita.com/nooonchi/items/8004dfc9deea6c25754b)を改良して、リクルートが提供しているA3RTのTalk APIを使って雑談するBOTを作った。


#（１）A3RTからAPIKEYを取得する
[A3RTのサイト](https://a3rt.recruit-tech.co.jp/product/talkAPI/)で、APIKEYを発行する。

#（２）A3RTの構造を確認する
前回作成したmain.pyを修正する前にA３RTの構造を確認する。
A3RTの構造を確認するために以下のコードを実行して、"おはよう"に対する回答をAIがちゃんと返してくれるか確認する。
まず、仮想環境でpya3rtをインストールして、

```
pip install pya3rt
```

以下をターミナルのpythonモードで実行してみる。

```
import pya3rt

apikey = "*******************************"
client = pya3rt.TalkClient(apikey)
reply_message = client.talk("おはよう")

print(reply_message)
```

```
{'status': 0,'message': 'ok','results': [{'perplexity': 0.07743213382788067, 'reply': 'おはようございます'}]}
```

となる。
replyの"おはようございます"を取得したいので、以下のように修正

```
import pya3rt

apikey = "****************************"
client = pya3rt.TalkClient(apikey)
reply_message = client.talk("おはよう")

print(reply_message['results'][0]['reply'])
```

すると、

```
おはようございます
```

となり、ちゃんと"おはよう"→"おはようございます"と返してくれた。
これを前回作成したmain.pyに組み込む。

#（３）前回作成したmain.pyを修正
まず、上記のpya3rtの記述を以下のように関数化する。

```
def talk_ai(word):
    apikey = "****************************"
    client = pya3rt.TalkClient(apikey)
    reply_message = client.talk(word)
    return reply_message['results'][0]['reply']
```

[前回](https://qiita.com/nooonchi/items/8004dfc9deea6c25754b)作成したmain.pyを修正する。

```.py:main.py
from flask import Flask, request, abort
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)
import os
#追加
import pya3rt

app = Flask(__name__)

YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]

line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)

@app.route("/")
def hello_world():
    return "hello world!"


@app.route("/callback", methods=['POST'])
def callback():
    signature = request.headers['X-Line-Signature']
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        print("Invalid signature. Please check your channel access token/channel secret.")
        abort(400)
    return 'OK'



@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    #（追加）talk_aiメソッドに引数を渡して返り値をai_messageに代入
    ai_message = talk_ai(event.message.text)
    line_bot_api.reply_message(
        event.reply_token,
        #TextSendMessage(text=event.message.txt))
        #（修正）ai_messageを返すようにする
        TextSendMessage(text=ai_message))

#（追加）pya3rtでai会話を返信
def talk_ai(word):
    apikey = "****************************"
    client = pya3rt.TalkClient(apikey)
    reply_message = client.talk(word)
    return reply_message['results'][0]['reply']

if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)
```

修正できたらrequirements.txtを更新して、

```
pip freeze > requirements.txt
```

あとは、Herokuにデプロイすれば完成。
レスポンシブにしたのに、なぜかなっていない。そんな時の確認。

せっかくレスポンシブに対応しているようにコードを書いたのに、サーバーにあげるとレスポンシブになっていない。

#結論　head要素を見ましょう

ヘッド要素の中（railsならapplication.html）の中身に


```
<meta name="viewport" content="width=device-width, initial-scale=1.0">
```

hamlなら

```
%meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}/
```

こちらを記入しましょう。
gatsbyでポートフォリオ作ろうとしたらコマンドが使えなかった話

##gatsbyでポートフォリオサイト作ろうとしたら・・・
何をしても`zsh: command not found: gatsby`が表示される
何度もこの表示を見て泣きそうになりました。

**Success!**
とか
**Welcome to the Gatsby CLI! Please visit https://www.gatsbyjs.org/docs/gatsby-cli/ for more information.**
とか出るくせに`gatsby -h`を入力すると
`zsh: command not found: gatsby
`
もうまじで**「f○○k ○○u**」と心の中で叫んでましたね。
失礼しました。
では次は試したことを
##試した事
- npmのバージョンアップ
- npmのアンインストール/再インストール
- nodeのアンインストール/再インストール

これらをやったのちに`npm i -g gatsby-cli`を打ってもう一度`gatsby -h!!!`

`zsh: command not found: gatsby`

・・・・・・・・・・・
もう諦めようかと思いましたよ。

いちよう解決したので次に解決方
##やっと解決

ググりまくってやっと解決出来た方法がこちら
```npm config delete prefix
npm config set prefix /usr/local```
簡単に言うと最新のmacOSではnpm configを更新する必要する必要があるらしく、このコマンドで更新が出来るみたいです。
この後に`npm i -g gatsby-cli`を打って`gatsby -h`をやったらしっかりhelpが出てきてくれました。
やっとgatsbyでポートフォリオサイトが作れます。
npmとかnodeとかyarnとかの知識がまだまだなのでもっと理解をしないとダメだなと思った今日この頃でした。
##最後に
見てくれた方ありがとうございます。
まだ学習を始めて半年の初心者ですが誰かの役に立てればと思います。
RPi2シリアルコンソールコンフィグ

# memo
デフォルトでは以下
Speed (baud rate): 115200
Bits: 8
Parity: None
Stop Bits: 1
Flow Control: None

screenはシリアルコンソール接続できて便利(tmuxも可能か？(

/dev/ttyUSB0
だとすると、
$ screen /dev/ttyUSB0 115200,cs8,-ixon,-ixoff,-istrip
 

# cuコマンドでpi側から応答がない場合
接続コマンド

```
cu -l /dev/ttyUSB0 -s 115200
Connected.

```

接続は上記で正常にできている。`Connected.`と表示されるから。
アクセス元マシンからの入力が正常かどうかを確認するため、エコーバックを有効にしてみる。

```
cu -l /dev/ttyUSB0 -s 115200 -h
Connected.
(ローカルでタイプ->)hogehoge
```

エコーバックは来るので、接続元からの入力は行えている。
別のプロセスから、`/dev/ttyUSB0`の設定を行うと、pi側に正常に文字を入力できる。

```
$ stty -F /dev/ttyS0 -crtscts
```

後で読む
https://access.redhat.com/solutions/209663
Elastic Beanstalkの.ebextensionsでApacheのDocument Rootを変更する方法

Elastic BeanstalkでEC2を立ち上げる際、ApacheのDocument Rootは

```httpd.conf

      DocumentRoot "/var/www/html/"

```
となっています。
これを変更しようとしたのですが、ちょっとトリッキーなことをしたので、残しておきます。

## 環境
64bit Amazon Linux/2.9.3
Apache/2.4.41

## やり方
.ebextensionsのフォルダ内に以下のファイルを入れます。

```apache.config
files:
  /etc/httpd/conf/myhttpd.conf:
    content: |
      ##以下にDocment Rootを変更したconfファイルの内容を記載する
      ##例えば↓↓
      DocumentRoot "/var/www/html/public"

      #### End of AWS Settings ####
container_commands:
  00-rm-httpd-conf:
    command: "sudo rm /etc/httpd/conf/httpd.conf"
  01-cp-conf-file:
    command: "sudo cp /etc/httpd/conf/myhttpd.conf /etc/httpd/conf/httpd.conf"
  02-httpd-restart:
    command: "sudo httpd -k restart"

```
このファイルでは
①Document Rootを変更した設定ファイル`myhttpd.conf`をEC2に置く
②元々の設定ファイル`httpd.conf`でApacheを立ち上げた後、`httpd.conf`を削除する
③`myhttpd.conf`を`httpd.conf`に置き換える
④Apacheを再起動する
という手順を踏んでいます。

## この手順を踏んでいる理由
元々は最初のApacheの立ち上げの前から`httpd.conf`を上書きしようとしたのですが、そうするとなぜかDocument Rootがデフォルトに書き換わってしまいました。
なので、ちょっとトリッキーな手順を踏みました。
[実践編]Pukiwikiのエンコードされた添付ファイルの名前をデコードする方法2

## はじめに
[前回の記事](https://qiita.com/a27yb/items/03966d05caefd6e97ade)では、ファイル名をデコードする方法を紹介しました。
今回の記事では、添付ファイルのデコードから新しいファイルの生成まで行っています。

## ディレクトリ構造
/home/$user/eucjpDecoder

eucjpDecoder内に**downloaded**と**attach**ディレクトリを作成し、**downloaded**ディレクトリ内にPukiwikiの添付ファイルが保存されている**attach**ディレクトリを挿入します。
こちらの環境では、Zipファイルの展開先を**downloaded**ディレクトリに指定しました。


##コード

``` python3

import os
import shutil

import pdb
pdb.set_trace()

fileList = os.listdir(path="./downloaded/attach")

for i in range(len(fileList)):
    print(fileList[i],i)

    # 拡張子が付いているファイルは除外---
    if "." in fileList[i]:
        continue
    # ---
    
    elif "_" in fileList[i]:
        fileName = fileList[i].split("_") # ファイル名を_で分割

        # 分割したファイル名を変数に代入---
        bytePageName =  bytes.fromhex(fileName[0]).decode("euc_jp", errors="backslashreplace") # Pukiwikiでのページ名
        byteFileName = bytes.fromhex(fileName[1]).decode("euc_jp", errors="backslashreplace") # Pukiwikiでのファイル名
        # ---

        # ファイルのパス---
        newFilePath = os.getcwd() + "/attach/" + bytePageName.replace("/","_")+"--"+byteFileName.replace("/","_") # 新しく生成するファイルの絶対パス
        downloadedFilePath = os.getcwd( ) + "/downloaded/attach/" + str(fileList[i]) # 16進数表記になっているファイルの絶対パス
        # ---

        # 新しく生成するファイルを指定したパス内に生成する---
        if os.path.isfile(newFilePath)==False:
            open(newFilePath, mode="w") # 空ファイル生成
        # ---

        shutil.copyfile(downloadedFilePath, newFilePath) # 16進数表記になっているファイルの中身を新しく生成したファイルにコピー
```

## 注意事項
デコードに失敗してしまうファイルがほんの少しですが存在しました。
デバッガを起動しながら、何番目のファイルでデコードに失敗したのかを把握しておきましょう。
デコードに失敗したファイルは手動でデコードさせます。

## さいごに
Pukiwikiの添付ファイルを短時間で大量に手元に戻しておきたい、というニーズが世界で何件あるのか...
もしそのようなニーズがあるのであれば、参考にしてみてほしいです。
Swift における、Object、Methodを連結、作成する方法、AVPlayer で、外部URLのファイルを再生する方法。

#ViewController.swift における、言わば、script における functionの連結。
import UIKit
import Avfoundation
class ViewController: UIViewController
のあと、Button Action の中や、
override func viewDidLoad(){
} 内に置いて。
![スクリーンショット 2020-03-20 21.47.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606144/8d6bc28f-0be5-943f-0037-239fbc116dec.png)
から、
![スクリーンショット 2020-03-20 21.49.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606144/1a4a4915-38b3-85a3-d0e4-a907a209e906.png)
に、self.~の形で発進し、func ~(){} で受け取る
また、題材の
![スクリーンショット 2020-03-20 21.53.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606144/078b8f06-1ddc-e351-ffae-7453395994ff.png)
の形で、いずれのカッコの中にもおかず、class ViewControler : UIController の直下にセットしデクレアしておく。
二種類のNSArrayは、viewDidLoad(){} 内に置いて、item = ["url","url2","url3"]
songName = ["title1","title2","title3"]
として置き、counter = 0などとし、item[counter]、songName[counter]で取り出す。
NestJSをAWS Lambdaで動かすためのライブラリ「serverless-lambda-nestjs」を作った

NestJS的にもAWS Lambda with API Gateway的にもアンチパターンな香りがしますが、欲しいものは欲しいので作りました。

https://www.npmjs.com/package/serverless-lambda-nestjs

## なんで作った？

- 手慣れたAWS Lambda & Amazon API GatewayでAPI作りたい
- NestJSにはチャレンジしたかった
- 「無理ってなったらFargate / ECSあたりのコンテナへそのままいけばいいや」という軽い気持ち

## インストール方法

npmで入れちゃいましょう。

```
npm i -S serverless-lambda-nestjs
```

## 使い方

NestJSのアプリをラップする形で使います。

### Before

大体の記事で紹介されている、Lambdaで動かすための書き方がこんな感じ。

```typescript

import { APIGatewayProxyHandler } from 'aws-lambda';
import { NestFactory } from '@nestjs/core';
import { Server } from 'http';
import { ExpressAdapter } from '@nestjs/platform-express';
import * as serverless from 'aws-serverless-express';
import * as express from 'express';
import { AppModule } from './app.module';

let cachedServer: Server;

const bootstrapServer = async (): Promise<Server> => {
  const expressApp = express();
  const adapter = new ExpressAdapter(expressApp);
  const app = await NestFactory.create(AppModule, adapter);
  app.enableCors();
  app.init();
  return serverless.createServer(expressApp);
};

export const handler: APIGatewayProxyHandler = async (event, context) => {
  if (!cachedServer) {
    cachedServer = await bootstrapServer();
  }
  const result = await serverless.proxy(cachedServer, event, context, 'PROMISE')
    .promise;
  return result;
};

```

### After

毎回書くことになる長いコードを全部ラップしました。

```typescript

import { APIGatewayProxyHandler } from 'aws-lambda';
import { ServerlessNestjsApplicationFactory } from 'serverless-lambda-nestjs';
import { ValidationPipe, INestApplication } from '@nestjs/common';
import { AppModule } from './app.module';

export const handler: APIGatewayProxyHandler = async (event, context) => {
  const app = new ServerlessNestjsApplicationFactory<AppModule>(
    AppModule
  );
  const result = await app.run(event, context);
  return result;
};

```

### INestApplicationのオプション諸々

`ServerlessNestjsApplicationFactory`の第二引数でオプションが渡せます。


```typescript
  const app = new ServerlessNestjsApplicationFactory<AppModule>(
    AppModule,
    { cors: true }
  );
```


`ServerlessNestjsApplicationFactory`の第三引数がコールバックになってるので、そこでいじれます。

```typescript
  const app = new ServerlessNestjsApplicationFactory<AppModule>(
    AppModule,
    {
      cors: true
    },
    (nestApp) => {
      nestApp.useGlobalPipes(
        new ValidationPipe({
          transform: true,
        }),
      );
      nestApp.useGlobalFilters(new HttpErrorFilter());
      return nestApp
    },
  );
```

## 最後に

「Fargateとかぶん回した方がコスパもいいし便利だよね」ということが言えるようになりたいなという気持ちだけはあります。
Bootstrapのtooltipをfont-awesomeのアイコンに使いたい

# tooltip実装前の元のコード

```slim:application.html.slim
span.ul.navbar-text = link_to new_task_path, class: 'text-reset'
  = content_tag(:i, "", class: "far fa-file fa-lg")
```

font-awesomeのアイコンをクリックすると新規作成画面に移動する。が、何の説明もなしじゃこのアイコンが何を意味するか分からないのでBootstrapによるtooltip実装を試みた。

[ツールチップ～Bootstrap4移行ガイド](https://cccabinet.jpn.org/bootstrap4/components/tooltips)

>`<p><a href="#" data-toggle="tooltip" title="これがツールチップです">リンク</a>の上にカーソルを合わせるかタッチして下さい。</p>`

## 試行錯誤

data-toggleとtitleを設定すればいいだけかと思いまず書いたコード

```slim:application.html.slim
span.ul.navbar-text = link_to new_task_path, class: 'text-reset'
  = content_tag(:i, "", class: "far fa-file fa-lg", data-toggle="tooltip", title="新規作成")
```

結果はエラー。原因はaを作るlink_toではなくiを作ってるcontent_tagの中に書いたからだと思う。

```slim:application.html.slim
span.ul.navbar-text = link_to new_task_path, class: 'text-reset', data-toggle="tooltip", title="新規作成"
  = content_tag(:i, "", class: "far fa-file fa-lg")
```

これでいけるかと思いきやこっちもダメ。

## 解決法

[HTML5 - Rails，link_toメソッドの｜teratail](https://teratail.com/questions/124849)
上の記事を見ると、`data-toggle`をシングルクォーテーションで囲っている。

最終的なコード

```slim:application.html.slim
span.ul.navbar-text = link_to new_task_path, class: 'text-reset', 'data-toggle': "tooltip", 'title': "新規作成"
  = content_tag(:i, "", class: "far fa-file fa-lg")
```

<img width="185" alt="スクリーンショット 2020-03-20 21.50.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451253/470cac60-0210-8866-ba9a-03388f1666fa.png">

無事、アイコンが何を意味するのかをtooltipによって説明出来ました。
【UE4】スプラインで飛来して目的地に着陸する／第13回UE4ぷちコン進捗 - 2020/03/20

[1]:http://historia.co.jp/ue4petitcon13
[2]:http://hooktail.sub.jp/mechanics/resistdown/
[3]:https://docs.unrealengine.com/en-US/BlueprintAPI/Spline/GetLocationatDistanceAlongSpline/index.html


[株式会社ヒストリアさん主催の第13回UE4ぷちコン][1]の作業進捗。

前回に引き続き、敵となるドラゴンを作っている。
今日は空から飛んできて、目的地に着地するような挙動を作成した。

![20200320_1929.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/eb4e32f2-3e9b-e97c-896a-093b43dc5416.gif)

- 影がよぎってから画面に登場
- 画面奥で旋回してから、着地。

…という演出込みでやりたかった。
残念ながら、飛行パスは固定(スプライン)。毎回同じ挙動をする。
せいぜい、左右反転を作った程度。

例によって、本プロジェクトを汚さないように、実験用の新しいプロジェクトで試している。

# スプライン＋物理？

最初はスプラインを参照しながら、物理で飛ぶような動きを作ってみた。
（スプライン上を一定速度で動く点を、物理で追いかけるような挙動）
だが、パラメータによっては追い越してしまったり、旋回しきれなくなってしまったりで、難航。
うまくいかないまま１日使った時点で捨てることにした。

で、今回のやり方は：

- 空気抵抗付きの加速度運動するスカラ値を作成。
    - 空気抵抗があると、際限なく加速し続けず、最終的に一定の速度に落ち着くので。
    - 参考リンク：[抵抗力のある落下運動 - 物理のかぎしっぽ][2]
- このスカラ値をスプラインの始点からの距離として、スプライン上の点を求める。
    - Spline Component の [Get Location at Distance Along Spline][3] を使用(Blueprint)

…という方法で、速度感だけが物理に沿う動きを作った。だが、スプラインに沿って動く都合上、移動パスは全然物理っぽくない。これが顕著なのは、旋回時だった。なんというか、カクンと曲がるというか、プログラムっぽいというか。
で、誤魔化しとして、スプラインの曲がり具合に応じてロールするようにしてみたのだが、急に予定外にええ感じになってしまった。これで良しとする。

# 着地は物理

ドラゴンが着地体制に入るアニメーションに切り替わったときから、スプラインから切り離して、ぽいっと放り投げている。まっすぐ着地点に向かう向きに放り投げているので、それまでのスプラインの向きとの差異で、少々カクついているが、今回はこれで良しとする。

どうやって狙った位置に落としているか　…は、もうただ単純にパラメータ調整。種も仕掛けもなく、ちょうどいい位置に落ちる放り投げ速度とか、空気抵抗とか、そういうのを試行錯誤で見つけただけ。

とはいえ、地形などでズレは生じるだろうから、目的地から半径 5m 程度内に入れば、そこにこっそり吸い寄せるようなズルはやっている。

# ピンチ!?

後は、逃げ回る地竜(=２足歩行の恐竜)をええ感じにホーミングして食べなきゃいけないんだが、どう考えても難易度が高い。どうしよう…
ていうか、もう残り１週間＋αしかない。ドラゴン作っている場合なのだろうか。
ここまで作ってなんだが、最悪ドラゴンは無しになるかもしれない…


ともかく頑張る。でも、今日はもう寝る。
すごいHaskellたのしく学ぼう! を学びなおしてみる(第1章)[with Elixir]

# はじめに
- [Elixir](https://elixir-lang.org/)を使いはじめてだいたい1年くらいがたちました
- [すごいHaskellたのしく学ぼう!](https://www.amazon.co.jp/dp/4274068854/)という本を2015年に買って、一通り読んだあとずっと本棚にしまわれていたままでした
- 久しぶりに引っ張り出して読んでみると、こんなに愉快な内容だったけ！？　という感想を持ちました
- [Elixir](https://elixir-lang.org/)で関数プログラミングにだいぶ慣れたので、ユーモアの部分を楽しむ余裕ができたのだとおもいます
- 少しずつ読み進めながら、興味が向いたところだけ[Elixir](https://elixir-lang.org/)で書き換えてみたりして理解を深めていきたいとおもいます

# init関数

```Haskell
ghci> init [5,4,3,2,1]  
[5,4,3,2]  
```

### [すごいHaskellたのしく学ぼう!](https://www.amazon.co.jp/dp/4274068854/)から引用
> init関数はリストを受け取り、最後の要素を除いた残りのリストを返します

- [Starting Out](http://learnyouahaskell.com/starting-out)
    - [原文サイト](http://learnyouahaskell.com/chapters)内の上記ページの中央ほどにある可愛らしい絵をみるとイメージしやすいです

## [Elixir](https://elixir-lang.org/)で書いてみます

```Elixir
defmodule LearnYouAHaskellForGreatGood do
  def init([_ | []]) do
    []
  end

  def init([head | tail]) do
    [head] ++ init(tail)
  end
end
```

```Elixir
iex> LearnYouAHaskellForGreatGood.init([5,4,3,2,1]) 
[5, 4, 3, 2]
```
- 本当にこれ自分で書かないと無いのだろうか？　とおもって[List](https://hexdocs.pm/elixir/List.html#content)を眺めてみました
- **ありました！**

```Elixir
iex> [5, 4, 3, 2, 1] |> List.delete_at(-1)
[5, 4, 3, 2]
```

**こんな感じで、少しずつ [すごいHaskellたのしく学ぼう!](https://www.amazon.co.jp/dp/4274068854/) を学びなおしてみようとおもいます :rocket::rocket::rocket:**
【忘備録】Ruby on rails : パスワード登録

## 前提
今回はユーザーの新規登録する場面を想定しています。
以下がユーザーを登録する為のusersテーブルです。
password_digest カラムが新規登録する際に設定するパスワードを格納しています。

```
+-----------------+--------------+------+-----+---------+----------------+
| Field           | Type         | Null | Key | Default | Extra          |
+-----------------+--------------+------+-----+---------+----------------+
| id              | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name            | varchar(255) | YES  |     | NULL    |                |
| email           | varchar(255) | YES  |     | NULL    |                |
| created_at      | datetime     | NO   |     | NULL    |                |
| updated_at      | datetime     | NO   |     | NULL    |                |
| password_digest | varchar(255) | YES  |     | NULL    |                |
+-----------------+--------------+------+-----+---------+----------------+
```
## 本題
railsではパスワードを設定する際に便利な機能が既に用意されています。
以下はusersテーブルを操作する為のモデルクラスです。
validates 群の下に has_secure_password とありますがこれはrailsに備わっている
メソッドです。
このメソッドをモデルクラスに追加することで今回の場合、usersテーブルのpassword_digest カラムに
暗号化されたパスワードを保存することが可能になります。(password_digest カラムは自分で作る必要があります。)厳密にはこの他にbcryptというgemが必要になるのでインストールしましょう。
インストールが済んだら正式に完了です。

```
class User < ApplicationRecord
  validates :name, presence: true, length: { maximum: 50 }
  validates :email, presence: true, format: { with: /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i }
  validates :password, presence: true, length: { minimum: 6, maximum: 25 }, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8,}+\z/i }

  has_secure_password
end
```

あとはこのメソッドを使用すると自動的に通常のパスワードと確認用のパスワードが一致しているかの確認を行ってくれます。フロント側に普通のパスワード用のフォームと確認用パスワード用のフォームを用意してsubmitすれば自動的に確認してくれます。

一応下記がそのフォームです。

```
        <%= form_for @user do |f| %>
          <div>
            <%= f.label :name %>
            <%= f.text_field :name %>
          </div>
          <div>
            <%= f.label :email %>
            <%= f.text_field :email %>
          </div>
          <div>
            <%= f.label :password %>
            <%= f.password_field :password %>
          </div>
          <div>
            <%= f.label :password_confirmation %>
            <%= f.password_field :password_confirmation%>
          </div>

        <%= f.submit "登録", class: "btn-block btn-white" %>
        <% end %>
        <%= link_to "ログイン", "#", class: "text-white" %>
      </div>
    </div>
  </div>
</div>

```

これがパスワードフォームで
`<%= f.password_field :password %>`

これがパスワード確認用のフォームです。
`<%= f.password_field :password_confirmation%>`

`:password`と`password_confirmation`がparamsのハッシュのkeyとなって送信され、
keyのvalueが一致しているかモデルクラスで確認されますので名前は変えない方がいいと思います。
IBM Cloud Object Storage(ICOS)に付属しているAsperaにSDK(Python版)を用いてファイルアップロードする

IBM Cloud Object Storage(ICOS)にファイルをアップロードする方法です。
今回はICOSに付属しているAsperaに対して、Python版のSDKを用いて操作を行います。

# 使用した環境
* macOS Mojave 10.14.6、Python2.7.10
* Windows7 Ultimate、Python2.7.16

3系でも良いのですが、現状SDKが3.6までしかサポートしていないので2系でチェックしました。

# Python版SDKのセットアップ
こちらを参考にセットアップ下さい。
[GitHub：IBM-Cloud/data-lake/upload/cos-upload](https://github.com/IBM-Cloud/data-lake/tree/master/upload/cos-upload)

pipのセットアップの後に、install.shを実行しますが、
Windows版については、私はファイルの中身を直接コピーして、コマンドを実行しました。

```sh:install.sh
pip install --upgrade pip
pip install --upgrade setuptools
pip install "requests>=2.22.0,<2.23.0" "ibm-cos-sdk>=2.5.4" "cos-aspera>=0.1.163682"
```

# ICOSの情報確認
IBM Cloud コンソール（Web）にログインしてICOSのサービス資格情報を確認します。
サービス資格情報はICOSに作成したバケットの資格情報の中にあります。
![service_info.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187099/e851c63d-46c2-e70c-1e11-cbddda4a7f13.png)

# 実行
コマンド例は以下の通りです。

```
cos-upload.py <endpoint> <apikey> <bucket_name> <prefix> <file>
```

## Macでの実行

```
$ python cos-upload.py s3.jp-tok.cloud-object-storage.appdomain.cloud "api-key" test-bucket "" test-upload-python-mac.txt

Initialize COS and Aspera Transfer Manager using endpoint: https://s3.jp-tok.cloud-object-storage.appdomain.cloud

Upload file to COS: /tmp/test-upload-python-mac.txt => test-upload-python-mac.txt
Upload file to COS completed.
```

## Windowsでの実行

```
C:\tmp>py -2 D:\Workspace\cos-upload.py s3.jp-tok.cloud-object-storage.appdomain.cloud "api-key" test-bucket "" test-upload-python-win.txt

Initialize COS and Aspera Transfer Manager using endpoint: https://s3.jp-tok.cloud-object-storage.appdomain.cloud

Upload file to COS: C:\tmp\test-upload-python-win.txt => test-upload-python-win.txt
Upload file to COS completed.
```

## 到着確認
正常にアップロードされたことを[ibmcloudコマンド]()にて確認します。

```
// 正常にアップロードされたことを確認
$ ibmcloud cos list-objects --bucket test-bucket
OK
見つかりました 3 バケットにオブジェクトがあります 'test-bucket':

名前        最終変更日時               オブジェクト・サイズ
test.txt    Feb 28, 2020 at 02:27:12   14 B
test-upload-python-mac.txt   Mar 05, 2020 at 20:05:11   20 B
test-upload-python-win.txt   Mar 05, 2020 at 21:21:50   20 B
```

# あとがき
Python版のポイントは"実行環境の構築"と"実行時のパラメータ指定の概念理解"かと思います。

私はしばらくRequireに気が付かずに3.7系で実行していましたので、なかなかinstall.shがうまくいかずに困っていましたが、2.7系で実施したらものの見事に解決したので、時間をロスした！と感じました。
また、PythonをWindowsで動かすこともあまり無いかと思いますが、せっかくなのでチャレンジしてみたところ、うまくいったのでついでに載せた次第です。

実行時のパラメータの `<prefix>` と `<file>` は曲者で、やってみると分かるのですが、当初は意図した通りにファイルがアップロードされず、少々理解に苦しみました。
例えば `<file>` にフルパスを指定すると、

```
/tmp/upload/test.txt   Mar 03, 2020 at 21:21:50   20 B
```

みたいにパス名も付いたファイルがアップロードされます。
ですので、送りたいファイルのディレクトリまで移動し、そこから `cos-upload.py` をCallする形でやるのが小細工しなくて良いので、やり易いのではないかな？と思います。

# 参考リンク
- [curlコマンドでIBM Cloud Object Storage(ICOS)にファイルをアップロードして公開する](https://qiita.com/y_tama/items/6e31922eb9504502d568)
- [IBM Cloud Object Storage(ICOS)にCLI(ibmcloudコマンド)を用いてファイルアップロードする](https://qiita.com/takanobu_kawaguchi/items/90ed22c5a2852fb3b9d5)
- [IBM Cloud Object Storage(ICOS)に付属しているAsperaにSDK(Java版)を用いてファイルアップロードする](https://qiita.com/takanobu_kawaguchi/items/d95d9ca0fd1ab654ac00)
知っておきたいキー操作

##Ctrl + A
行頭へカーソル移動

##Ctrl + E
行末へカーソル移動

##Ctrl + U
カーソル位置から行頭まで削除

##Ctrl + K
カーソル位置から行末まで削除

##Ctrl + L
ターミナル画面をクリアにしてカーソルを一番上に持っていく

##date
現在の時刻を表示

##cal
カレンダーを表示

##pwd
カウントディレクトリの表示

##cd
ホームディレクトリへ移動

##sudo -s
rootユーザーに切り替える

##

##参考
Linuxコマンド入門教室
【Rails】bundler-auditの使い方

# `bundler-audit`とは

`bundler-audit`はプロジェクトで利用しているGemの脆弱性の有無をチェックしてくれるGemです。
システムの脆弱性チェックの一つとして利用できますね。

# 検証した環境

- Ruby 2.7.0
- bundler-audit 0.6.1

# 準備

## bundle install

Gemfileに以下を追加して`bundle install`

```ruby:Gemfile
group :development do
  gem 'bundler-audit'
end
```

```sh
$ bundle install
```

## 脆弱性チェックに使用するDBを更新する

脆弱性チェックを実行する前に、`bundler-audit`が使用するDBの更新を行いましょう。

```
$ bundle exec bundler-audit update
```

このコマンドでは、実際には`$HOME/.local/share`ディレクトリ配下に[rubysec/ruby-advisory-db](https://github.com/rubysec/ruby-advisory-db)を`git clone`しているようです。

# 脆弱性の存在するGemをチェックする

実際に`bundler-audit`を実行してGemの脆弱性をチェックしてみましょう。
以下のコマンドで実行できます。
脆弱性が見つからなかった場合は`No vulnerabilities found`と出力されます。

```
$ bundle exec bundler-audit
No vulnerabilities found
```

## DBの更新と脆弱性チェックを同時に実行する

以下のコマンドで脆弱性チェックに使用するDBの更新と脆弱性チェックを同時に実行できます。
DBの更新忘れを防ぐためにも、基本的には以下のコマンドを利用するほうがいいでしょう。

```
$ bundle exec bundler-audit check --update
```

# 実際に脆弱性があるGemをインストールして検証してみる

`bundler-audit`の出力を確認するために、実際に脆弱性が存在するGemのインストール~脆弱性チェック~修正までやってみます。

## 脆弱性があるGemをインストール

実際に脆弱性が存在するGemをインストールしてみます。
ここでは試しに`bootstrap`の`v4.3.0`をインストールしてみます。
`Gemfile`に以下を追記して`bundle install`。

```ruby:Gemfile
gem 'bootstrap', '4.3.0'
```

```sh
$ bundle install
```

## 脆弱性をチェックする

`bundler-audit`を実行してみます。

```sh
$ bundle exec bundler-audit
Name: bootstrap
Version: 4.3.0
Advisory: CVE-2019-8331
Criticality: Medium
URL: https://blog.getbootstrap.com/2019/02/13/bootstrap-4-3-1-and-3-4-1/
Title: XSS vulnerability in bootstrap
Solution: upgrade to >= 4.3.1

Vulnerabilities found!
```

脆弱性が見つかったGemとその内容、解決するバージョンまでわかりやすく出力してくれます。

## 脆弱性を無視する

場合によっては`bundler-audit`によって見つかった脆弱性を無視したいこともあるかと思います。
そういうときは`--ignore`オプションに無視したいAdvisoryを指定しましょう。

```
$ bundle exec bundler-audit --ignore CVE-2019-8331
No vulnerabilities found
```

## 脆弱性のあるGemのバージョンを上げる

先ほど`bundler-audit`で出力された内容には

```
Solution: upgrade to >= 4.3.1
```

と書いてあったので、それに従って`Gemfile`を修正してみます。
（※実際には`Gemfile`にバージョンを指定していない場合の方が多いと思うので、その場合は`bundle update`コマンド等を利用してください。）

```diff:Gemfile
-gem 'bootstrap', '4.3.0'
+gem 'bootstrap', '4.3.1'
```

```
$ bundle install
```

`bootstrap`のバージョンを上げたのでもう一度`bundler-audit`を実行してみます。

```
$ bundle exec bundler-audit
No vulnerabilities found
```

警告が出なくなりました！

# 参考

- [rubysec/bundler\-audit: Patch\-level verification for Bundler](https://github.com/rubysec/bundler-audit)
3Dモデリングツールを作る①

##はじめに
作ってます。

#何を
3D のゲームを作ろうと思っていますが、いかんせん全部俺です。そこで疑似的なモーフィングで 3D キャラクターを量産するためのツールを作って楽をします。

モデル A とモデル B の中間モデルを生成するツールです。一般的にはモーフィングを使えばそんなものは 1 秒でできるのですが、条件としてモデル A とモデル B の頂点同士の対応関係が分かっている必要があります。
頂点の対応関係が分かっていないモーフィングツールは世の中にないと思う（たぶん）。あったら教えてください。

頂点の数自体が違う場合には直線や平面を近似できるように頂点を新たに生成する必要がありますが、この対応問題がまた難しい。対応問題が解ければモーフィングの補間問題を解けばよいです。

（ひどい絵だ）
![morphing3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/79b6023d-728a-5ef6-2f69-8e1fc0eae629.png)

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">モーフィングは<br>(1-α)A0+αA1<br>そんなことはサルの俺でも分かる<br><br>でも異種頂点の補完問題はレベルが違うやろがい😱<br>完成したら5000兆円下さい <a href="https://t.co/wYA1BBqP70">pic.twitter.com/wYA1BBqP70</a></p>&mdash; ユニカ@浮世離れ (@jojo15izumi) <a href="https://twitter.com/jojo15izumi/status/1223746577673490432?ref_src=twsrc%5Etfw">2020年2月1日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



先日お試し版の設計を終えて実装してみたところ叫び声をあげてしまった。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">全然進まん<br>気づいてしまったんやけど耳は耳、尻尾は尻尾と対応させるにはタグが必要じゃないですかヤダー<br>ヤダー自動がイイーヤダー <a href="https://t.co/dAt2Xq8vVH">pic.twitter.com/dAt2Xq8vVH</a></p>&mdash; ユニカ@浮世離れ (@jojo15izumi) <a href="https://twitter.com/jojo15izumi/status/1235896129327222790?ref_src=twsrc%5Etfw">2020年3月6日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ある程度相似な物体同士であれば数学的に変換できるけども、そうじゃない場合には目と耳だったり、背中と尻尾だったり、もっというと目尻と目頭とか絶対に一致しないことに気づいた。（当たり前なんだけどね。）
ということで今は半ば断念してしまっている。

アイデアはあるにはあるんだけど手作業が必要なので嫌なのです。

あと１カ月で妙案が出なければ打ち切ってゲームの開発に入ります。
Linux概要

# Linux概要

- 広義のLinux:Linuxディストリビューション
    - Linuxを利用できるようにまとめ上げた配布形態
- 狭義のLinux:Linuxカーネル
    - ハードウェアとソフトウェアの中立


Linux自体はOSのカーネルに過ぎない。
実際に使用するには以下のような機能レイヤーを追加する必要がある

- デバイスドライバ
- シェル
- デーモン
- コマンド

# Linuxカーネル機能

## 基本機能

- アプリケーションが動作するための基本環境を提供している
    - メモリのどの場所にデータを保存するか
    - CPUのリソースをどの程度どのアプリケーションに割り振ればイイか
- 役割は大別して2つ
    - アプリケーションからの要求に応えること
    - ハードウェアからの応答をアプリケーションに伝えること

## プロセス管理

- プロセスとは
    - メモリやCPUなどのリソースを割り当てる管理単位
    - 実行中のプログラムが利用するデータは、メモリに書き出してから使用する事になる
        - 演算の結果のデータ
        - コマンドラインで入力された値
        - 通信して取得したデータ
    - CPUがプログラムに従って、あるメモリのデータに対して演算を行なっている状態
    - 割り振られたリソースの上でプログラムはOS上のプロセスとして稼働する。
    - プロセスは基本的に役目を果たすと終了して、メモリなどの資源を解放する。
- ゾンビプロセス
    - 役目を終えているのにメモリを解放しない状態のプロセスのこと。
    - ユーザからkillコマンドを発行しプロセスを強制的に終了させることになる。
PowerBIのレポートを組織外の人にメール送信する方法


#背景
現状を分析する為にデータを可視化して見て欲しいと思ってる相手がいるのですが、そもそも「見て欲しい」と思われている状態なので、いろんな課題もあります。

* そもそも、現状分析に興味あるのか。。。
* そもそも、可視化しても見るのか。。。
* そんな状態なので、もちろんPowerBI Proのライセンスは持ってないし。。。
* 定期的にTeamsのチャンネルにレポートを通知しているが見てるのか分からないし。。。
* PowerBIの機能を使ってメールが送れるのは、組織内のアカウントのメールだけだし。
* そっちのメールに送っても、そっちのメールは見ているのだろうか。。。

なので、普段、仕事でやり取りしているメールアドレスに送れば、これなら見るだろうと思って、環境を作ることにしました。つまり、今回は本当に、組織外の人にメール送信する訳ではなく、本当は同じ職場だけどこっちのメールアドレスの方が確実に見るんじゃないかと思われるアドレスにメール送信する方法になります。

#システム構成
ざっくり言うと、PowerBIのサブスクライブの機能を使って、レポートのスナップショットを自分のメールアドレスに送信して、メーラー側でフィルタを掛けて、メールを転送する流れ。
PowerBIのサブスクライブのやり方は公式のMicrosoftDocsが参考になるので、[こちら](https://docs.microsoft.com/ja-jp/power-bi/consumer/end-user-subscribe)。

以下のような流れになります。
1. PowerBIの「メールの受信登録」で、定期的にレポートのスナップショットを自分宛にメールで送信
1. Outlookの「仕分けルール」で、「差出人」「件名」で転送設定
1. Outlookが自動で、見て欲しい人に転送してくれる
1. 仕事でやり取りしているメールなので、おそらく見ているはず！！！
![PowerBIスナップショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/670317f1-e200-0087-2a39-c2e98dc0cc17.png)

#結果
* 普段やり取りしているメールアドレスに、定期的に自動送信される環境が出来ました
* レポートの画面がスナップショットで送られるので、簡単に見ることができるはずです
* PowerBI Proの追加ライセンスを準備せずに、見て欲しい人に届けることが出来ました
* メールで送られるので、「俺はメールしか見てない」みたいな人にも対応できます
* でも、結局、見てるかどうかは不明。。。

#まとめ
個人的にはPowerBIProライセンスを用意して、意識を持って、「みんなでちゃんと見ようよ」って思うのですが、そもそも見てるかどうか分からないし、リアクションもないからメールで送ろうって話になる訳だから、いきなりPowerBIProライセンスって話しても、更に何？？？ってなりそうだし、とりあえず、メールで送り続けてみることにします。

# 注意点：メールの転送設定
Outlookの転送設定で「差出人」は入れたほうが良いです。最初は、こんな件名で送ってくる人いないだろうしいいかって思ってルールを決めたら、内容に対して返信してくれる人がいたので、またそのメールが転送されるという面倒臭いことになったので、「差出人」は重要です。
TDD（テスト駆動開発）って？？

TDDについてのアウトプットを行います。
#TDDとは？
簡単に言うと、
####①テストコード ②実装、リファクタリングの順で多なっていく事

#なんで、先にテストコードを書くん？
####実装と修正のサイクルを定期的に行うため
その必要性は、常にエラーを意識しながら実装していくためです。
結果、その都度エラーを発見することができると言うことですね。
#どんな方法で行うん？
####①失敗のコードを書く　
####②成功のコードを書く　
####③リファクタリング
##失敗のコードを書く意味って何なのでしょうか？
####『エラーになると思っていたコードがエラーにならない！？』ってな事が起きないようにするためですね。
例えが合っているか怪しいですが、
（例）1+1=4とエラーコードを書きました。しかし、返ってきた答えがエラーではなく『成功』してしまう。ってな異常事態を防ぐためですね。
##成功のコードを書くときは？
この時に注意することは、最低限のコードでいいからテストを成功させる事。
消して整ったコードを書いて成功させなければならないと言うわけではないと言う事です。
#終わりに
最低限のアウトプットではありますが、ここからアップデートして行きます。
モデルメソッドの使い方


メソッドを定義してuseして使うだけ

```php
# 使い方(Personモデルでの例)
use App\Person; #コントローラでuse

$person = Person::all(); #インスタンス取得
$Person->モデルメソッド(); #メソッドを使用
```

####viewで表示する例：

```Person.php
	# メソッド定義
  public function getData()
  {
    return $this->id . ':' . $this->name . '(' . $this->age . ')';
  }
```

```PersonController.php

use App\Person;
use Illuminate\Http\Request;

class PersonController extends Controller
{
  public function index(){
    $people = Person::all();
    return view('person.index', ['people' => $people]);
  }
}

```

```person/index.blade.php
  <table>
    @foreach($people as $person)
    <tr>
    <!-- ここでメソッド呼び出し -->
      <td>{{ $person->getData() }}</td>
    </tr>
    @endforeach
  </table>
```
bundle install でNokorigiインストール時に「Gem::Ext::BuildError: ERROR: Failed to build gem native extension.」エラーが出た場合の対処方法

`bundle install`でnokogiriインストール時に下記のようなエラー

```
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
```

が出てしまった場合

gem install時であれば `--use-system-libraries` オプションを付けて再実行してみるところですがbundlerの場合はどうすればいいかというと

`bundle config --local build.nokogiri --use-system-libraries`

というような感じでコマンドを実行します。

`--local`オプションは`app/.bundle/config`へ設定を書きます。
`--global`オプションは`~/.bundle/config`に書くようです。

まあよほどの事情がない限り、プロジェクトごとの`.bundle/config`に書いておくほうが良いと思います。その他、環境変数にも定義できます。

### bundle configの優先順位

bundle configですが、mysqlなどと同様、複数の箇所に設定を保持しておけます。用途によって適切な場所に設定を書いておくのがいいと思いますが、bundleコマンドのhelpによると

```
DESCRIPTION
       This command allows you to interact with Bundler´s configuration system.

       Bundler loads configuration settings in this order:

       1.  Local config (app/.bundle/config)

       2.  Environmental variables (ENV)

       3.  Global config (~/.bundle/config)

       4.  Bundler default config
```

という優先順位で参照されます。
【Linux】プロセスとジョブの終了、どっちがベター？

#プロセスとジョブの違いって何

同じ意味で使いがちだけど、、、と思って調べてみました。

###ジョブは処理全体の流れ
牛を育てるところから、食べる人に届くまでがジョブ。
![job.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373778/5c0956dc-ea1a-c672-08ad-07e173e0919f.jpeg)

###プロセスはひとつひとつの作業
牛を育てる：１プロセス
運送：１プロセス
…
![process.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373778/0bde064b-1dc7-177a-eff0-6dfb76b21f06.jpeg)

ps コマンド：process status　実行中プロセスの表示
jobs コマンド：実行中ジョブ表示

たとえばkillコマンドさんはプロセスの終了に使う。

```Linux:killコマンドさん
kill [PID]
#プロセスID[PID]を渡す
```

ということは、たくさんのプロセスを実行しているジョブさんでは、
終了したいなー→一つのプロセスを終了→ジョブ自体は終了していない可能性あり

ということで、ジョブの終了はジョブごと終了するほうがベターかも。
gnuplot で、フォルダ内の全てのファイルを描画する


同じフォーマットの複数のファイルがあるとき、例えばそれがdataA, dataB, dataCだったら、

```
plot for [i in "dataA dataB dataC"] i
```

で、複数のグラフを描画できる。
ただし、タイトルをつけないとわかりにくいので、

```
plot for [i in "dataA dataB dataC"] i title i
```

が良い。
では、`" "`の中を、シェル関数の`ls`を使って表現すると、途端に難しくなった。
原因は区切り文字。
`ls`の個々のファイル名の間にスペースを挟む必要がある。
スマートに書けなかったので、以下ではわざわざ`awk`を使っている。

```
plot for [i in "`ls | awk '{print $1" "}' `"] i title i
```
外部のシェル関数をいじっていて、
`awk`の中の `$1" "`で、ファイル名+スペースを表現している。

他に、いい方法がないのかなぁ・・・

### 参考
[Plot コマンドの for ループ](http://takeno.iee.niit.ac.jp/~foo/gp-jman/data/20170823/gnuplot-ja-div/node187.html)
よく利用するDocker, Docker-compose コマンド

# Docker

**Dockerの起動**

```
$ sudo systemctl start docker
```

**Docker hubへのログイン/ログアウト**

```
$ docker login/logout
```

**Docker image一覧**

```
$ docker image ps
```
REPOSITORYはイメージの名前。

**Docker image ダウンロード**

```
$ docker image pull [オプション] [イメージ名：タグ名]
$ docker image pull [URL]
例：
$ docker image pull centos:7

DockerへアップロードしたImageをダウンロードすることも可能。
$ docker pull [dockerhubのユーザ名]/[イメージ名：タグ名]
```
タグ名を省略されると、最新版がダウンロードされます。-aオプションを指定すると、すべてのイメージがダウンロードされます。

**Docker imageの詳細**

```
$ docker image inspect centos:7
```
イメージID、作成日、Dockerバージョン、CPUアーキテクチャ

**Dockerでイメージにタグ名を設定**

```
$ docker image tag [イメージ名] [dockerhubユーザ名]/[コンテナ名]:[バージョン]
```

**イメージの検索**

```
$ docker search --limit 検索キーワード
```

**未使用のdockerイメージの削除**

```
$ docker image prune [オプション]
オプション：
--all, --a　使用していないイメージをすべて削除
--force, --f　イメージを強制的に削除する
```


**Docker container一覧**

```
$ docker container ps
$ docker ps -all
```

**Docker container 起動/停止/削除**

```
$ docker container run/start/stop/rm [コンテナ名]
------
runは生成＆起動です。
-dオプションをつけると、バックグラウンドで動きます。
```

**コンテナのログの確認**

```
$ docker container logs -t [コンテナ識別子]
```

**コンテナ起動の最も簡単な一例**

```
$ docker container run -it --name "test1" centos /bin/cal
------
docker container runはコンテナを作成、実行
-itはコンソールに結果を出すオプション
--name "test1"はコンテナ名
centosはイメージ名
/bin/cal/はコンテナで実行するコマンド。/bin/bashを入力すると、コンテナ内でシェルを実行することもできます。
```

**Dockerイメージの中に入る**

```
イメージの一覧からログインしたいイメージを確認します。
$ docker images
REPOSITORYカラムに表示されている名称を指定して、以下のコマンドでイメージにログインします。
$ docker run --rm -t -i イメージ名 /bin/bash
```

**container 稼動確認**

```
$ docker container stats コンテナ名
```

**コンテナへ入る**

```
$ sudo docker exec -it [コンテナID] bash
```


**containerの起動/停止**

```
$ docker start/stop コンテナ名
```

**Dockerの実行環境確認**
コンテナの数、Dockerのバージョン、ストレージドライバの種類、OSの種類、アーキテクチャ

```
$ docker system info
```

**Dockerのディスク利用状況(詳細確認-v)**

```
$ docker system df
```

## Docker 応用編

```
$ docker container run --name webserver -d -p 8080:80 nginx
```
Dockerイメージnginxを使ってwebserverという名前のDockerコンテナを起動します。その際、ブラウザからHTTP80番ポートでのアクセスを許可するため、-pオプションでコンテナからの転送を許可しています。
ホストの8080ポートにアクセスすると、コンテナ上で動作しているNginx（80番ポート）のサービスにアクセスできます。また、指定したレンジのポート番号を割り当てたいときは、--exposeオプションを使用します。さらに、ホストマシンの任意のポートを割り当てるときは、-Pオプションを使用します。

そのほかに、DNSサーバ、MACアドレスの指定も可能です。

**コンテナをtarファイル出力**

```
$ docker container export　[コンテナ識別子]
例：
$ docker container export [コンテナ識別子] > [ファイル名.tar]
生成されたtarファイルの中身を確認する。

$ tar -tf [tarファイル名] | more

```


# Docker-compose

**Dockerコンテナのシェルの中に入る**

```
$ docker exec -i -t コンテナ名 bash
```

**複数のDockerコンテナの起動/リソース削除/停止/確認**

```
$ docker-compose up/down/stop/ps/logs
```

Compose定義ファイルのバージョンとDokcer Engineのバージョンにマッピング関係があります。
それぞれに対応するバージョンがあります。

**コンテナの生成**

```
$ docker-compose up --build
```

任意の名前のDockerfileをビルドするときは、[dockerfile]を指定します。その際、DockerfileがあるディレクトリのパスやGitレポジトリのURLをcontextで指定します。

```ymal
services:
 webserver:
  build:
   context: /data
   dockerfile: Dockerfile-alternate
```
一発でコンテナを削除
https://qiita.com/shisama/items/48e2eaf1dc356568b0d7
統合版Minecraftサーバのセキュリティ対策はじめの一歩

# はじめに
前回の記事では統合版 Minecraft サーバを建てました。インターネット上に公開すると色々な人がアクセスしにくる可能性があるので、自分達の身を守るためにしっかりとセキュリティ対策をしよう。
一般にサーバを守る方法は色々ありますが、今回は標準の Minecraft の機能だけで実現できるセキュリティ対策をやっていくよ。ほとんどはJava版でも使えます。
（前回建てた ubuntu サーバのファイル編集を行うので、Linux OS の知識が少しあるとよい。ここでは Linux の使い方は説明しません。）

#1. ホワイトリスト
Minecraft は接続を許可するユーザを管理する「ホワイトリスト」を作ることができます。ホワイトリストを上手に管理することで、信頼できる友達とだけ遊ぶ環境を作ることができます。
サーバ側のコマンド、またはオペレータ権限を持ったゲーム内ユーザのコマンドからホワイトリストを操作できます。
デメリットはやはりホワイトリストの管理が必要な事ですが、参加者が特定できる環境であれば一番有効です。
（以下はサーバ上で実施した例、ゲーム内で実施する場合はコマンドの最初に / を付けましょう。）
![whitelist1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/45d7c835-2e12-1b7d-fa0b-2b4e23145c60.png)
ホワイトリストにユーザを追加するには以下のコマンドを使います。

```shell
whitelist add ユーザ名
```
名前を間違えた等で、ユーザを削除するには以下のコマンドを使います。

```shell
whitelist remove ユーザ名
```
ユーザの追加を行ったら、ホワイトリスト機能を有効にします。

```shell
whitelist on
```
![whitelist2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/a3a417a7-01db-1a86-84b5-96dfdc26773c.png)
ダメでした・・・統合版では有効化コマンドは使えないのかもしれない。（教えて偉い人）
という訳で、ホワイトリストを有効化するためにサーバ上のファイルを直接編集します。
サーバが置かれているディレクトリの中に「server.properties」というファイルがあるのでこれを編集します。
![Minecraft 2020_03_20 18_29_34_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/966a447b-38e2-aa4a-b887-0a11a08be70c.png)
white_list=false と書かれた箇所を見つけて、white_list=true に書き換えましょう。

```shell
white-list=true
# If true then all connected players must be listed in the separate whitelist.json file.
# Allowed values: "true" or "false"
```

これでサーバを起動すればホワイトリストが有効になっています。私のユーザ名 JohnikiJoestar はホワイトリストに書いてない（書いてあるのは末尾に1,2,3がついた３人）ので、ログインできない人になっています。
![root@mcapsv01_ _minecraft - Google Chrome 2020_03_20 18_28_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/488e3cad-a1e9-dc28-0c00-24519ef81ae0.png)

#2. ブラックリスト（Java版限定）
ホワイトリストの反対で、接続を拒否するユーザを管理できます。ユーザ名とIPアドレスの情報を使って制御できますが、どちらも攻撃者側が変更してしまえば意味がなくなるため、いたちごっこになります。
限定サーバに限っていえばホワイトリストで十分なので、ブラックリストを使う理由は特にありません。緊急時や一時的な防御と思ってもらえればよいです。

```shell
ban ユーザ名
ban-ip IPアドレス
```

#3. ポート番号
統合版 Minecraft サーバが使うポート番号はデフォルトで 19132 ですが、これを変えてしまう手もあります。漏洩してしまえば意味が無いですが、少なくともデフォルトじゃない時点で不正アクセスのハードルは上がります。「server.properties」ファイルの中の下記数字を書き換えればよいです。もし変えるならばですが、説明に書いてある範囲は少し嘘っぱちなので 50000 より上あたりを適当に使っておきましょう。変えた場合は、ファイアウォールルールやクライアント全員の設定も変える必要があります。

```shell
server-port=19132
# Which IPv4 port the server should listen to.
# Allowed values: Integers in the range [1, 65535]
```




以上、セキュリティ対策はじめの一歩でした。
Macをクリーンインストールした後にやったこと

備忘録です。

#Mac設定
###Dock
Dockサイズ変更
Dockを自動的に表示/非表示をオン
###キーボード
F1、F2などのキーを標準のファクションキーとして使用をオン
入力ソースに半角カタカナを追加
###トラックパッド
タップでクリックをオン
###アクセシビリティ
ポインタコントロール>トラックパッドオプション>ドラッグを有効にするをオンにし3本指のドラッグを選択
####一般
最近使った項目の記憶数を0に設定
####Finder設定
新規Finderウィンドウで表示する場所をユーザ名にする
#####サイドバータブ
- [ ] 最近の項目
- [x] ユーザ名ディレクトリ

#アプリ導入
###Google Chrome
公式サイトからdmgをDLしインストール
###Xcode
App Storeからインストール
###homebrew
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```
####brewからインストール
```
brew cask install visual-studio-code
brew cask install mi
brew cask install sourcetree
brew cask install docker
```
####anyenv
```
brew install anyenv
anyenv init
echo '#anyenv settings' >> ~/.zshrc
echo 'eval "$(anyenv init -)"' >> ~/.zshrc
anyenv install --init
```
####node.js
anyenv install実行にnode-buildが必要なため先に入れる。

```
anyenv install nodenv
brew install node-build
echo yarn >> $NODENV_ROOT/default-packages
nodenv install 12.16.1
nodenv global 12.16.1  #LTS版を選択
nodenv rehash
```
初めての　AtCoder

#初投稿
何もわからなかったのでこれを触ってみました
[Welcome to AtCoder](https://atcoder.jp/contests/practice/tasks/practice_1)
内容は、こんな感じ![スクリーンショット 2020-03-20 19.50.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606053/27386cae-a064-97c3-2c02-1e7793cf3d3c.png)

とりあえず下に解答例があったので写してみた
![スクリーンショット 2020-03-20 19.51.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606053/0adc7c27-6f7f-fc0d-f28a-f74e1edaea98.png)

もうどこがなんの役割をしているかさっぱりわからなかったのでいろいろ調べることになりました
cinってconsole input ってことだったんですね！

今後もいろいろ知っていきたいです

## 翌日　追記

```c++
#include<iostream>
using namespace std;
int main(){
	int a;
  	cin >> a;
  	cout << a+1;
  	cout << "\n";
  
  	int b,c;
  	cin >> b >> c;
  	string s;
   	cin >> s;
  	cout << (a+b+c) << " " << s << endl;
	return 0;
}
```

スクショだと使い勝手悪いので、ソースコードをQiitaからコピペできるようにしました。
自分で色々追加してaに+１できるようにしたり、改行のやり方を学びました。
Goでデスクトップアプリを作る (QlovaSeed HelloWorld編)

# 概要
[QlovaSeed](https://github.com/qlova/seed)というクロスプラットフォームフレームワークを使ってデスクトップアプリを作ってみます。


# 環境
- `OS: Windows [Version 10.0.18362.720]        `
- `Go: go1.13.8 windows/amd64  `

# 準備
## 1. プロジェクト作成
まず、プロジェクトを以下の手順で作成します。[^1]

```bash
mkdir hello-world
go mod init hello-world
```

## 2. go.modを編集

QlovaSeedをそのまま`go get`すると`blackfriday/v2`が取得できないので、以下のように`go.mod`を編集して解決します。[^2]

```go.mod
module hello-world

go 1.13

require (
	// …
    //追加!!
	gopkg.in/russross/blackfriday.v2 v2.0.1
)
//追加!!
replace gopkg.in/russross/blackfriday.v2 => github.com/russross/blackfriday/v2 v2.0.1
```

## 3. QlovaSeedライブラリを入れる
下記コマンドをターミナルに入力し、ライブラリを取得します。

```bash
go get github.com/qlova/seed 
```

## 4. アプリ本体のコードを書く
最後にコードを書いていきます。


まず、`seed.NewApp(string)`でアプリを作成します。

次に、スペースを配置するために`expander.AddTo(App)`を配置します。これは、他にものが存在しない限り広がります。これを複数組み合わせることによって、テキストなどを任意の場所に配置できます。以下の例ではウインドウの縦における 3/1, 3/2 のところにテキストを配置しています。

スペースを配置したら`text.AddTo(App, string)`でtextを配置します。この定義したtextに対して何も装飾などを行わない場合はこのまま記述するだけですが、そうでない場合は`Text := Text.AddTo(App, string)`と結果を変数に代入することであとから装飾をすることができます。下記の例では`Text.SetColor(seed.RGB(116, 196, 133))`とすることで色を付けています。 

最後に、`App.Launch()`とすることでアプリを立ち上げます。

```main.go
package main

import (
    "github.com/qlova/seed"
    "github.com/qlova/seeds/text"
    "github.com/qlova/seeds/expander"
)


func main() {
	//アプリを作成
    var App = seed.NewApp("Hello World")	

    expander.AddTo(App)	//スペース
    text.AddTo(App, "Hello World!")	//テキストを配置
    expander.AddTo(App)	
    Text := text.AddTo(App, "Hello QlovaSeed!") //テキストを配置後Textに代入
    Text.SetColor(seed.RGB(116,196,133))	//Textに色を設定
    expander.AddTo(App)	

	//アプリを起動
    App.Launch()
}
```

## 5. ビルドして、HelloWorld！
`go run main.go` を打つと、ウインドウが立ち上がります！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298844/7539245c-1f38-c977-d13f-5843ac611aac.png)




# 最後に
作る時はGithub上のexampleが結構参考になると思います。[^3]


[^1]: [Go Modulesも触れてみるGo入門]( https://tech.opst.co.jp/2019/07/09/go-modules%E3%82%82%E8%A7%A6%E3%82%8C%E3%81%A6%E3%81%BF%E3%82%8Bgo%E5%85%A5%E9%96%80/)
[^2]: [Code no longer builds due to broken URL github.com/russross/blackfriday/v2 #500](https://github.com/russross/blackfriday/issues/500)
[^3]: https://github.com/qlova/seed/tree/master/examples
報連相のコツ

## 報連相のコツ

**相手に何をしてほしいかを伝えること**

## 説明のコツ　≠　報連相のコツ

* 結論から話す
* 論理的に話す
* 物事を MECE に分けて話す
* etc.

これが「報連相のコツ」だ、と教えられたかもしれない。

残念、これは「**説明のコツ**」であり、別物だ。

* 結論から・論理的に・物事をMECEに「説明」をしても
* 「報連相 = 相手に動いてもらう行為」をしているわけではない

## 説明は上手だが、動いてもらえない

「報連相される側」は **何をしてほしいかを伝えてもらうこと** を求めている。

実際に

* 「それで、私は何をすればよいでしょうか」
* 「うーん、では何をどうしたらよいですか」

と言われた経験はないだろうか。これは、裏を返せば

* **今まで** のことは分かった、しかし **これから** どうすべきかが分からない
* **説明だけで終わりなんですか？この後どうすればいいですか**

と投げかけられているのだ。ここにイチ早く気付こう

## いかに報連相するか

繰り返しになるが 「**相手に何をしてほしいかを伝える**」ことを一番に考える

MECE・論理・結論、こいつらは二の次だ。

**説明上手は人を動かせない**

### 報告

**その報告を受けた後、何をすればいい？**

あなたに部下・後輩がいるとして、下 3 つの話を聞いたとしよう。

```
* (1) バグが発生したので、障害レポートを書きました
* (2) 指摘内容を修正しました
* (3) 担当の仕事が遅れています
```

この後あなたは何をしたらよいか分からないだろう。

同様の報告を日次的にやっているかもしれない。

...

報告するときは、相手に **「この後どうしてほしいか」** を伝えよう

```
* (1) バグが発生したので障害レポートを書きました。
      このバグを優先度高めで修正するかどうか指示をお願いしたいです。
====> [[ バグ修正への指示を仰いで欲しいと、相手に動いてもらう ]]

* (2) 指摘内容を修正しました。
      修正が指摘通りか確認をお願いします。
====> [[ 指摘通りの修正なのか再確認してもらうよう、相手に動いてもらう ]]

* (3) 担当の仕事が遅れています。
      あと 1 日あれば巻取れるので、猶予を 1 日もらえないでしょうか。
====> [[ 締切の猶予を貰えるように、相手に動いてもらう ]]
```

### 連絡

**連絡を受けた後、何をすればいい？**

**3 秒後に忘れられるような連絡は、ただの大きな独り言だ**

下のような連絡をうけることはよくあるだろう

```
* (1) 来週月曜の 17:00 に共通管理している資料の入れ替えをします
* (2) 機能 X に Y という仕様変更をする予定です
* (3) 明後日休みます
```

「連絡をもらった側は」何をすればよいだろうか。

**連絡をもらった側が何をすべきかも含めて、連絡としよう**

```
* (1) 来週月曜の 17:00 に共通管理している資料 X の入れ替えをします。
      入替にどうしても問題がある人は教えてください、日程をずらすことは出来ます。
====> [[ 資料入替に問題がある人だけに、動いてもらうようにする ]]

* (2) 機能 Y に Z という仕様変更をする予定です。
      独立した機能の認識ですが、影響を受ける開発担当がいらっしゃれば教えてください。
====> [[ 機能変更に影響がある人だけに、動いてもらうようにする ]]

* (3) 明後日休みます。
      その日までに打ち合わせが必要な人は Web の予定表にて、空き時間に予定をいれておいてください。
====> [[ 要件がある人だけに、動いてもらうようにする ]]
```

### 相談

**悩みを打ち明けるのは相談ではない**

**「助けてもらえなければ」意味がない。**

あなたは下のような相談をして「助けてもらったこと」はあっただろうか。

```
* 担当の仕事は何をすればよいかわかりません
* 今回が初めての出張なので社内手続きの方法が分かりません
* 仕事がつらいです
```

こういった相談のようなものは大抵

* 相談相手(おそらく上司や先輩、etc.) が色々聞いてきて
* 「挙句の果て」に
* 「じゃあ、どうしようか」と切り出された = 助け舟を貰った

のではなかろうか。

相談では **「自ら助けてもらおうとする」** ことが必要である

```
* (1) 担当の仕事は何をすればよいかわかりません。
      まず何をから始めて行くべきか、足がかりを教えていただけないでしょうか。
====> [[ 担当の仕事の始め方すら分からないので、その「始め方」を尋ねる ]]

* (2) 今回が初めての出張なので社内手続きの方法が分かりません。
      手続きを示した資料などの「ありか」があれば教えて欲しいです。
====> [[ 出張手続きを形式化したものがあるかどうか、その「ありか」を訪ねる ]]

* (3) 仕事がつらいです
      1ヵ月にこなさなければいけない仕事量が、自分は他の担当者に比べて明らかに多いので、
      均等な分担をお願いしたいです
====> [[ 仕事の分担を願い出る(上位者・指揮者に対して) ]]
```

## おさらい

報連相のコツは **相手に何をしてほしいかを伝える事**。

## 脱線話

「相手に何をしてほしいか」を伝えた後

「なぜ動いてほしいか・どういった理由で動いてほしいか」を「説明のコツ」で補うと

筋の通った報連相になる。テンプレにすると下のような体裁になる。

```
xxx をお願いしたいです(報連相)

まず、yyy が発生しました(結論)

zzz という経緯があるからです。(論理説明 - 経緯説明)

なぜ zzz が起きたかというと (論理説明 - 理由説明)

* 理由1 (MECE)
* 理由2 (MECE)
* 理由3 (MECE)

以上踏まえて xxx をお願いしたいです (報連相の念押し)
```

これ一つで記事が書けるのでここでは脱線話程度にしておきたい。
Ubuntu19.10からNVR500へVPNしたい

# 対象
Ubuntu: 19.10
YAMAHA NVR500 Netvolante router: Rev.11.00.38

# ルータ設定
1. 詳細設定と情報 > VPN接続の設定 を開く。
1. 設定可能なVPN設定 から Anonymousユーザを追加する。
1. 先に登録した設定の登録の修正を開く。
1. VPN Anonymous 接続 共通設定を開く。
1. 以下の状態に設定する。

| 項目名 | 設定値 |
|---|---|
| 認証アルゴリズム | HMAC-SHA |
| 暗号アルゴリズム | 3DES-CBC |
| PPP方式 | MS-CHAP v2 |

# Ubuntu側の設定
## 1. 前提パッケージのインストール

```bashコマンド
apt install network-manager-l2tp-gnome
```

## 2. VPN設定
1. gnome設定 > ネットワークを開く
![Screenshot from 2020-03-20 19-14-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/2b4a5d9f-8b7d-5104-6d3c-f0fa75646ecc.png)

2. VPN接続の追加を開く
![Screenshot from 2020-03-20 19-15-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/ce97254e-ef6f-3565-00d6-7afa209a0468.png)

3. Layer 2 Tunneling Protocol(L2TP)を選択し、以下の状態に設定する。
![Screenshot from 2020-03-20 19-18-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/5424d7b8-51fa-8d54-9471-d865b29a1420.png)

4. IPsec Settings...を開き、以下の状態に設定する。
Pre-shared keyは事前共有鍵を入力。
![Screenshot from 2020-03-20 19-19-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/4ec54070-847a-68f8-cbe2-2cae4400f5eb.png)

5. OKをクリックして戻り、PPP Settings...を開き、以下の状態に設定する。
![Screenshot from 2020-03-20 19-22-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567239/a2c4c352-069a-5e7b-1377-41bede74d910.png)

## 3. 接続テスト
失敗する場合は、事前共有鍵とログインパスワードが正しいか確認する。
両方とも正しい場合、L2TPかIPSecのプロトコルが一致しているか確認する。
Liberica JDK 11 の JavaFX 11 (OpenJFX) で Hello World する

『みんなの Java OpenJDK から始まる大変革期！』を読んでいて、何となく Liberica JDK 11 の JavaFX 11 で [Getting Started with JavaFX](https://openjfx.io/openjfx-docs/) をやってみたのでメモっとく。

ほとんどの OpenJDK ディストリビューションには JavaFX (OpenJFX) は含まれていない。なので、Getting Started with JavaFX の手順を素直にやるとちょっと手間がかかる。でも、Liberica JDK 11 を SDKMAN! などでインストールすれば簡単に JavaFX 11 で遊べる。

# SDKMAN! で Liberica JDK 11 をインストールする

[SDKMAN!](https://sdkman.io/) で Liberica JDK 11 をインストールする。JavaFX が含まれないバージョンもあるので注意する。インストールできる Java バージョンの一覧は `sdk list java` コマンドで確認できる。

```shell-session
$ sdk install java 11.0.6.fx-librca
```

# Getting Started with JavaFX のコードで Hello World する

HelloFX.java というファイル名で下記のコードを保存する。Java と JavaFX のバージョンを取得して、それを含めた文字列で Label コントロールを生成し StackPane レイアウトに配置して表示しているようだ。

```java:HelloFX.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HelloFX extends Application {

    @Override
    public void start(Stage stage) {
        String javaVersion = System.getProperty("java.version");
        String javafxVersion = System.getProperty("javafx.version");
        Label l = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");
        Scene scene = new Scene(new StackPane(l), 640, 480);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

}
```

それではコンパイルして、実行してみよう。SDKMAN! で Liberica JDK 11 が設定されていることを必ず確認すること。設定されていなければ `sdk use java 11.0.6.fx-librca` コマンドを実行してから、下記のコマンドを実行してね。

```shell-session
$ sdk current java
Using java version 11.0.6.fx-librca
$ javac HelloFX.java
$ java HelloFX
```

こんな画面が表示されたら成功。

<img width="640" alt="Hello, JavaFX 11.0.6, running on Java 11.0.6." src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67627/5e7665fb-b949-968d-04fe-c5655775fe06.png">

アプリケーションとして配布するとなると考えることは多いけど、社内ツールで簡単な GUI がほしいとかそういうことであれば、Liberica JDK 11 を用いた JavaFX は便利そうだ。

---

今回は Liberica JDK 11 の JavaFX 11 (OpenJFX) で Hello World してみた。ちゃんとした開発環境を構築するとなると、IntelliJ IDEA と Scene Builder を利用するといいみたい。ちょっと眺めただけなのだが『The Definitive Guide to Modern Java Clients with JavaFX』にそういう開発環境の構築手順が記載されていた。


# 参考文献

みんなの Java OpenJDK から始まる大変革期！
The Definitive Guide to Modern Java Clients with JavaFX
コンポーネントイベント

 1.自体通信
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393170/d61f49a5-eb2e-db64-1901-09a6fefad342.png)
cmp：<<aura:handler>><<aura:registerEvent>>
js：cmp.getEvent("").fire()

2.子親通信
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393170/4f7d28ea-0a0e-0a35-c243-9e94b7fff433.png)
親cmp：<<aura:handler>>
子cmp：<<aura:registerEvent>>
子js：cmp.getEvent("").fire()

3.親子通信（下記のやり方で通信できません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393170/d0a46d16-512f-6960-4e45-57d0fe39c62f.png)
子cmp：<<aura:handler>>
親cmp：<<aura:registerEvent>>
親js：cmp.getEvent("").fire()

4.親子通信（下記のやり方で通信できる）
子cmp：<<aura:method>>
子controll.js：call：function (component, event, helper) {}
親controll.js：
var aaa = component.find("子aura:id");
aaa.call();