OmniAICreator/Qiita-1.07M huggingface dataset:
誰でも勝てる三目並べAIで遊ぼう

#はじめに

先に，Canvas を用いた三目並べの作成について報告した[^1]。このとき，cpu が選択する一手は，乱数を用いる方法であった。これは簡単な方法であるだけに，試行してみると，非常に弱いことが分かる。三目並べ AI を強くする方法として，ミニマックス法が知られている[^2] [^3] [^4]。参考記事[^2] を参照しながら，Python をJavaScript に書き直すことによって，Canvas を用いた三目並べのプログラムに組み込んだ[^5]。

ゲームの面白さは，勝ったときに，より強く感じられる。そこで，初心者でも勝てるような三目並べ AI の開発を考えた。その結果，誰でも勝てる三目並べAIが完成した[^6]。やってみると判るように，誰でも勝てるだけでなく，負けようとしても勝ってしまう。引き分けに持ち込もうとしても，勝ってしまう。なぜ，そうなるのか，考えてみるのも面白いだろう。プログラム（最弱ミニマックス法）も置いてあるので，見ていただきたい[^7]。

#ミニマックス法の実装

JavaScript に書き直したミニマックス法の実装部分を，下記に示す。

``` Javascript
function minimax(depth) {
    // ミニマックス法で探索して，着手を返す
    if (state != GAME) { return evaluate(depth);}

    var best_value = 0;
    var value = 0;
    if (my_turn) { value = 10000;}
    else         { value = -10000;}

    for (var i = 0; i < 9; i++) {
        if (board[i] == 0) {
            put_value(i);
            var child_value = minimax(depth+1);
            if (my_turn) {
                if (child_value > value) {
                    value = child_value;
                    best_value = i;
                }
            }
            else {
                if (child_value < value) {
                    value = child_value;
                    best_value = i;
                }
            }
            undo_value(i);
        }
    }
    if (depth == 0) { return best_value;}
    else            { return value;}
}
```

#最弱ミニマックス法の実装

誰でも勝てる三目並べAI（最弱ミニマックス法）の実装部分を，下記に示す。

``` Javascript
function minimaxmin(depth) {
    // ミニマックスミニ法で探索して，着手を返す
    if (state != GAME) { return evaluate(depth);}

    var best_value = 0;
    var value = 0;
    if (my_turn) { value = -10000;}
    else         { value = 10000;}

    for (var i = 0; i < 9; i++) {
        if (board[i] == 0) {
            put_value(i);
            var child_value = minimaxmin(depth+1);
            if (my_turn) {
                if (child_value < value) {
                    value = child_value;
                    best_value = i;
                }
            }
            else {
                if (child_value > value) {
                    value = child_value;
                    best_value = i;
                }
            }
            undo_value(i);
        }
    }
    if (depth == 0) { return best_value;}
    else            { return value;}
}
```
#おわりに

Canvas を用いた三目並べのプログラムに，ミニマックス法を組み込んだ。また，この最強ミニマックス法のアルゴリズムを逆にすることによって，誰でも勝てる三目並べAI（最弱ミニマックス法）のプログラムを作成した。ゲームの初心者に，興味を持ってもらうのに役立つと思われる。

[^1]: [三目並べをCanvasとjQueryで作る](https://qiita.com/Sakurai_San/items/0d681f2fb994de772c02)
[^2]: [ミニマックス法で最強の3目並べAIを実装する話](https://qiita.com/army_sh/items/1ff678a0c184dff35116)
[^3]: [三目並べで学ぶミニマックス法](https://postd.cc/tic-tac-toe-understanding-the-minimax-algorithm/)
[^4]: [ミニマックス法を使ってマルバツゲームを実装した [Rust]](https://qiita.com/kahirokunn/items/1e0f15cceeeda0ab96d8)
[^5]: [三目並べ（対局レベル２）](http://waves.upper.jp/Computer/TicTacToe/TicTacToe02.html)
[^6]: [三目並べ（対局レベル－２）](http://waves.upper.jp/Computer/TicTacToe/TicTacToe-2.html)
[^7]: [三目並べ プログラム HTML JavaScript](http://waves.upper.jp/Computer/tictactoe.html)
シェルスクリプト bash for 文 算術式

bash では C言語のような for 文で記述が可能。

```bash:for-bash-example1.sh
total=0
for ((i = 1; i <= 12; i++))
do
  ((total += i))
done
echo "${total}"
```

do - done を { } で置き換えることができる。

```bash:for-bash-example2.sh
total=0
for ((i = 1; i <= 12; i++)) {
  ((total += i))
}
echo "${total}"
```

シェル変数(total)の初期化をfor文の中でできる。
最後の total の表示を算術式展開$((xxx))で行うことができる。

```bash:for-bash-example3.sh
for ((total = 0, i = 1; i <= 12; i++)) {
  ((total += i))
}
echo "${total}"
echo "$((total))"
```

iのインクリメントを省略したら、無限ループ。

```bash:for-bash-example4.sh
for ((i = 0; i <= 1;))
do
  echo "Test:${i}"
done
```

bash でしか動かないため、積極的に使わなくて良いと思う。
DialogflowのフルフィルメントWebhookで会話をすぐに終了させる方法

Google Homeを活用しようと思い、Google Cloud Functionsで外部APIを叩き、テキストを整形してその結果をGoogle Homeに喋らせるようなサンプルコードを作っています。

## Webhookでレスポンスを返すと、会話待機状態になってしまう

サンプル通りにActions On Googleでプロジェクトを作り、
Dialogflowのfulfillment Webhookを設定するような連携です。
Cloud Functionsを使用したのは、Always Free枠がたくさんあるのでWebhook endpointとして使うのにリーズナブルだったためです。

```
Google Home -> Actions On Google -> Dialogflow -> Cloud Functions -> 外部API
Google Home <- Actions On Google <- Dialogflow <- Cloud Functions <-
```

Google Homeに喋らせることはできたのですが、 **レスポンスを喋ったあと、会話待機状態になり、次の会話を受け付けようとする** という現象が発生しました。
レスポンスとして返却していたのは、喋らせたいテキストだけの非常にシンプルなJSONです。

```json

{
  "fulfillmentText": "今日のタスクは1件で、期限切れタスクが3件あります。..."
}
```

フルフィルメントだからなのかどうかまでは調べられていませんが、サンプルとして作ったGoogle Home用アプリは、アプリに接続し、接続状態を維持するようなアプリの挙動になっていました。
この状態のGoogle Homeアプリは、わざわざ「ねぇ、Google、ストップ」と話しかけないっとアプリが終了してくれないので、使い勝手が悪いです。

## 会話を終わらせるWebhookレスポンス

会話を終わらせる方法を調べると、とても簡単な方法がありました。
以下は、Dialogflowの Webhookフォーマットの会話を終了させるレスポンス例として載っていたものです。

[End conversation example - Dialogflow Webhook Format  |  Conversational Actions  |  Google Developers ](https://developers.google.com/assistant/actions/build/json/dialogflow-webhook-json?_ga=2.132146118.-996209516.1559469849#dialogflow-end-conversation-example)

> End conversation example
> 
> The snippet below shows an example of a simple response to end a conversation session in the Dialogflow webhook format. The `expectUserResponse` value of `false` in the response message signals to the Assistant that no further user input is expected and that it should end the current conversation.


```json
{
  "payload": {
    "google": {
      "expectUserResponse": false,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "Goodbye!"
            }
          }
        ]
      }
    }
  }
}
```

上記のサンプルのとおりに、 `payload.google.expectUserResponse` に `false` を指定します。そうすると、Google Homeに話しかけてレスポンスを喋ったあとに、アプリ自体が終了します。接続状態を維持するようなことがなくなりました。
CDATAの評価版ドライバをダウンロードして”DBVisualizer で CSV Data に繋いでみた”に挑戦

先日参加した東京のセッションで、エクセルデータの統合ドライバとしてCDATAが紹介されていました。
<br>
気になったのでCSVドライバの評価版を使ってみました。
CSVファイルに対してSELECTクエリが実行できるのですが、テーブル名の指定でハマりました。
<h2>JDBC CSVドライバをダウンロード</h2>
まずは<a href="https://www.cdata.com/jp/">CDATA</a>から評価版（30
日間）をダウンロードします。
今回は”CSV”を使用します。
<img width="397" alt="スクリーンショット 2019-11-24 9.04.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534084/11759379-6ba4-e34c-4034-2f16119bc94d.png">
どんどん進めます。
<img width="607" alt="スクリーンショット 2019-11-24 9.52.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534084/de23a3b3-9cad-7053-c202-ba9ac7bcc2e4.png">
”ダウンロード評価版”を選択します。
<img width="907" alt="スクリーンショット 2019-11-24 9.58.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534084/d219da18-eee9-5fde-727a-2fb9b182a3fb.png">
Eメールのみの入力でダウンロードできます。
サポートからメールが届くようになりますので、ビジネスでの利用を考えている方は連絡するとよいでしょう。
<img width="317" alt="スクリーンショット 2019-11-24 10.03.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534084/1d1e9ded-6210-7238-f60c-37da06d646bf.png">
ダウンロード完了です。
readmeを見るとJava6以上とあります。問題なし。
<h2>DBVisualizerで使ってみた</h2>
<a href="https://www.cdata.com/jp/kb/tech/csv-jdbc-dbv.rst">DBVisualizer で CSV Data に繋いでみた</a>を参考に進めます。
DBVisualizerをダウンロードしてインストールします。すぐできます。
<a href="https://www.dbvis.com/download/10.0">ダウンロードサイト</a>
<br>
では参考サイトの手順に戻ります。
DBVisualizerを立ち上げ、CSVドライバの読み込みを設定します。
<img width="1095" alt="スクリーンショット 2019-11-18 21.55.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534084/4ecbf73e-debe-aaf9-29b0-d605e1258210.png">
CSVファイルをフォルダにまとめ、そのパスをDatabase URLへ設定します。
今回は株価データのCSVを使用します。
<img width="1025" alt="スクリーンショット 2019-11-18 21.56.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534084/2c5353d9-f0c5-fffc-6fd7-4adfa1e0779c.png">
株価自体カンマ3桁区切りだったため、データが変ですが気にしません。
単なる前処理ミスです。
<br>
CSVファイルへSELECTクエリを実行できました。
<img width="1025" alt="スクリーンショット 2019-11-18 21.57.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534084/44dca950-31e4-bd34-774c-ed6d552fa55d.png">
フリー（個人利用のみ）のデータ分析ツール"KNIME"にCSVドライバを組み込んでみたので、その記事もアップします。
<h2>テーブル名の指定に注意</h2>
FROM でのテーブル名指定はファイル拡張子は不要です。
" FROM kabu.csv "だとエラーになります。

    SELECT *
    FROM kabu;
↑これでSELECTできました。
A-FRAME: 物理演算でボーリングっぽい動きを実現してみる４（ボールの平行移動への抵抗）

A-Frameをつかって物理演算ができるようにしてみます。
今回はボールの平行移動への抵抗を検証します。

例１）linearDamping=0.01
デフォルト値です。
![linear1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/121d941f-be80-9770-fa06-72fcc91d3b85.gif)[demo](https://k38.github.io/aframe/physics-system/ball_linear_001.html)
実際のボーリングだと、もっと滑らかに転がっていく気がします。
抵抗を変化させることで、実現できるのではないかと思います。

例２）linearDamping=1
抵抗を高めてみます。
![linear2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/3ee5d119-597f-cce7-01e0-b9ee3acaab51.gif)[demo](https://k38.github.io/aframe/physics-system/ball_linear_1.html)
ボールが飛んでいかず、静かに落下していきました。
レーンもすり抜けています。
よくわからないので、考えるのはやめて次にいきましょう。

例３）linearDamping=0.99
1はちょっと良くない感じだったので、0.01だけ下げてみましょう。
それでもデフォルトと比べたら大きな抵抗がある状態のはずです。
![linear3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/c8fd85c7-6ee9-f0b4-461d-b5a0b5abde74.gif)[demo](https://k38.github.io/aframe/physics-system/ball_linear_099.html)
いちおうボールは前に飛びましたが、レーンを少し転がって停止しました。
いかにも、抵抗を受けているような結果で、わかりやすいです。

例４）linearDamping=0.0001
デフォルト値の100分の1です。
![linear4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/d6004f6b-b80b-5db5-3ce6-4506fd276ce4.gif)[demo](https://k38.github.io/aframe/physics-system/ball_linear_00001.html)
気持ち、デフォルトよりはよく転がったように見えます。

例５）linearDamping=0
抵抗を無くしてみました。
![linear5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/aa2a98fa-68d1-f37a-62d2-d9a1ef603e52.gif)[demo](https://k38.github.io/aframe/physics-system/ball_linear_0.html)
あまり、0.0001のときとの差は感じません。
0.0001で十分小さい値なのでしょう。

### まとめ
ボーリングのボールの転がりには0.0001を採用してみます。
レーン側の摩擦係数を変更する事で、より調整ができるかもしれません。
Selenium × Java

# SeleniumをJavaで使ってみた

## Seleniumとは
※以下抜粋
Seleniumは、Webアプリケーションをテストするためのポータブルフレームワークです。
Seleniumは、テストスクリプト言語を学ぶ必要なく機能テストを作成するための再生ツールを提供します。


要はwebアプリケーションを自動で実行できたり、HTMLを解析(Webスクレイピング)するためのライブラリ。python、node.js、Java、PHPなど多言語でライブラリが用意されており、簡単に実装が可能。

## 目標
Java x Selenium導入、「Chrome起動→Google検索を開く」まで。


## アーキテクト
|  ||
|:-:|:-:|
|言語  |Java( ver.11 )|
|build   |Maven   |
|ブラウザ   |Google Chrome   |
|IDE   |IntelliJ   |

## 手順
前提
java x Mavenのアプリケーションの環境構築済みであること。

### 準備
1.　Seleniumのライブラリをpomに依存ライブラリを追加、読み込み。

```
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.12.0</version>
</dependency>
``` 

2.　Chromeで実行するため、Chromeのdriverをダウンロードする。これにより、Chromeによる実行が可能となる。別ブラウザでやりたい場合は、各ブラウザのdriverをダウンロードすればOK。

chromedriverのダウンロード
http://chromedriver.chromium.org/downloads

### サンプルコードの実行
「Chrome起動→Google検索を開く」

```
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class MainApplication {

    public static void main(String[] args){
        final String PATH = "※chromeDriverのpath";
        System.setProperty("webdriver.chrome.driver", PATH);
        WebDriver driver = new ChromeDriver();

        final String URL = "http://www.google.com";
        // URL遷移
        driver.get(URL);
    }
}
```


アプケーションを実行して、以下のようにGoogle検索が表示されれば成功:clap:
<img width="1276" alt="スクリーンショット 2019-11-24 10.48.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534340/f4ed8d79-e0e9-d0a0-e3ce-3d0c744186dd.png">
Greengrass(v1.9.4)上でNode.js(v8.10)のLambdaのデプロイができない問題の解決法

※追記
Greengrass Nodejs SDKのGitHubに書いてますね。。
https://github.com/aws/aws-greengrass-core-sdk-js

> Rename the file to nodejs8.10
> Make sure the file is not a symlink.

シンボリックリンクもだめらしいです。

---

GreengrassにNode.js(v8.10)のLambdaをデプロイすると、エラーになります。

```
Deployment xxxxx of type NewDeployment for group xxxxx failed error: worker with xxxxx failed to initialize
```

ログを確認すると、`nodejs8.10`というバイナリがないよと言っているようです。

```console:/greengrass/ggc/var/log/system/runtime.log
[ERROR]-runtime execution error: unable to start lambda container.	{"errorString": "failed to run container sandbox: container_linux.go:344: starting container process caused \"exec: \\\"nodejs8.10\\\": executable file not found in $PATH\""}
```

無理やり作ってやると、うまくいくようになりました。

```console
sudo ln -s /usr/bin/nodejs /usr/bin/nodejs8.10
```

Node.jsのセットアップの問題？

# 環境
OS: Ubuntu 18.04(VirtualBox on Mac)
Greengrass: 1.9.4
Node.js:10.17.0

Node.jsのインストールは公式サイト( https://github.com/nodesource/distributions/blob/master/README.md )に従いました。（2019/11/24時点で最新のv10.17.0がインストールされました）

```
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install -y nodejs
```

# Raspberry Piでは続きがあります

Raspberry Piでも同様の問題が起きますが、上記手順でデプロイは成功するようになります。ただし、Lambdaの実行時にエラーとなって実行されません。
こちらは解決法がわかりません。。。ヘルプ。。。

Raspberry Pi Zero W
OS:Raspbian Buster
Greengrass: 1.9.3
Node.js:10.16.3

Lambdaが呼び出されると、以下のエラー

```console:/greengrass/ggc/var/log/user/[リージョン]/[アカウントID]/[Lambda名].log
[ERROR]-standard_init_linux.go:207: exec user process caused "operation not permitted"
```
20年付き合ったデザイナーの肩書と別れて、エンジニアになった全裸中年男性の話

みなさまこんにちは。Qiita初投稿者です。
いずれ技術的な話も書いていってみたいですが、まずは初投稿記念に自己紹介とQiita記事を投稿しようと思った経緯など書いてみます。Qiita怖い。

簡潔にいうと、隙あれば自語りという内容です。Qiita怖い。
ですが、どなたかの何かしらの参考になればという思いもございます。Qiita怖い。

##はじめに
タイトル通りですが、私は20年ほどデザイナー（少し具体的には、紙媒体やDTPデザイナーからWebデザイナーへ転向したマン）という肩書で雇われた会社で業務に従事してまいりましたが、どうも『デザイン』という言葉の定義を履き違えていたようなのと、何も考えてなかった、及び将来見据えてエンジニアという道を選択しましたので、デザイナーだった自分へのはなむけみたいなとりとめのない話です。Qiita怖い。
20年以上使い込み慣れ親しんだイラレやフォトショとはここでオサラバです。（会社のしか使ったことないけど）

最近よく見る投稿で「ゼロからエンジニアになった話」とか「未経験から」とか「（全く違う職種）から」などありますが、自分に関しては全くそうではなく、絵を描くのが小さい頃は好きで多少なり絵に関わるデザイナーみたいな仕事を選んだにも関わらず、よくよく思い返してみると、高校くらいから初めて買ってもらったMac（←Macというのはデザイナーぽい）に付属してたハイパーカードでRPG作ったり、デザイン専門学校のグラフィック科に入ったのに、学科的に本当は専攻できないディレクター？ショックウェーブ？だっけ？でのゲーム作り講義になぜか入り込んでいたり（半年だかで事務局からあなたこの授業受講できませんって言われた）、Webデザイン始めてからは当然絵作りはもちろんhtml, cssでのコーディング（初期は懐かしのテーブルコーディング）はもちろん、javascript, 今は亡き？ActionScript, 商用のCMSで謎記述したりと割とそもそもお前プログラミングとか好きでは？的な生き方でありました。

さらにざっくり10年ほど前にiPhone 3Gの発売の衝撃から、『ゲーム作りたい！』マインドが爆発し、ググって出てきたObjective-Cのコードを丸々コピペしながら何も考えずに80本ほどApp Store/Google playにてリリースしてきました。（直近はもっぱらUnityでの制作ですが）もちろん会社仕事とは別です。

そんなですから多くの技術者様に石を投げられそうな（最近だとマサカリっていうんですかね？村田兆治？）クソコードを量産してきており、とてもこちらに投稿できるようなレベルの記事が書けるとも思えないのですが、自身の研鑽のためにもとにかくやってみようと思った次第です。
おそらく『未経験から〜』の方々の方がしっかり大学やらで一番大事な基礎の学問を学ばれてその下地により経験1年でも1ヶ月でも僕なんかよりよほど優れたコードをお書きになられていると存じます。Qiita怖い。

##本文
なんやかんやありまして。

##いがかでたしでしうょか？
導入だけで終わるという、いかにも表層だけ、見た目だけの中身のないデザイナー（という肩書の依頼者が気に入る絵を組む人）を続けてきた人間の書く初投稿といった感じではないでしょうか？Qiita怖い。
正直どんな仕事であれ、頭使ってしっかり考えなきゃダメ、という自戒でした。

まとめると、
・何も考えずともデザイナーという肩書きで適当に働ける。
・何も考えずとも10年で80本くらいはアプリをリリースできる。
・何も考えていないと仕事も、アプリもいくら数撃っても当たらない。
（まぐれ当たりはノーカウント。）

##おわりに
よろしければ20年の集大成とも言える、一番最近、私のリリースしたアプリをぜひ遊んでみてください。

Lunch Time Fish（日本語タイトル：シロクマランチFish）
https://softfunk.com/app/rd_ltf.html
プラットフォーム：iOS, Android

<img width="125" alt="sc_x_3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538223/5e11a713-aa7a-3139-273f-236ac887b346.png">


ありがたい事に今年開催されたGoogle主催のインディーゲームコンテスト、『Google IndieGames Festival 2019』にて、数多くの応募の中から栄えあるトップ10に選出していただきました！
デザイナー肩書との決別とともに、40代突入の大変素晴らしいスタートを切らせていただきました。
...が、現状おそろしくダウンロードされてませんのでまだまだここから、今後はしっかり遊ぶ人がいかに楽しめるかを考えて、アップデートでコンテンツ拡充を頑張りたいと思っています。

最後までお読みいただき、ありがとうございました。
※本記事に関しては完全に単なる自分語りですので、何か思うところあれば本記事へのコメントはせず、ご自身で記事を投稿いただけますようお願いいたします。非常に怯えながら書いております。Qiita怖い。
ちなみにこの記事も特に何も考えず書いています。ただ書いてみたいと思って。・・・こういうとこやぞ！
PythonとLOUDSによるTRIE木の実装 

# 概要
PythonでTRIE木を実装した
TRIE木を作成する上でデータ構造にLOUDSを使用している

# TRIE木
 - TRIE木とは、文字列の集合を順序付きの木構造で表したもの
 - ノードとエッジから構成され、各ノードの位置とキー（検索文字列）が対応している
 - ルートノードには空文字列が対応している
 
![TRIE木](https://upload.wikimedia.org/wikipedia/commons/thumb/b/be/Trie_example.svg/256px-Trie_example.svg.png)

### TRIE木の特徴
 - 高速な辞書検索：木の大きさに関わらず定数時間で検索することができる
 - メモリを節約：ノードにキーが格納されないため、複数のキーでノードを共有することができ、メモリを節約することができる
 - 効率的なプレフィックス検索：複数のキーでノードを共有しているため、親ノード（プレフィックス）に紐づく子ノードの検索も効率的に行うことができる

TRIE木はその特徴から、かな漢字変換や自動補完などに使用されている

# LOUDS
 - LOUDS（level order unary degree sequence）とは、順序木表現の一つ、極めて小さいサイズで木構造を表現することができる
 - 具体的にはノード数がN個の場合、その木構造は長さNのラベル配列と2N+1のbit配列で表現される
 - ただし、作成したTreeから効率よく検索するために、補助的なデータ（完備辞書）が別途必要になる

# 完備辞書
 - 完備辞書とは、簡潔データ構造において最も基本的なデータ構造
 - 完備辞書を補助データとして用いることによって、定数時間での検索が可能になる
 - 具体的にはrankとselectという操作を用いて、TRIE木の検索を行う
    - rank():ビット列の先頭から位置 k までに、1 のビットがいくつあるか
    - select():ビット列の先頭から見て、n 個目の 1 のビットの次の位置はどこか
<br>[簡潔データ構造については、こちらのページで詳しく解説されている](https://takeda25.hatenablog.jp/entry/20140201/1391250137)

# 実装
Pythonで以下を実装した（[GitHub](https://github.com/kawasaki-kento/LOUDS)）

 - trie.py：TRIE木
 - constructor.py：ビット配列
 - words.py：辞書データの作成・読み込み
 - measure.py：メモリと検索時間の測定
 - search_word.py：単語検索
 - test.py：検索時間の測定

# 辞書データの作成
以下のように実行すると、TRIE木のノード番号と単語がカンマ区切りで書かれている辞書データが作成される
データはnltkのwordnetコーパスを使用した
後にテストデータをこの辞書データから作成する

~~~
from words import CreateWords
CreateWords("./data/origin/wordnet_words.csv")
~~~

# 単語検索
~~~
python search_word.py 辞書データPATH
~~~
上記のファイルを実行すると、単一の単語検索をすることができる
任意の単語を入力すると、以下のように、検索から得られたノード番号、単語の定義、プレフィックスが出力される
![search_result.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363376/953e28e1-94b3-de87-628e-5ae55a986737.png)

# 検索時間の測定

### テストデータの作成
以下を実行すると、任意の単語数のテストデータを辞書データから作成できる

~~~
python words.py 辞書データPATH サンプル数1,サンプル数2,サンプル数3,…
~~~
複数のテストデータを作成したい場合は、データのサンプルサイズをカンマ区切りで指定
"Test data is created."と出力されればok。テストデータが./data/testに作成される

### 測定
以下のように、実行するとテストデータで任意の回数、テストを実行することができる

~~~
python test.py 辞書データPATH テストデータPATH テスト回数
~~~

"Test is done."と出力されればok。出力結果が./resultsに作成される

測定では、完全一致検索時間とプレフィックス検索時間を計測している

 - 完全一致検索：trieクラスのsearch関数の実行時間の合計
 - プレフィックス検索：trieクラスのget_blow_nodes関数の実行時間の合計

内部的には入力された単語に対して、trieクラスのsearch関数が実行され、TRIE木のノード番号を出力する
出力されたノード番号は辞書データのノード番号と照合され、一致していれば検索件数を+1し、正確に検索ができているかどうか確認している。プレフィックス検索も同様

### 出力結果
![test_result_detail.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363376/3fa2c02e-37e7-79c1-6f8c-e056cd5dd67c.png)

 - 完全一致検索：単語の検索にかかった合計時間
 - 検索結果：辞書データのノード番号と一致した件数
 - プレフィックス検索：検索単語に紐づくプレフィックスをすべて検索するまでにかかった合計時間
 - プレフィックス検索（１件当たり）：検索単語に紐づくプレフィックス１件当たりの検索時間
 - メモリ使用量
    - bit_array：bit配列のメモリ使用量
    - labels：ラベル配列のメモリ使用量
    - rank：rankのメモリ使用量
    - select：selectのメモリ使用量

# 参考文献
 - [簡潔データ構造 LOUDS の解説（全12回、練習問題付き）](https://takeda25.hatenablog.jp/entry/20120421/1335019644)
 - [完備辞書（簡潔ビットベクトル）の解説](https://takeda25.hatenablog.jp/entry/20140201/1391250137)
 - [高速な辞書実装に使えるトライ木をD言語とPythonで書いてみた](https://qiita.com/IshitaTakeshi/items/04e6fcf7c9d52082d4de)
cakephp ワンタイムURL作成をメール送信

## ワンタイムURL
> 一度あるいは、限られた時間あるいは回数しかGETリクエストを受け付けないメカニズムである。 目的は、アクセス制限されたリソースに対して未承認アクセスすることをより困難にすることにある。

何かのログインでパスワードを忘れた時にメールアドレスを入力してそのアドレス宛に再設定などを行うURLが送られてくるやつです。

## 基本的な流れ
①　メールアドレスを入力してそのアドレス宛にメール送信
https://book.cakephp.org/2/ja/core-utility-libraries/email.html

```
App::uses('CakeEmail', 'Network/Email');
$content = array('url' => $url);
$email = new CakeEmail();
$email->from('example@test.com')
     ->to($post_email)
     ->template('text_email')//テンプレートファイル名指定
     ->viewVars($content)//text_email.ctp内の$url変数はコントローラ内のviewVarsメソッドで渡した値を利用
     ->subject('パスワード再設定')
     ->send();//メール送信
```

②　送信と同時にDBにランダムなトークンを保存する

```
$token = substr(str_shuffle('1234567890abcdefghijklmnopqrstuvwxyz'), 0, 16);//ランダムな文字列
$save_data = array('User' => array('token' => $ctoken));//保存するワンタイムトークン
$this->User->save($save_data);//配列で値を渡す
```

③　②と同時に有効期限を設定する

```
$limit = time() + 1800;//有効期限30分
```
メールを送信した時間から1800秒（30分）足した時間

④　受け取ったURLのチェックを行う

```
$key = $this->request->query['key'];//パラメータからcheck_flagを取得
$pass = $this->request->data['User']['password'];//新しいパスワード
$save_data = array('User' => array('password' => $pass, 'token' => null));//保存するデータ
if (intval($expire) < time() || $key !== $db_token'User']['check_flag']) {
	$this->Flash->error('このURLは無効です');
} else {
	if ($this->request->is('post')) {
	     $this->User->save($save_data);
	     $this->Flash->success('パスワードを更新しました');
	}
}
```

DBに保存されているトークンとURLのキーで受け取った値が一緒であるかチェックする
一致しない場合は無効なURLとなる
また、②で設定した時間が現在時間より大きい場合も無効なURLとなる。
転移学習でCM検出器を作ったが品質が微妙だった

# はじめに

この記事で示されるコードは動作はするが、品質は微妙なので実用レベルではない。

# 動機と先行事例の調査

さんざん撮り溜めたテレビの録画から自動的にCMがカットできればうれしいなあとずっと思っていた。具体的にはカリフォルニア工科大学に勤める才能溢れる若者がなぜかその能力を斜め上の方向に傾注するシチュエーション・コメディや、現代に甦ったシャーロック・ホームズがニューヨークでチャーリーズ・エンジェルに出てそうなアジア系のドクター・ワトソンと難事件に挑むドラマなど。少し前まではメンバーの一人が不祥事を起こしてしまったアイドルグループが山の中や孤島でいろいろ自給自足生活に挑戦するバラエティなど。毎回編集してCMを取り除くのは億劫なので、そういうものをいい感じにアレできるようなものがあるといい感じなんじゃないかな、と。

調べたかぎりでは先行事例は3つ。

- 事例(1): https://vasanthkalingeri.github.io/CommercialDetection/
    - シーンの区切りは音声の無音区間を認識。実際にはダイナミックレンジの偏差も取っている
    - 予めCM音声のフィンガープリントを取っておいて、区切ったシーンごとに該当するかを判断
- 事例(2): https://github.com/Breakthrough/PySceneDetect
    - 画像の変化の幅を利用してシーンの区切りを検出
    - シーンそのものの種別の認識はやっていない
- 事例(3): https://www.pyimagesearch.com/2019/07/15/video-classification-with-keras-and-deep-learning/
    - 転移学習、ファインチューニングを使用して、動画のセマンティックスを認識

事例(1)についてはたぶんCMの認識精度は高いんだろうけど、全てのCMをパターンに登録しておかないといけないので結局それって全エピソード手動で切り分けることとほとんど大差ないねって感じで、手間かかるだろうなという感じ。事例(2)についてはデモ動かした感じでは認識が鋭敏すぎてちょっとしたシーンの切り替え(カメラアングルの変化)とかでもシーンチェンジと認識してしまっているので、ちょっとしんどいな、という感じ。

事例(3)がかなり自分の中では刺さって、これでCMの認識とかいけるんじゃなかろうか！ということで応用してみた。

# 実装

こちらを参照。

https://github.com/mkiuchi/keras-cmdetection

Kerasなので極端に言えばGPUなくても動く。でも現実的なパフォーマンスを出すには 16GB MEM, 4GB以上のメモリを搭載したGeForceがいるとおもう。私はディープ・ラーニングの勉強も今後したかったので￥15,000出して[玄人志向のGeForce GTX 1650](https://www.kuroutoshikou.com/product/graphics_bord/nvidia/gf-gtx1650-e4gb_oc_df/)を購入した。

教師データにはドラマの録画そのものを使用した。2エピソードだけ手動で厳密に本編とCMを切り分け、それを元に動画を読み込んでフレームを切り出した時のラベル(0=本編, 1=CM)をつけて教師データにしている。教師データの数が結構多いので、Data Augmentationは行わなかった。1エピソードだけでもメモリ9GB程度を使うみたいだ。

トレーニングの結果としては、数字だけ見るとまじでって感じ。そう何回もepochを回していないうちにvalidation accuracyも90%とかになって、これかなりいけるんじゃないのって感じ。

で、実際Estimateで他エピソードのシーンカット、種別認識を行った結果が [bbt-01-08-timesheet-queue30.txt](https://github.com/mkiuchi/keras-cmdetection/blob/master/bbt-01-08-timesheet-queue30.txt) 。トレーニングの時点でCM側のRecall rateが低めですねとは出ていたんだけど、FNが結構キツめに出てますね、と。アイデア元の記事でも言及されていたんだけど、予測がチャタるというか、ちらつく現象が出ている。ただチャタる部分は傾向性があるのでヒューリスティックなフィルタリングで除去できそう。

# 実装してみてどうだったか

- ざっくりとしたレベルでは本編とCMは切り分けることができる。ただ本編シーンの前後にCMが少しまざったりしてきっちり切り分けるのは無理っぽいなあ、と思った。元記事の記述だとRNNやLSTMを使うとこのへんはもっと改善できるらしい。う〜ん
- 教師データ足りないんじゃないのというのも思いついたけど、もともとの動機が怠惰にCMと本編を切り分けたいということだったので、教師データ増やすために頑張るというのもなんか本末転倒だよなあ、と
- まだ私の知識が足りていないので、何かが悪い時に改善策を打つことができない。単にその辺に転がってるコードを実行してみて良かった、悪かった、的な感じを繰り返しているとよくなさそう。やっぱりちゃんと勉強しないとなあ

こんな感じ。ディープラーニングって動かすだけならまあまあできるけど、うまく動かない時ちゃんと勉強していないと大変ですね
PythonによるTRIE実装　～ダブル配列（Tailあり）～

# 概要
　Python上でダブル配列を実装し、そのメモリ使用量、検索時間を測定します。
　性能評価をするにあたって、いろいろと検索してみたのですが、今一つ納得のいく実装が見当たらなかったので、自作することにしました。
　なお、本来なら、ダブル配列の作成過程の効率も考えるべきですが、今回はそこは重視しません。あくまでも、出来上がったダブル配列の性能を評価することを目的としています。（したがって、動的な追加についても対象外です。）
　また、ファイルでの運用も考慮していません。メモリ上で作成し、そこで性能測定を行います。

#TRIE構造
　文字列データを管理する方法のひとつで、効果的な速度で検索を実現することができます。
　理論的にはシンプルな構造なのですが、実装方法によってはさほど効果が出ない場合もあります。  

- [トライ木 (Wikipedia)](https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%82%A4%E6%9C%A8)

　「ダブル配列」はそのTRIE構造の実装方法の一つで高速な検索が実現できます。

#ダブル配列
　ダブル配列については、各所にわかりやすい説明が載っているのでそれを参照してください。

- [情報系修士にもわかるダブル配列](https://takeda25.hatenablog.jp/entry/20120219/1329634865)
- [ダブル配列の実装方法 (slideshare)](https://www.slideshare.net/higashiyama/ss-8738479)
- [ダブル配列の豆知識 (slideshare)](https://www.slideshare.net/s5yata/dsirnlp-04s5yata)
- [文字列アルゴリズムの学びかた](https://developer.hatenastaff.com/entry/2016/12/22/210006#6-%E3%83%88%E3%83%A9%E3%82%A4%E6%9C%A8-Trie-%E3%81%AB%E3%82%88%E3%82%8B%E8%A4%87%E6%95%B0%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%83%9E%E3%83%83%E3%83%81%E3%83%B3%E3%82%B0)
- [人生で何度目かのダブル配列TRIEを書いた (Qiita)](https://qiita.com/ikawaha/items/edb4e18960ae6e4babc3)
- [ダブル配列法によるトライ検索の実現法 （青江順一教授による論文）](https://ipsj.ixsq.nii.ac.jp/ej/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=49490&item_no=1&page_id=13&block_id=8)

# Pythonでの実装
　これまで、他のプログラミング言語（C、C++、Javaなど）で「ダブル配列」を実装したことはありましたが、Pythonでの実装は初めてです。Python特有の効率化手法があるかと思いますが、基本的なアルゴリズムに従って実装することにします。
　基本的なデータ構造（ListやArrayなど）は言語に備わっているものを使いますが、アルゴリズム実装はフルスクラッチで作成しました。

　1ノードにおけるリンクの全体像が見えないと、配列のどこに格納可能かを確認できないので、まず、簡易的な（速度を考えない）TRIE実装を行い、リンクの全体が見渡せるようにして、それをダブル配列に格納するようにします。

　今回のダブル配列の実装では、Tailを考慮したつくりになっています。
　すべての文字列をTRIE構造で表現することは可能です。そうすることでアルゴリズム的にはシンプルになります。しかし、終端に近い文字列では分岐がなく、ひとつながりのノードとリンクが出来上がってしまい、その結果として、メモリや時間のコストが大きくなります。そこで分岐がない終端文字列をTailとして管理することでこれを改善します。
　すなわち、性能評価においてより良い性能の実装という観点でTailありのダブル配列を実装しました。

- [プログラムソース(Github)](https://github.com/michihosokawa/Trie_By_Daouble-array)


#性能評価
- 性能測定の方法
    - 完全一致検索を測定する
100回試行してその平均値を結果とする

- 実行環境
    - Windows 10 Pro
    - Intel(R) Core(TM)i7-75600U CPU @ 2.40GHz
    - RAM 16GB
    - Python 3.7.1

- 検索対象単語
    - wordnetから取得した英単語 87,379件

- 実行時間＆使用メモリ
    - 検索単語数
        - 50,000件
    - 結果：実行時間
        - 0.281秒
    - 結果：使用メモリ
        - 7.5MB

## 今後の改良

- 前方一致検索の追加
    - 今回は、文字列と一致するレコードを検索するだけですが、他への応用を考えた場合には前方一致検索が必要な局面が出てきます。
- 性能アップ
    - 「とりあえず作ってみた」レベルの実装なので、Python特有の効率化の余地があると思っています。さらなる性能アップを目指したいと思います。
仮想環境にECCUBE4導入でハマった事

## CentOS7/PHP7.2/MySQL5.7/apache2.4
[MacにVagrantでCentOS7環境を作成](https://qiita.com/sudachi808/items/3614fd90f9025973de4b)
[Vagrant+VirtualBoxでLAMP環境構築をする](https://leben.mobi/blog/vagrant_virtualbox_php7/php/)

### 管理画面が NOT FOUND 404
http://(インストールしたディレクトリ)/index.php/(管理画面ディレクトリ)/
アクセスはできたので、 `mod_rewrite` が有効になっていません。
※ フロント画面もトップページ以外は表示不可
<?php phpinfo(); ?> では `mod_rewrite` が確認できた。

```
<Directory "/var/www/html">
    # AllowOverride None
    AllowOverride All
</Directory>
```
ドキュメントルートの `AllowOverride` 設定が `None` になってたので `All` に変更

### vagrant共有フォルダ設定でファイルをリアルタイム同期
Vagrantfile 設定

```
  config.vm.synced_folder "/Users/kudohte/centos7", "/vagrant",type:"virtualbox",
   owner: "apache", group: "apache"
```

- [ApacheのドキュメントルートをVagrantの共有フォルダにすると403 Forbiddenになる](https://blog.fire-sign.info/552/)
- [Vagrantの共有フォルダ設定時にエラーが出た時の対処](https://qiita.com/oka91/items/4b8517d390740faa1e74)
- [【ECCUBE】intl拡張モジュールが有効になっていません](https://qiita.com/machio77777/items/be29ca83992976afdcec)
pythonのクラス、インスタンス

##クラスとインスタンス
###クラスとインスタンスの関係
クラスはモノを生成するための設計図、インスタンスはそのモノのこと
###インスタンスを生成するステップ
クラスを用意⇨クラスからインスタンス生成⇨インスタンスに情報追加
###クラスの定義
**class クラス名:**
クラスの中身は『class クラス名:』の後の行でインデント
処理を追加する必要がない場合は**pass**と書く
###インスタンスの作成
**クラス名()**でクラスを呼び出し、クラスを用いて新たなインスタンスを生成できる
**変数名 = クラス名()**とすることで、生成したインスタンスを変数に代入することができる

###インスタンスに情報を与える
下のコードのようにfruit.name = "バナナ"とする事でfruit1にnameがバナナとであるという情報を追加
このときのnameを**インスタンス変数**という
**インスタンス.インスタンス変数名**とすることで、そのインスタンス変数の値を用いることができる

```python.py
class Fruits:
  pass

fruit1 = Fruits()
fruit1.name = "バナナ"
```

###クラスの中に処理を追加
クラスの中に関数を定義することができる（この関数を**メソッド**という）
メソッドの定義の方法は通常の関数と同じだが第一引数にselfを追加する必要がある
クラスの中で定義したメソッドは、インスタンスに対して使うように呼び出す。具体的には、**インスタンス.メソッド名()**とすることで、そのメソッドを呼び出すことができる。
インスタンスメソッドの第1引数に指定した「self」には、そのメソッドを呼び出したインスタンス自身が代入されている
インスタンスは情報として「インスタンス変数」を、処理として「インスタンスメソッド」を持っている
###initメソッド
initメソッドは他のインスタンスと同様に定義できインスタンスが生成した直後に自動で呼び出される　
このメソッドを用いるとインスタンスを生成すると同時にインスタンス変数に値を代入することができる
引数を渡すこともできインスタンスごとに値を変えれる

###クラスをそのまま読み込む
**from モジュール名 import クラス名**とすることで、そのモジュール内の指定したクラスを直接読み込むことができる
SpringBoot×OpenAPI入門　〜Generation gapパターンで作るOpenAPI〜

### 背景

Javaのコミュニティイベント「JJUG CCC 2019 Fall」に参加。
そこで聞いた「Swagger ではない OpenAPI Specification 3.0 による API サーバー開発」の登壇内容に触発されて超簡単なOpenAPIを作った話。（浅いです）

### 今回のゴール

SpringBootを使ってOpenAPIを書く

### OpenAPIを使った開発フロー(ざっくり）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/fe324a04-eeea-b7f5-44fe-7157e2b4c0a9.png)

ルール：**Generation gapパターン**　→　自動生成したクラスファイルは編集しない。

#### 1. API定義ファイルを用意

OAS（OpenAPISpecification）にあるサンプルを使用

https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore.yaml

#### 2. 定義よりコード自動生成

Gradleのプラグイン【openapi-generator-gradle-plugin】を使用。
APIの定義ファイルよりコードを自動生成してくれるGradleプラグイン。

```gradle:build.gradle
plugins {
	id "org.openapi.generator" version "4.2.1"
}
```

##### ポイント１：コンパイル時の設定

自動生成したクラスファイルをコンパイル時に含めるように設定

```gradle:build.gradle
compileJava.dependsOn tasks.openApiGenerate
sourceSets.main.java.srcDir "${openApiGenerate.outputDir.get()}/src/main/java"
sourceSets.main.resources.srcDir 
```

##### ポイント２：OpenapiGeneratorの設定

openapi-generator-gradle-pluginの実行例をほぼほぼコピーでOK。
ただ、インターフェイスを作成するようにコンフィグファイルを操作。

```gradle:build.gradle
//https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-gradle-plugin

openApiGenerate {
    generatorName = "spring"
    //コンフィグ設定
    configFile = "$rootDir/specs/config.json".toString()
    //サンプルAPI指定
    inputSpec = "$rootDir/specs/petstore-v3.0.yaml".toString()
    outputDir = "$buildDir/generated".toString()
    apiPackage = "org.openapi.example.api"
    invokerPackage = "org.openapi.example.invoker"
    modelPackage = "org.openapi.example.model"
    configOptions = [
        dateLibrary: "java8"
    ]
    systemProperties = [
        modelDocs: 'false'
    ]
}
```

```json:config.json
{
  "interfaceOnly": true
}
```

クラスの自動生成はGradleのタスク【openApiGenerate】でOK。

![スクリーンショット 2019-11-24 9.40.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/d71a9a32-5c82-41ed-daf4-c4973d472fbf.png)

タスク実行すると、以下のJavaファイルが自動生成される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/4df00c72-1789-ede6-f1e5-86a76cd00a69.png)

#### 3. API実装

自動生成されたインターフェイスからimplementして、コントローラーを生成

```java:PetsApiController.java
@RestController
public class PetsApiController implements PetsApi{
	@Override
	public ResponseEntity<List<Pet>> listPets(@Valid Integer limit) {
		System.out.println("Here list pet");
		return new ResponseEntity<>(HttpStatus.OK);
	}
}
```

完成！！

### 完成したコード

https://github.com/harutotanabe09/SpringBootOpenAPIBegin

### おまけ:OpenAPIのドキュメントツールを使ってみた

OpenAPIのドキュメントツール（redoc）を使って、ドキュメントを自動生成。
※　前提：Dockerが入っていること

```sh
docker run -it --rm -p 80:80 \
  -v $(pwd)/specs/petstore-v3.0.yaml:/usr/share/nginx/html/swagger.yaml \
  redocly/redoc
```

http://localhost/

出力イメージ：定義ファイルを元にAPIのパラメータや戻り値を見やすい画面で出力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/6e9308da-5cf0-0555-df20-00c594d4c502.png)

### 参考資料

Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
https://www.slideshare.net/techblogyahoo/swagger-openapi-specification-30-api
コマンド1つで、erbファイルをhamlファイルに変えちゃうよ  ❏Rails❏ ❏haml❏

すべてのerbファイルをhamlファイルに変換する便利なコマンドを紹介します。

#gemを追加

```ruby
gem 'haml-rails'
gem 'erb2haml'
```

を追加

bundle installもお忘れなく。

#魔法のコマンド

```
rails haml:replace_erbs
```

これでいけると思います。
僕がはじめて成功した時は小躍りしました。

<br>
ではまた！
plunkerでvalidation

#概要

plunkerでvalidationやってみた。

#参考にしたページ

https://qiita.com/ezawa800/items/6628890bb343cd6bbc14

#成果物

https://embed.plnkr.co/wL1X21AssXiYfoar8RtF/

https://embed.plnkr.co/0iOflGrP2Ymob8zzuSjt/


以上。
Span を DllImport に渡す

```c++
// c の定義
SAMPLE_EXPORT void SAMPLE_NumberSequence(unsigned char *bytes, int length);
```

```cs
[DllImport(DllName, EntryPoint = "SAMPLE_NumberSequence")]
public static extern void SAMPLE_NumberSequence_UseRef(ref byte bytes, int length);
```

と書いておいて

```cs
static void StackSample()
{
    Span<byte> span = stackalloc byte[10];
    SampleImport.SAMPLE_NumberSequence_UseRef(ref span[0], span.Length);
    Console.WriteLine(ToString(span));
}
```

`ref span[0]` で先頭要素へのリファレンスを渡すことでできた。

## 実験コード

https://github.com/ousttrue/SpanSample
見様見真似でlinux の仮想環境をVisual BOXで作ったド初心者メモ


ついに！！
休日に一緒に勉強を教えてくれる友達ができた！！！＼(^o^)／

3人でなんかアプリ作りながら勉強しようぜ！

って話してて
その友達にまず言われたのが

「とりあえずLinuxの環境作りましょうか！」

！？

Windowsしか使ったことないし、
そもそもLinuxって何者！？
ってレベルで、

名前は聞いたことある、別のOSなんでしょ？
Windowsにお別れを告げないといけないってこと？
待ってくれ心の準備が、、


なんて思ってたら全然そんなことなくて
仮想の環境を作って
そこにリモートデスクトップみたいな感じで繋ぐだけらしい...!

安心して
教えてもらうことに。

横で教えてもらいながらなので、すごい速度で進んでいく。
すごい。できる人と勉強するのってすごい！


ただ教えてもらいながらすると、進行速度が上がる分、
「今自分が何してるのか」
「なんでそんなことするのか」
整理できないまま、環境だけができていく。。

このままじゃあ、自分が次誰かに教える番は一生こない。。
もっかいおんなじことができない。

ってことで忘れないうちにここにメモすることにしました！


時間がないので取り合ず殴り書き＆スクショペタペタです！
自分のためのメモなので、、多少の分かりにくさはご了承ください...！


＜使用するツール(ツールであってる？笑)＞
Virtual BOX
https://www.oracle.com/virtualization/technologies/vm/downloads/virtualbox-downloads.html

ubuntu
https://jp.ubuntu.com/download


＜ツールについて簡単に解説＞

●Virtualbox（バーチャルボックス）は、使用しているPCに仮想環境を構築して、他のOSをインストールすることができる仮想化ソフトです。

つまり、Windows使ってる人もMac使ってる人も、これを使えば、パソコンの中でパラレルワールドみたいなところを作って別のOSを使うことができるんです！


●ubuntuはLinuxの数あるディストリビューションのひとつ
ディストリビューションとはLinuxの種類のこと！
LinuxのUserになるぜ！と言っても
いろんな特徴を持ったやつがいて選ばないといけないんですね～

ポケモントレーナーになるぜ！っていっても
アチャモ、ミズゴロー、キモリからまずは選ばないといけないみたいな感じですかね

その中でもubuntuはとにかく初心者に使いやすいディストリビューション！
最初のジム戦は岩タイプだからキモリが使いやすいみたいな感じですかね？笑

分かりにくいですね、すみません。
よくわからない方は侍さん見てください。めちゃくちゃ分かりやすいです。
→ubuntuとは？
https://eng-entrance.com/what-is-ubuntu


＜全体の作業の流れ＞

①Virtualboxをダウンロード、インストール(リンクは上に！)
②ubuntuをダウンロード(リンクは上に！)
③Virtualboxの設定→ストレージ→空→右の青いDVDアイコン→ダウンロードしたubuntuのファイルを選択！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321122/3919b9a2-4498-67e2-0c52-259acac066d7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321122/b7eb2724-adc9-b12b-b4e9-03f776e2ebcc.png)
④起動！

これでLinuxの仮想環境ができます！

仮想の環境でubuntuの設定がたくさんあるんですが、
スクショとってなかったので説明が難しい。笑

また時間があったら追記します！


番外編
lenovoのUserさんの場合、
これだけだと④で起動できずエラーになってしまいます。。
→解決方法はこちら！
https://support.lenovo.com/jp/ja/solutions/ht500006
plunkerでfont-awesome

#概要

plunkerでfont-awesomeやってみた。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6627ce2d-0597-cc50-9be0-c3199e93b3b0.png)


#成果物

https://embed.plnkr.co/Kj74uNaQtS4rW55d6mGW/


以上。
初心者によるプログラミング学習ログ 167日目

# 100日チャレンジの167日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

167日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>167日目<br><br>webサイトコーディング課題<br>休みだったけど、ほかにいろいろやることあったので、コーディング自体は1時間ぐらいです。<br><br>さぼりぎみなので、今日は集中してやります<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1198363921620406272?ref_src=twsrc%5Etfw">November 23, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Google Cloud Run がGAになった記念に株の自動売買を目指す（多分）

#目指すゴール
目指すのは、日経225オプション取引を自動化すること。
普段は、予定とか考えないが、今回は以下のような予定で、進めてみたい。
制限と選択と集中が良いとどこかの記事で読んだので、１記事あたりにかける時間は、１時間までと決め、内容に不足があっても次の機会に作業する。30分に1度は休憩することも忘れずに。
期限は2020/5/31としてみる。（遅っそ）
コンテナは、全くわからないので、以下の作業を進めていく中で理解できたらいいなくらいで進めてみる。

##1.技術的に使うものを決める。（自分に使えそうなものだけ）
　-　[Google Cloud Run(フルマネージドのサーバーレス)](https://cloud.google.com/blog/ja/products/serverless/knative-based-cloud-run-services-are-ga) 
　-　Python3 (Flask)　 Flaskは、[Quickstart: Build and Deploy](https://cloud.google.com/run/docs/quickstarts/build-and-deploy)で、Flask使ってるから
　-　Selenium 
　-　ヘッドレスchrome
　-　上記技術で、証券会社のWEBページへログインして、必要なデータをスクレイピングで取得して、売買注文を自動で投入する。
##2.Google Cloud Runの[Quickstart: Build and Deploy](https://cloud.google.com/run/docs/quickstarts/build-and-deploy)をとにかくやってみる
##3.コンテナに、ヘッドレスchromeやSeleniumを入れる方法を調べる
　ここは時間がかかりそう。
　参考にする予定[Docker上でSeleniumとHeadless ChromeとPython3を動かす](https://qiita.com/sikkim/items/447b72e6ec45849058cd)
##4.ローカルで、コンテナ・アプリ（軽めの実装）を動かせるようになる
　[windows 10 home で docker を導入するメモ](https://qiita.com/idani/items/fb7681d79eeb48c05144)を参考に、とりあえず、dockerが動くようになった。（2019/11/28追記）
　参考にする予定[Google Cloud Run を使うまで](https://qiita.com/massie_g/items/5a9ce514eaa7c460b5e3)
##5.ローカルで作ったアプリをCloud Runへデプロイしてみる
##6.アプリの自動売買ロジックは、今のところ良い作戦がないので、BigQueryで分析しながら適当に考えておく
##7.日経225オプションの自動売買アプリを完成させる



###Why Cloud Run
AppEngineでできるものならやりたかった。しかし、証券会社のWEBサイトのデータはJavascriptで取得するものがほとんどになってきてるので、Javascriptに対応するするには、ヘッドレスchromeとSeleniumがデファクトかな？と思った。
自分にとって、とっつきやすいのが、Cloud Runだったので、取り組んでみることとしました。

####Who am I ?
投資：
とあるファンドに投資していて、月利4%程度の利益があります。
でも、自分で稼げないと将来困りそう。だから、自動売買システムを作って稼ぎたい！
この一念で、やってます。

本業：
私は、事業会社のIT部門で働くしがないサラリーマンです。
本業では、プログラムを書かないです。未だにオンプレがほとんどです。
COBOLもあります。
クラウドは使ってる部分もあるけど、場所を移動しただけのIaaSがメイン。


（編集日時：2019/11/24 07:30　-　2019/11/24 08:00 最初から7.まで）
（編集日時：2019/11/24 08:15　-　2019/11/24 08:45 最初からWho am Iまで更新）
julia のmethod dispatch の動きの確認

実行環境 julia1.2, MacOS10.15

juliaのmethod dispatchで、どの型とも一致しなかった場合の処理を、型Anyで書けばうまくいくのかどうか確認した。(マニュアル読めばわかるだろうけど、さがすのが面倒)
とりあえず、3つ型を定義する。

```julia
struct A
 x::String
end

struct B
 y::Number
end

struct C
 z::Symbol
end

```

methodの定義をこうする。
引数がAでもBでもないとき、Anyの定義だけが使われれば吉。
classの継承だと、親のmethodが呼ばれたりするので、それに似た振る舞いだと、AやBのときもAnyの定義が使われてしまわないことを確認したい。

```julia
f(x::A) = "with A"
f(x::Any) = "with others"
f(x::B) = "with B"
```
Bの定義を最後にもってきたのは、定義の順番が関係しないか気になったので。

最後に、期待値を@testで書くとこんな感じ。
わたしの常識では、こうなっているはず。

```julia
using Test

@test f(A("i am A")) == "with A"
@test f(C(:others)) == "with others"
@test f(124) == "with others"
@test f(B(123)) == "with B"
```

実行すると、こうなったのでめでたし。

```julia
julia> include("methods.jl")
Test Passed
```

マニュアルさがすより面倒だったかもしれないが、動かしたほうが記憶できる。
case文で条件分岐 ❏Ruby❏

#使い方
対象の値が条件に合うかどうか調べます。
合っていたら処理を実行します。

```ruby
case 対象
when 条件1
  条件1
when 条件2
  処理2
...
else
  処理3
end
```

#例1

```ruby
fruits = banana

case fruits
when "apple"
  puts "It's red!"
when "banana"
  puts "It's yellow"
when "orange"
  puts "It's orange"
else
  puts "I don't know"
end
```

結果
`It's yellow`

#例2

```ruby
score = 65

case score
when 90..100
  puts "A+"
when 80..89
  puts "A"
when 70..79
  puts "B"
when 60..69
  puts "C"
else
  puts "F"
end
```

結果
`C`

#if文との使い分け
条件式といえば if文 が真っ先に思いつきます。
上の例も if文 で書き換えることも可能です。

では、どう使い分けるか。。。

**基本 → if**

**条件式が複数あり、対象がすべて同じ場合 → case**

<br>
僕はこうしてます。
caseを使ったほうが可読性は上がります。

より良い意見あったらコメントお願いします。


<br>
ではまた！
記憶代用 ¥circ

実行環境 julia1.2, MacOS10.15

juliaのmanualの
15.15 Func􀦧on compositon and piping
で、関数のcompositionについてこう書かれている。
```
(f g)(args...) is the same as f(g(args...)).
```
このfとgの間になにも見えない。すこし空白の幅が大きいか。
例として書かれているコードをタイプしてみると

```julia
julia> (sqrt +)(3, 6)
3.0
```
とはならず、エラーになる。

先の引用の次の行にこうあるのに気づいたのは何日かしたあとだった。
```
... using \circ<tab>.
```
そうすると

```julia
julia> (sqrt ∘ +)(3,6)
3.0
```
この○がpdfでは見えなかった。

15.15のタイトルや、本文の'composition'をpdfからコピペすると、't'が豆腐になるのはなにか不思議なコードがはいっているのだろう。

ちなみにやりたかったのは、関数fとgの積の関数 (f x g)を作りたかったので、これははずれ。
Julia でlisp

実行環境 julia1.2, MacOS10.15

以前、juliaでlispが使えたのだけど、どうやってlispを動かすのか忘れてしまった。(以前というのはたぶん0.6か1.0か??)

あれこれやってみてわかったけれど、動いた。
マニュアルには書かれていないような気がするので、自己責任で・・・

```julia
% julia --lisp
;  _
; |_ _ _ |_ _ |  . _ _
; | (-||||_(_)|__|_)|_)
;-------------------|----------------------------------------------------------

>
```
英和辞典によると、femtoは10^{-15}だそうで、すごくちっちゃいlispということだろうな。

こんな動かし方になるので、scheme系らしい。

```julia
> (define (mao me you) (list you me))
#fn("6000r2}|L2;" [] mao)

> (mao 'a '(1 2))
((1 2) a)

```
VSCodeでよく使うショートカット

VSCodeでよく使うコードをまとめたメモ:pencil2:

PCのショートカットも含みます （※ 随時更新）
コマンドはmacの記号で表記しています。

- Command（⌘）
- Shift(⇧)
- option(⌥)
- control(^)

***

| コマンド | 実行結果 |
|:-:|:-:|
| ⇧ + ⌥ + ↑↓  |  アクティブ行をコピペ |
|  ⌘ + D | Dを押すごとにマルチ選択。一括編集  |
|  ⌘ + T | コマンドパレットを展開 >compareはよく使います  |
| ^ + ←  | 行の先頭に移動 |
| ^ + →   | 行の文末に移動  |
| ^ + ↑↓ |  アクティブ行を上下に移動 |
Google Apps ScriptのPropertiesServiceでキーに数値文字列を使うとハマる

#概要
Google Apps Scriptには永続的なKey-Valueストアとして`PropertiesService`がある。これは単独のKey-Valueペアを`getProperty`/`setProperty`できるだけでなく、複数のKey-Valueペアをオブジェクトとして表現し`setProperties`することもできるし、`getProperties`ですべてのKey-Valueをオブジェクトとして取り出すこともできる。しかしKeyとして`"123"`のような数値文字列を使うと`getProperties`では簡単に値を取り出せなくなる。

[Properties Service | Apps Script](https://developers.google.com/apps-script/guides/properties)

#JavaScriptのオブジェクトとしての挙動を確認
まずJavaScriptのオブジェクトにおいて、プロパティ名に数値や数値文字列を使った時の挙動を確認する。

```javascript:test1.gs
function test1(){
  var newProperties = {
    82: "eighty two",
    "83": "eighty three"
  };
  Logger.log(newProperties[82]);   // "eighty two"
  Logger.log(newProperties["82"]); // "eighty two"  
  Logger.log(newProperties[83]);   // "eighty three"
  Logger.log(newProperties["83"]); // "eighty three"
}
```

これは問題ない。プロパティ名として数値を使ってもただ相当する数値文字列として扱われるだけだ。

#`getProperties`で取り出すと値が`undefined`

`setProperties(newProperties)`で保存し`getProperties()`で取り出すと確かにオブジェクトが得られるが、そのオブジェクトから値を取り出そうとすると`undefined`になる。

```javascript:test2.gs
function test2(){
  var newProperties = {
    82: "eighty two",
    "83": "eighty three"
  };
  var scriptProperties = PropertiesService.getScriptProperties();
  scriptProperties.setProperties(newProperties);
  var properties = scriptProperties.getProperties();
  Logger.log(properties[82]);   // undefined
  Logger.log(properties["82"]); // undefined  
  Logger.log(properties[83]);   // undefined
  Logger.log(properties["83"]); // undefined

  Logger.log(typeof properties); // object
  Logger.log(Object.prototype.toString.call(properties)); //[object Object]
  Logger.log(JSON.stringify(properties)); //{"82":"eighty two","83":"eighty three"}
  properties[82] = "EIGHTY TWO";
  Logger.log(properties["82"]); // "EIGHTY TWO"
}
```

`PropertiesService`から取り出した`properties`は普通のJavaScriptのオブジェクトとは違うものなのだろうかと思って`typeof`してみたり`JSON.stringify(properties)`してみたりしたが、特におかしなところは無かった。

#`getProperty`でひとつずつ取り出すと問題なし
`getProperties()`でKey-Valueペアをまとめて取り出したオブジェクトから値を取り出そうとすると`undefined`だが、`getProperty("82")`のように一つのKey-Valueペアなら正しい値が取り出せる。

```javascript:test3.gs
function test3(){
  var newProperties = {
    82: "eighty two",
    "83": "eighty three"
  };
  var scriptProperties = PropertiesService.getScriptProperties();
  scriptProperties.setProperties(newProperties);
  Logger.log(scriptProperties.getProperty("82")); // "eighty two"
  Logger.log(scriptProperties.getProperty("83")); // "eighty three"
}
```

#結論
Google Apps Scriptの`PropertiesService`では数値文字列をキーに使っちゃダメ。`getProperty`で一つずつ取り出しているときには問題ないが、そのうちKey-Valueペアが増えてきてまとめて`getProperties`しても値は取り出せない。どうしても取り出したければ`getProperties`で取り出したオブジェクトを`JSON.stringify`してから`JSON.parse`してまともなオブジェクトに戻す。

#想像
Google Apps ScriptはJavaScriptの実行エンジンとしてMozilla Rhinoのたぶん古いバージョンのものを使っている。`getProperties`で取り出したオブジェクトはRhino上では普通のオブジェクトと異なる何か変なJavaオブジェクトだったりするのではなかろうか。RhinoがJavaScriptのオブジェクトをどのような内部表現で扱っているのかは知らない。`JSON.parse`を実装しているJavaコードはそれをうまく扱うことができるんじゃないだろうか。いったんJSONな文字列になってしまえばこっちのものである。
Cloud function for firebaseで定期実行


## 手順

特に難しいことは何もない。

* いつもどおりfirebase initでfunctionsを作る
* functions.pubsub.schedule().onRun()で関数を作る
* deploy

本家の解説は[ここ](https://firebase.google.com/docs/functions/schedule-functions)。

有償プランである必要があるが、アカウント毎に3つまで無償らしい。
GCP側のUIでもある程度いじれるみたい。


## 実装

下記のような感じ。

```js:index.js
const functions = require('firebase-functions');

exports.cron = functions.pubsub.schedule('every 1 minutes') //('* * * * *') cron風にも書ける
    .timeZone('Asia/Tokyo')
    .onRun((context) => {
        console.log("hello");
        console.log(context);
        return 0; //Function returned undefined, expected Promise or value 防止
    });
```

## その他

contextの内容を出力してみたが、特に役立ちそうな情報はないみたい。
timestampが取れるので実行時間を記録したいとか、条件分岐したいとかに使えるかな。

```
{ eventId: '854843810028592',
  timestamp: '2019-11-23T21:45:00.067Z',
  eventType: 'google.pubsub.topic.publish',
  resource: 
   { service: 'pubsub.googleapis.com',
     name: 'projects/project-id/topics/firebase-schedule-cron-us-central1',
     type: 'type.googleapis.com/google.pubsub.v1.PubsubMessage' },
  params: {} }
    
```
Gradle5 で Lombok が使えない

# macOS x IDEA x Gradle5 x Spring-boot2 で Lombok を使おうとして、コンパイルはできるがビルドができない。

アノテーションの設定や Lombok Plugin の設定は済んでいて、@Slf4 を記述し、log.debug を記載してエディタ上でエラーは発生しないけど、ビルドすると以下エラーが発生する。

```
/src/to/path/TestController.java:14: エラー: シンボルを見つけられません
        log.info("start");
        ^
  シンボル:   変数 log
  場所: クラス TestController
```

以下の設定を build.gradle に追加したら解決

```
compileOnly group: 'org.projectlombok', name: 'lombok', version: "${lombokVersion}"
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: "${lombokVersion}"
```

※「providedCompile」で読み込もうとしていたのが誤りのようでした。

参考：
https://intellij-support.jetbrains.com/hc/en-us/community/posts/360003400520-Intellij-Idea-Lombok-Gradle-5-broken-build
python仮想環境(venv)にインストールしたjupyter-labを使う

すでにQiitaにも投稿がありましたが、情報が点在していたので整理しました。

ポイントは２つです。
* 仮想環境にインストールしたカーネルを使う
* 実行環境(python)のパスに仮想環境を追加する

わかってしまうと当たり前なんですが、調べずに元の環境にインストールしてしまうことが多いです。

### 環境
* MacOS 10.15.1
* python 3.7.4 (pyenv/anyenv)

### 仮想環境作成
仮想環境を作成するモジュールはインストール済みとします。

```
$ virtualenv test
$ source test/bin/activate
$ pip install keras
$ pip install jupyterlab
```

### 仮想環境にカーネルをインストール

```
$ pip install ipykernel
$ ipython kernel install --user --name=test
```

### 実行
jupyter-labを起動します。

```
$ test/bin/jupyter-lab
```

インストールしたカーネルが一覧に表示されるので今回作成したカーネル(test)を選択します。
カーネルはメニュー(Kernel/select kernel)から選択することもできます。
![launcher_JupyterLab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5247/ad607f54-9f49-cc3b-0dbb-67876f53a4bf.png)

起動画面(右側)のカーネルがtestになっていることがわかります。
![start_JupyterLab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5247/16db74e2-4baf-8cf6-93b2-ba6f0d71803e.png)

仮想環境でインストールしたモジュールをimportするとエラー(ModuleNotFoundError)が発生します。
![JupyterLab_ModuleNotFoundError.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5247/01b8928b-172e-0479-c226-de63f937b7e4.png)

Pythonのパスを表示します。
![JupyterLab_syspath_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5247/c96a9b97-8983-f0d7-be10-3ef9bf730d70.png)

仮想環境のパスを追加して実行してみます。
importに成功します。
![JupyterLab_syspath_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5247/0157e178-3680-fe03-5913-bfde66a70e24.png)
![JupyterLab_install_keras.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5247/3f69022e-9635-40e2-ef25-ff3f9c96cfa8.png)


# リンク
* [jupyter notebookでvenvを使う \- Qiita](https://qiita.com/Gattaca/items/80a5d36673ba2b6ef7f0)
* [Using jupyter notebooks with a virtual environment \- Zettel](https://anbasile.github.io/programming/2017/06/25/jupyter-venv/)
* [作ったpythonの仮想環境をjupyter labに認識させる方法 \- Qiita](https://qiita.com/limeearth/items/2a3bf3d4a04ed9d66742)
* [venvのJupyter Notebook利用時にModuleNotFoundErrorが出てきてしまった時の対処 \- Qiita](https://qiita.com/ninomiyt/items/b81866a17b4379ccb522)
IntelliJでJarファイルをワンクリックでpluginフォルダにビルドする

マイクラでPluginの開発をしている時に、すこしでも時間短縮をしたかったので、ワンクリックで使用したいサーバーのpluginsへぶっこむ方法を書きます。

## 環境
* Windows 10 Pro
* IntelliJ IDEA 2019.2.2

## ~~素晴らしい~~前置き
今日もいい天気なのに、どうして僕(私)はいちいちビルドしてからビルドしたjarファイルをいちいちpluginsファイルに置いてreloadしないといけないんだろう...と思ったことはありませんか？かなりの開発者が思ったことがあるはずです。

さて、そんなあなたに朗報です。右上の緑の右三角を押すだけで、そのプロセスをすべて行って、コンソールでreloadとうつだけであなたの最高で素晴らしいプラグインが試せます！では参りましょう。

## Build Artifactを作る
### 基本設定
1... Fileを押す
2... Project Structureを押す
3... Project Settingsを見る
4... Artifactsを押す
![intellij_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/c83eacd5-bba5-d24a-b109-831d23e576f8.png)
![intellij_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/38412d94-afc6-ef54-72c3-e0fc0096da4f.png)

5... 上のプラスボタンを押す
6... JAR ▶を押す
7... From modules with dependenciesを押す
8... **画像と特に違いがなければ**、OKを押す[^1]

![intellij_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/ceed6e74-e450-4cf6-3552-649710384e14.png)
![intellij_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/3e786f56-22ba-97eb-a664-34965e329c05.png)
![intellij_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/0907d44d-a24b-378a-b021-78e0eb2a4e9f.png)

9... Output Layoutの下辺りにあるプラスボタンを押す
10... Fileを押す
11... `プロジェクトへのパス\src\main\resources\plugin.yml`を指定する
12... OKを押す
13... Output Directoryに、サーバーのpluginフォルダを設定する
14... OKを押す

![intellij_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/2c200986-ac87-5e58-5f4f-8d337a8a310b.png)
![intellij_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/6fd10e4c-059d-8e80-472d-fafdb0f40670.png)
![intellij_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/f5e5452f-8309-a421-b3fd-d5785948ac44.png)


## Build Artifactを試してみる

1... 上のメニューのBuildを押す
2... Build Artifactsを押す
3... 先程作ったArtifactを押す
4... Buildを押す

![intellij_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/6e46bdb0-30ed-0602-fe19-ed259a641e32.png)
![intellij_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/30906ef2-d8c3-1459-90ca-2fd9bc7c3614.png)

これで、pluginsファイルにプラグインの名前のjarファイルが生成されているはずです！やったあ！
あとは、サーバーで実行してテストしてみてください。

## ボタンを押して指定したディレクトリへビルドする
1... 右上のSample Buildを押す
2... Edit Configurationsを押す
3... 左上のプラスボタンを押す
4... JAR Applicationを押す
5-1... Nameを変える(任意)
5-2... Path to JARを、サーバーのjarのパスにする
5-3... Working Directoryを、サーバーのルート(一番浅いフォルダ)にする
5-4... JREをDefaultにする[^1]
5-5... Search sources using module's classpathを`<whole project>`にする
6... 先ほど作ったArtifactを設定する(チェックを付ける)
7... OKを押す

![intellij_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/0407a9b7-89b2-e0c2-b7fb-5bdb43440d19.png)
![intellij_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237514/eeefdbec-2706-bc6d-88c2-f192822a1567.png)

あとは、右上のドロップダウンからいま作ったJAR Applicationを選択して、Runボタンを押せばサーバーが起動してビルドしたものが自動で読み込まれているはずです！

それでは皆様、よき開発ライフを。

## 参考
https://www.spigotmc.org/threads/tip-one-click-artifact-build-and-spigot-server-start-in-intellij.308427/

[^1]: 場合によっては設定が変わることもあるかもしれませんので、環境によって合わせてください