OmniAICreator/Qiita-1.07M huggingface dataset:
openframeworksでオーディオ（音声）データをofxshadertoyのシェーダーに渡す

###openframeworks+ofxshadertoyでオーディオ（音声）データの扱い

openframeworksでサウンドデータをofxshadertoyのシェーダーに渡すやり方は、本家
https://openframeworks.cc
でもあまり詳しく論じられていません。それがわからないと、https://www.shadertoy.com/view/Xds3Rr
とかは、openframeworksで動作しません。
今回、色々試して、とりあえず動いているようなので、手順を記します。

![out000001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/93174fe4-2b9b-30b8-9079-42a8a850a99b.jpeg)

![out000122.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/2d745349-76fc-23ca-fa35-c438a037c2ca.jpeg)


###アドオンofxFftの導入
先ず、アドオンofxFftを導入します。
projectGenerator.exeなどのツールを使って、ofxFftを組み込んでください。
###ofApp.hの修正
ofApp.hに
```
enum { SINE, MIC, NOISE };
```
及び
```
　#include "ofxFft.h"
```

を追加します。
また、以下の関数と変数を追加します。
```
 void audioReceived(float* input, int bufferSize, int nChannels);	
 ofxFft *fft;
 ofMutex soundMutex;
 ofSoundStream sound_stream;
 vector<float> middleBins, audioBins;
 vector<float> middleBuffer, audioBuffer;
ofTexture mTexture;
```

###ofApp.cppの修正
次に、audioReceivedの処理を以下のようにします。

```
 void ofApp::audioReceived(float* input, int bufferSize, int nChannels) {

	if (!audioOn) return;
	if (mode == MIC) {
		// store input in audioInput buffer
		memcpy(&audioBuffer[0], input, sizeof(float) * bufferSize);

		float maxValue = 0;
		for (int i = 0; i < bufferSize; i++) {
			if (abs(audioBuffer[i]) > maxValue) {
				maxValue = abs(audioBuffer[i]);
			}
		}
		for (int i = 0; i < bufferSize; i++) {
			audioBuffer[i] /= maxValue;
		}

	}
	else if (mode == NOISE) {
		for (int i = 0; i < bufferSize; i++)
			audioBuffer[i] = ofRandom(-1, 1);
	}
	else if (mode == SINE) {
		for (int i = 0; i < bufferSize; i++)
			audioBuffer[i] = sinf(PI * i * mouseX / appWidth);
	}

	fft->setSignal(&audioBuffer[0]);

	float* curFft = fft->getAmplitude();
	memcpy(&audioBins[0], curFft, sizeof(float) * fft->getBinSize());

	float maxValue = 0;
	for (int i = 0; i < fft->getBinSize(); i++) {
		if (abs(audioBins[i]) > maxValue) {
			maxValue = abs(audioBins[i]);
		}
	}
	for (int i = 0; i < fft->getBinSize(); i++) {
		audioBins[i] /= maxValue;
	}

	soundMutex.lock();
	middleBuffer = audioBuffer;
	middleBins = audioBins;
	soundMutex.unlock();
}
```
上記はオーディオデータを受け取った場合の処理です。
この受け取ったデータをシェーダーに渡すためにテクスチャーに変換します。
void ofApp::update()内に、

```
　　　　soundMutex.lock();
　　　　unsigned char signal[1024];
　　　　// for FFT
　　　　for (int i = 0; i < 512; i++) {
　　　　　　　signal[i] = (unsigned char)(middleBins.at(i) * 255);
　　　　}
　　　　// for wave
　　　　for (int i = 0; i < 512; i++) {
　　　　　　　signal[512 + i] = ofMap(middleBuffer.at(i), -1.0, 1.0, 0, 255);
　　　　}
　　　　soundMutex.unlock();
　　　　mTexture.loadData(signal, 512, 2, GL_RED);
```
を追加し、フレームごとに音声データをmTextureにロードします。
そして以下のようにチャンネル（0－3）とmTextureを指定して
```
shadertoy[shdrNum].setTexture(＜チャンネル＞, mTexture);
```
とすればオーディオデータがシェーダーに渡ります。
UE4+ADX2で、複数のAtomCraftプロジェクトをUE4側で併用・統合（ロード関係まとめ）

# はじめに
アンリアルエンジン4とサウンドミドルウェア「ADX2 for UE4」を連携させた際、
サウンドオーサリングツール「AtomCraft」で複数プロジェクトからエクスポートされたAtom Cue SheetやAtom Cueを併用する方法と、ロード関係のまとめです。

複数人でプロジェクト別に作成した、もしくは別のプロジェクトから流用してきたAtom Cueを再生したい場合、この方法である程度UE4側プロジェクトで処理を統合することが可能です。

当記事ではUE4.23+「ADX2 LE v2.10.05」を使用します。基本的にブループリントのみでの実装を想定しています。

# 前提
AtomCraftでビルドしたAtom Cueがあることを前提に進めていきます。AtomCraftの使い方は下記の導入編にあります。
「ADX2 for UE4 LE」を使用します。導入や簡単な使い方は以下の記事にあります。
ADX2 for UE4の導入で、一歩上のサウンド表現を（導入編）
https://qiita.com/SigRem/items/4250925f6d66a4fd287a
ADX2 for UE4の導入で、一歩上のサウンド表現を（実践編）
https://qiita.com/SigRem/items/c089b71c42e898980a46

# 実装

## 併用したいacbファイル、acfファイルを確認する

まずはファイルを把握しておきましょう。キューやキューシートが含まれているacfファイルはもちろん、その再生にはacfファイルも必要です。
これらは両方とも正しくインポートされていても、キューの再生時は対応している（同プロジェクトの）acfファイルを読み込むことが必須です。
通常acfファイルを設定するにはツールバーの「Edit」→「Project Settings」を開きます。
![01B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e94bae5e-9cb5-158d-750c-492a9c68d0c8.png)
「CriWare」タブ→「Atom Config」の項目に使用したいacfファイルを設定します。
![02B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/37f1d196-3004-a14a-a2fb-12fac2be517f.png)

ところが、この方法ではacfファイルをひとつしか設定することができず、ランタイム中に差し替えることもできません。


## acfファイルをランタイムで切り替える
実行中にacfファイルを切り替えるには、**Load Atom Config**ノードを使用します。
![03B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9f6cae16-7959-d100-8ff4-1407d5faf729.png)
上記の例では、ふたつのacfファイルを切り替える処理にしています。

Acf Objectピンはインプットができるように見えますが、今のところ対応する変数タイプはなさそうです。
![04B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/2bdd91da-32f8-f174-4357-c75039671e9b.png)
このため、使用したいキューに対応するacfファイルだけは事前に決め打ちしておく必要がある……
のですが、命名規則を決めておけばキューからacfファイルを判別して対応することが可能です。
![05B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/da4358ac-ee54-7860-49b3-8a7b2755b218.png)
①再生したいAtomキューのキューシートを取得し、
②最初の3文字を切り出します。
③**Switch on String**ノードで識別し、
④対応したacfファイルの読み込みへ分岐します。
この処理により、**プロジェクトが判別できる識別子をキューシートの頭3文字につけておく**ことで対応ができるわけです。


## キューシートを読み込む
キューシートを手動で読み込むには**Load Atom Cue Sheet**ノードを使います。
![06B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/a976e261-f8ae-5ebd-0c45-ad75cc99249a.png)
通常はキューの再生を直接行うだけでいいのですが、ランタイムでは読み込みに負荷がかかることがあります。
ロード画面やレベル開始時にキューシートの読み込みを行うことでこの問題を解決できます。

別のレベルをロードする際にキューシートはメモリから破棄されますが、ゲームインスタンスなどの**レベルをまたぐことができるクラス内**で変数として保持しておくことで、メモリに維持することができます。
![07B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/680ff9a0-c893-387c-5895-e5e4e33a7b85.png)

## ロード状況を確認する
**isLoaded**ノードを使うことでキューシートが現在ロード済みかを確認することができます。
![08B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/316e4ee8-9ec2-0ff5-7a4b-7d3783cd85be.png)
上記のグラフ例ではキューシートが正常に読み込まれた場合にTrueを返し、画面に表示します。


## 動的にキューを取得する
キューシートがアセットに組み込まれており、かつロード済みの場合はキューを指定せずとも取得し、再生することができます。
![09B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/2654fdb0-1271-b3d2-eed7-215816ec9342.png)
**Get Atom Cue by Name**、**Get Atom Cue by Index**、**Get Atom Cue by Id**ノードを使用します。
それぞれ名前のとおり、キュー名、インデックス番号、IDで指定することができます。
このノードを使えば、アセット内にキューが含まれていなくても再生が可能になります。
【webpack】画像バンドル時に詰まったこと

# 概要
webpackの画像のバンドルの際にエラーが出て困ったのでその時の対処法をかく。

# 結論
最初に結論から言うとscssのルーティングが間違っていた。

ファイルの構造は以下のようになっている。

.
├── dist
│   └── index.dev.js
├── images
│   └── background.jpg
├── index.js
├── javascript
├── sample.js
├── sample.js.LICENSE.txt
└── scss
    ├── base
    │   ├── base.scss
    │   └── dist
    │       └── base.css
    ├── component
    │   ├── dist
    │   │   ├── practice.css
    │   │   └── slide.css
    │   ├── header.scss
    │   ├── practice.scss
    │   ├── slide.css
    │   ├── slide.css.map
    │   └── slide.scss
    ├── dist
    │   └── style.css
    ├── mixin
    │   ├── dist
    │   │   └── mixin.css
    │   ├── mixin.css
    │   ├── mixin.css.map
    │   └── mixin.scss
    ├── style.css
    ├── style.css.map
    └── style.scss

流れとしては
(1)component等でそれぞれの要素に対応するcssをまとめる。
(2)style.scssでimportでまとめる
(3)npx webpackでバンドルする

ここでbase.scssの誤り例を示す。

```:base.scss
body{
    font-family: "Hiragino Maru Gothic ProN";
    height:1000px;
    background: url("../../images/background.jpg");
    background-repeat: no-repeat;
    background-size: 100vw;
    background-attachment: fixed;
}
```

次に正しい例を示す。

```:base.scss
body{
    font-family: "Hiragino Maru Gothic ProN";
    height:1000px;
    background: url("../images/background.jpg");
    background-repeat: no-repeat;
    background-size: 100vw;
    background-attachment: fixed;
}
```

backgroundに注目してほしいが、<font color="OrangeRed">style.scssからのRoutingにしなければいけないのだ。</font>

ちなみにwebpack.config.jsは以下の記事の最終的なものを用いている。

https://qiita.com/maru401/items/fe01a700d6a0faa06346
Ubuntu20.04にNemoというファイラーをインストールする


## インストール

```bash
sudo apt install -y nemo
xdg-mime default nemo.desktop inode/directory application/x-gnome-saved-search
gsettings set org.gnome.desktop.background show-desktop-icons false
gsettings set org.nemo.desktop show-desktop-icons true
```


## 参考
https://neos21.hatenablog.com/entry/2020/03/22/080000
Tomcat with Docker 入門

# 背景
TomcatのDocker imageを使用してJavaServletを使ったサーバーを作りたい！
と思ったけど，Webアプリケーション初心者なのでTomcat公式イメージの使い方がよくわかりませんでした．
同じような問題を抱えている人に届くと嬉しいです．

# 環境
* MacOS Catalina
* Docker Desktop

```
Client: Docker Engine - Community
 Cloud integration: 1.0.2
 Version:           19.03.13
 API version:       1.40
 Go version:        go1.13.15
 Git commit:        4484c46d9d
 Built:             Wed Sep 16 16:58:31 2020
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.13
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       4484c46d9d
  Built:            Wed Sep 16 17:07:04 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.3.7
  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
```

使用したDocker image

* tomcat:8.5.35

# Tomcat公式イメージの使い方
### runの基本構文
基本的には以下のようにしてdocker runします．

```
 docker run --rm -v /directory/has/.war:/usr/local/tomcat/webapps -p xxxx:8080 tomcat:8.5.35
```

ここで早くもポイントなのが `/directory/has/.war` と `xxxx` の部分です．
`/directory/has/.war` はwarファイルの入ったディレクトリを，
`xxxx` はポートフォワーディングしたいホスト側ポートを表現しています．

### Tomcatイメージのデフォルト動作
先程述べたようにwarファイルの入ったディレクトリを `/usr/local/tomcat/webapps` にマウントしてあげると，Tomcatさんが勝手にwarファイルを解凍してデプロイしてくれます．（便利ですね）

### Tomcatイメージを使った開発
warファイルがあると．つまりアプリが完成している場合についてはお話しました．
しかし，今回の私のようにTomcatイメージを使って開発がしたい人もいるでしょう（いて下さい）．
そんなときは以下のようにDocker runしましょう．

```
docker run -it --rm --name tomcat_test -v /directory/has/.war:/usr/local/tomcat/webapps -p xxxx:8080 tomcat:8.5.35 /bin/bash
```

先程のコマンドに `-it` と `/bin/bash` を付け足しました．
これでコンテナの中に入って作業ができます．

このイメージにはデフォルトでJDKが入っていなかったので，以下のようにJDKを後入れすることにします．（Tomcat公式のDockerHubを見ると予めJDKが入っていそうなものもありました）

```
# apt update -y
# apt install default-jdk
```

ここまで来ると，後は Docker 固有の問題はおそらく無く，一般的なTomcatの通りに開発できます

### Tomcatでのディレクトリ構成

```
webapps/
      └─ WebAppName/
             ├─ WEB-INF/
             │      ├─ classes/
             │      └─ lib/
             ├─ src/
             └─ etc.
```

あたりがよくある構成かと思います．

### TomcatでのJavaServletのコンパイル
JavaServletではSource内でアノテーションパターン（"@"）を使用しているため，xmlは必要ありません．

```
at WebAppName Dir# javac -cp "/usr/local/tomcat/lib/servlet-api.jar:WEB-INF/lib/*" -d WEB-INF/classes/ src/hogehoge/*.java
```

このようにすることで，JavaServletライブラリ `/usr/local/tomcat/lib/servlet-api.jar` と外部ライブラリ `WEB-INF/lib/*` が使えます．

### Tomcat 起動
コンパイルが済んだので，Tomcatを起動します．

```
at tomcat Dir# ./bin/catalina.sh run
```

### まとめ
今回は Tomcat with Docker の入門でした．
UbuntuのイメージにTomcatを後入れして頑張る記事は沢山ありましたが，Tomcat公式イメージを使用した場合の解説記事が見つからなかったため，書いてみました．

誰かの役に立てたなら幸いです．
TypeORMでPostgreSQLのtimestamp without timezoneから取得したUTC時刻がOSタイムゾーン分ズレたら

無理やり矯正するtransformerを`@Column`に指定してみた

```
    transformer: {
      to: (value: Date) => {
        if (value) {
          value.setMinutes(value.getMinutes() + value.getTimezoneOffset());
        }
        return value;
      },
      from: (value: Date) => {
        if (value) {
          value.setMinutes(value.getMinutes() - value.getTimezoneOffset());
        }
        return value;
      },
    },
```

たぶん https://qiita.com/tokicat/items/534aba8f0f3e86870d62 の方がちゃんとしてる
.NET 5.0 での Windows.Forms について

注：完全な初回テスト記事なので、意味があることはほぼ記載しておりません。飛んできてしまった方、申し訳ないです。
# .NET framework の統合
さて、ついに [ .NET framework ] が [ .NET 5.0 ] に統合され、使用不可になってしまいますね。
~~（今まで本当にありがとう）~~
初見で怖かったのが、お勉強をまったくしていないおっさんなので、Windows.Forms がどうなるか？だったのですが、さすがそこはMicorsoft様、そういう低レベルのプログラマーの救済のためなのか、残してくれていらっしゃいますね。
~~（さすがにWCFは、gRPCになってしまったようですが）~~
と言うことで、ひとまず Windows Form Application VB.NET は、それなりに残してくれているようです。
# 作成の仕方
[ Visual Studio 2019 ] 上で、Formsをインストールしていれば、[ 新しいプロジェクトの作成 ] で出てきてくれます。
![01_PCreate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905868/640a2c5d-5e00-44d2-7af6-e5d5e1aa0866.png)
# その他（コントロール等）
## デザイナーのコントロール
ひとまず主要なコントロールはすべて継承しているようです。
![02_Controls.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905868/86815ab0-b882-e84c-551b-64d3e1df8d23.png)
（FileSystemWatcherの破棄時のハング事象が改善している。。。とかはないんだろうなぁ。。。）
## Myの名前空間
Myの世界も継承していますねぇ。Windows上で動く簡単なツールは、まだまだ作成出来そうですかね。
![03_My.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905868/5a909d34-53b9-914c-6e2a-b3d1598189a4.png)
## 参照の追加
ここが初見わかりずらかったですね。[ 依存関係 ] から [ NuGet パッケージの管理(N)... ] から、.NET系の参照の追加を行うようになっています。
![04_Ref.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905868/0ca55193-4c1b-b2bf-134c-8ac7544c0619.png)
![04_pkg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905868/1ee4eb37-78b5-b3b3-3846-d937e0c8e4b3.png)
~~（はい、ソース上にゴリゴリSQLを書いてしまう人です。すみません。やっぱMyBatis的なやつがあるのかな？）~~
# おわりに
ひとまずWindows上で仕事をする上で、簡易ツールとして Windows.Forms はまだ使えそうですね。ホッと一息。が、そろそろ本当に他を勉強しなきゃいけないのですよね。
Qiitaも含めて、少しずつでも勉強しないとなぁ・・・
Dockerコンテナ内からホストのsshエージェント転送する場合


デプロイなどでDocker内からsshする場合(capistrano等)にホスト側のssh-agent転送する方法です。

# LinuxやWSL2等の場合

``` docker-compose.yml
services:
  web:
    volumes:
      - "$SSH_AUTH_SOCK:/tmp/ssh-agent.sock"
    environment:
      SSH_AUTH_SOCK: "/tmp/ssh-agent.sock"
```
ホスト側のssh-agentのsockファイルの$SSH_AUTH_SOCKを中継すればいい形でシンプルです。

# Docker Desktop for Macの場合

```
services:
  web:
    volumes:
      - "/run/host-services/ssh-auth.sock:/tmp/ssh-agent.sock"
    environment:
      SSH_AUTH_SOCK: "/tmp/ssh-agent.sock"
```

何故か標準の$SSH_AUTH_SOCKでは動かなく別のsockファイルの/run/host-services/ssh-auth.sockだと動くようです。

この仕組み自体が下記githubのissue見ると2020年にようやく解決したみたいで4年かかったようで。。
$SSH_AUTH_SOCK is not being forwarded to docker · Issue #410 · docker/for-mac
https://github.com/docker/for-mac/issues/410

参考

- ファイルシステム共有 [osxfs] — Docker-docs-ja 19.03 ドキュメント
https://docs.docker.jp/docker-for-mac/osxfs.html#ssh-ssh-agent-forwarding

- Dockerコンテナでsshする時の鍵をホストから持ってくる - Qiita
https://qiita.com/uwork/items/849f1035a765adb9c3af#linux%E3%81%AE%E5%A0%B4%E5%90%88
以前までは鍵ファイルをコピーするなどの案も

# LinuxとMac混在のクロスプラットフォーム対応

.envファイルでsockファイルを自分用の環境に書き換えるようにして吸収しました。
無理くりです。。macが標準のSSH_AUTH_SOCKでできるようになれば簡単に解決なんですが。。

※docker-compose自体が.envファイルに対応しているので別途ミドルウェア不要です。

``` docker-compose.yml
services:
  web:
    volumes:
      - "$SSH_AUTH_SOCK_APP:/tmp/ssh-agent.sock"
    environment:
      SSH_AUTH_SOCK: "/tmp/ssh-agent.sock"
```

``` ..env
# mac以外の場合は下記を利用する  (WSL2など)
SSH_AUTH_SOCK_APP=${SSH_AUTH_SOCK}
# macの場合は下記を利用する  (macだと$SSH_AUTH_SOCKのデフォルトだと動かなかった)
#SSH_AUTH_SOCK_APP=/run/host-services/ssh-auth.sock
```

ちなみにわざわざSSH_AUTH_SOCKではなくSSH_AUTH_SOCK_APPと別名をつけているのは.envで定義したものよりシェルの値のほうが優先されるという仕様があったためです。

- Compose における環境変数 | Docker ドキュメント
https://matsuand.github.io/docs.docker.jp.onthefly/compose/environment-variables/#the-env-file

>シェル内にて設定される値は、.envファイル内のものよりも優先されます。

docker-compose.ymlでif文使えたらいいんですが無さそうでした。
Rancherというのを入れればできるそうですがよほどデファクトでない限りは入れたくはないので。

- Rancherでdocker-compose.ymlの条件分岐を試す - Yassan's Memo
https://yassan.hatenablog.jp/entry/advent-calendar-rancher-1213
GitHubデスクトップの取り消す技術


Revert(リヴァート)

pushした情報をローカルリポジトリに戻すことはできないので本当にpushして良いかどうかの確認をしてからpushする事が大事ですが、

もし誤ってpushしなくていいものをpushした際の対処法を記述します。

誤ってpushしたcommitをリヴァート(取り消す)技術を使います。

historyを確認し誤ってpushしたものを選択し、右クリックしRevert this Commitをクリックします。そして[Push origin]をクリック。すると...リモートリポジトリで誤ってputhしたコードは消えています！！また、ローカルリポジトリでも前のコードに戻っています!

Undo

誤った情報をcommitしてしまったら。
pushする前なら簡単に取り消す事ができます。

commitしたその欄にUndoが表示されます。それをクリックする事で、commitする前の表示に変わってくれます。

技術的な事、ご指摘がありましたらよろしくお願いします。
Progate jQuery 道場コース 中級編

道場コース難しい。。
今までの基礎的な部分を組み合わせているだけではあるんですが、それが組み合わさると全く別次元の難しさになりますね。
ただ、100％出来ないってわけではなかったし、次回はサクッと終わらせることが出来そう！
自分の力で作りなさいという風になると、その処理はどういった背景があってそうなっているのか、というしっかりとした理解が必要だと感じました。
とはいえ、楽しいという気持ちは揺るぎないですね！
HTMLのリンクで別ウィンドウを開く



## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ HTML(aタグ)の基礎知識が増える
・ HTMLのリンクをクリック時、脆弱性を防ぎつつ、別ウィンドウを開く方法

## リンクの仕様について

リンクは`a`タグで生成しますが、特に何も指定がない場合は、リンクにアクセスした同じウィンドウで開きます

## HTMLのリンクで別ウィンドウを開く方法

別ウィンドウでリンクを開きたい場合は、下記の様に`a`タグに`target="_blank"`属性を追加します

```haml:index.haml
.sns
  %a.qiita(href="https://qiita.com/s79ns" target="_blank")
    %i.fas.fa-search
```

しかし、`target="_blank"`だけでは、<font color="red">Tabnabbing（タブナビング）</font>と呼ばれる脆弱性を突かれる可能性があるそうです。

##### ・  Tabnabbing（タブナビング）
→ `target="_blank"`で開かれたウィンドウから、もとのウィンドウの操作ができてしまう脆弱性
　これを防止するには`target=_"blank"`と合わせて`rel="noopener"`属性を追加します

```haml:index.haml
.sns
  %a.qiita(href="https://qiita.com/s79ns" target="_blank" rel="noopener noreferrer")
    %i.fas.fa-search
```
Vue で scrollBehavior が効かないときの対処法

[公式ドキュメント](https://router.vuejs.org/ja/guide/advanced/scroll-behavior.html#%E9%9D%9E%E5%90%8C%E6%9C%9F%E3%81%AA%E3%82%B9%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0)にある通り

```javascript

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    return { x: 0, y: 0 }
  }
})
```
としてもうまく動作しない。 console.log を入れて確認したところそもそも scrollBehavior 自体呼ばれていないようだった。

```javascript
const scrollBehavior = (to, from, savedPosition) => {
  if (savedPosition) {
    return savedPosition;
  } else {
    return { x: 0, y: 0 }
  }
};

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes,
  scrollBehavior
});
```

のように 関数を別で定義して代入すれば動くようになった。

参考: https://forum.vuejs.org/t/cant-get-scrollbehavior-working/29077/5
【こりゃ便利！】SLACK便利機能 ワークフロービルダー実践編

さて今回私がご紹介するのは、以前**「こりゃ便利！Slack便利機能 10選(その１）」**でご紹介させていただいた、こりゃ便利な機能の１つ、**ワークフロービルダー**の私の実践のご紹介となります。
前回までの記事はこちらをご覧ください。<br>[【こりゃ便利！】Slack便利機能 10選（その１）][1]
[1]:https://qiita.com/takeC74/items/d91022d6727bd248b194
[【こりゃ便利！】Slack便利機能 10選（番外編）待望のカスタムセクション機能][2]
[2]:https://qiita.com/takeC74/items/9fa51adf8ca74d8fb7a1
[【こりゃ便利！】Slack便利機能 10選（その２）][3]
[3]:https://qiita.com/takeC74/items/5bd2f6b433c7874146df
[【こりゃ便利！】Slack便利機能 10選（補足：ブックマーク編）][4]
[4]:https://qiita.com/takeC74/items/4e3fa10ffd795aa2b197


今回は、所属する会社が参加しているアドベントカレンダー用に、12/1記事のトップバッターとして、記事を書いてみました。
なぜトップバッターにですって？　それは、**ぼくは一番が好きだ　ナンバー１だ！　誰だろうとぼくの前でイバらせはしないッ！**からです。それでは、どうぞご覧ください！！<br><br>
#▼こりゃ便利６_ワークフロービルダー（ワークフロービルダーの機能について：再掲）
詳細の使い方はコチラ➯　[Slack公式サイト][3]
[3]:https://slack.com/intl/ja-jp/features/workflow-automation
※これはもう「神」機能です！とっても便利！！
Slackのサイドバーから「ツール」＞「ワークフロービルダー」でメニューが開けます。
定型的なアクション（リマインダーや何かをトリガーにした投稿やPull型情報配信、簡単なフォームでのアンケート作成・収集などなど）のワークフローが簡単に作成できます。
アイデア次第でいろんな利用用途があり、コミュニケーションがかなり効率化出来ます。![pic_６WFB_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/88b58145-837d-7f8e-7eec-ca93dbad2f99.png)
<br>
私も下記の例示のように、いろんなワークフローを作っていますが、それぞれのワークフローに合った「アイコン」を「設定」から登録しておくと楽しいですヨ
作ったワークフローは似たようなアクションをする際に「コピー」したり、他の人を「コラボレーター」として参加させて、チームで運用することも可能になっています。
![pic_６WFB_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/c055ceaf-ee02-18ac-a5b4-087b49edaf4d.png)


#▼現時点で私が作成したワークフローを整理してみる。
4か月で**45個も作っていた・・・**

![pic_seiri_mywfb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/bfe0ccc3-9a8c-03f1-30b4-845bbe6941fe.png)

ワークフロービルダーはとっても簡単に作成できる（数分~）ので、私のように普段プログラムを作ったこと無い人間でも**いともたやすく**つくることができます。そしてその機能（=私は勝手に**スタンド**と呼んでいます）たちを使うと私の業務は、とっても便利に、円滑に**行われる**のです。
そう、**いともたやすく行われる~~えげつない行為~~**な訳なのです。

#▼「はたらく」を「楽しく」するために
ところで皆さんお気づきかもしれませんが、私のスタンドたちには、自分で作ったアイコンの画像を入れています。
以下の画像はそのやり方ですが、私はスージーＱという自分専用の秘書（無料）を雇っています。
自分のステータス（働いているとか休憩中とか）を他の人に報告させたり、オシゴトで依頼している回答について回答期限前に私の代わりにリマインドしてもらっています。

![pic_myswb_icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/0c735612-15fc-62c0-019b-0855f2b97ed3.png)


もう１つ紹介します。オシゴトだけど、**何度も言わせるって事は無駄なんだ・・・・・無駄だから嫌いなんだ　無駄無駄・・・・・**って気分になるときありますよね？　相手は初めてなのかもしれないけど、こっちは何回も、何十回も同じような問い合わせ回答しているようなとき。
私は担当しているslackの相談チャンネルで、よく問い合わせがある内容をセルフサービスで取得できるスタンドも作りました。
私や私のチームの人が捕まらなくても、自分で回答を探し出せるように。
ちゃっかりと、誰がワークフローを使用したのかわかるようにしたり、チームへのフィードバックフォームとかも仕込んでいます。

![pic_oyakudachi_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/49709c90-d521-aad1-7d9f-40644096b8c5.png)


#【こりゃ便利！】SLACK便利機能 ワークフロービルダー実践編は以上です
皆さん、いかがでしたでしょうか？　まだまだたくさんのスタンドをご紹介したいのですが、もし気になるスタンドがあれば、皆さんからのリクエストをいただけると幸いです。ご意見、ご感想もお待ちしております。　<br>他にも「こりゃ便利！」な機能がありましたら是非教えてください。<br>
<br>以上、最後までお読みいただきありがとうございました。
vscode, c/c++, python, docker, online judge toolsの環境構築

##dockerをAtCoderの環境構築に使おう！

###目的
AtCoderにて使用するプログラミング環境をdockerで構築する。
使用するPCを変更、またはOSの再インストールなどに柔軟に対応できる。
dockerfileの記載方法を学ぶ。
自分でdockerを使い開発環境を配布できる知識をつける。

###これまでの記事
[Docker, java, vscodeの開発環境を構築](https://qiita.com/RubyLrving/items/cf64555a155e92c9cce1)
[AtCoderで記載したコードをgithubへアップロードし勉強記録として保存しよう](https://qiita.com/RubyLrving/items/6ae8bff333d72f8cb21e)

##対象のPC環境
macbook pro

###使用するプロジェクト
[online-judge-tools](https://github.com/online-judge-tools/oj/blob/master/docs/getting-started.ja.md)
[vscode-remote-try-cpp](https://github.com/microsoft/vscode-remote-try-cpp)

online-judge-toolsはpython3とpip3を使用します。
python3とpip3をdocker fileとdevcontainer.jsonに記載します。

##docker file
vscode-remote-try-cppの.devcontainer > Dockerfileを開きます。
pip3のインストールを行います。

```dockerfile:dockerfile
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/cpp/.devcontainer/base.Dockerfile
ARG VARIANT="buster"
FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT}
# python3-pip
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    && apt-get -y install --no-install-recommends python3-pip \
    && rm -rf /var/lib/apt/lists/* \
    && rm -rf ~/.cache/pip
```

##devcontainer.json
ここではvscodeで使用するパッケージを指定できます。
python3を使用するので「ms-python.python」を指定します。

```json:extensions
	"extensions": [
		"ms-vscode.cpptools",
		"ms-python.python"
	],
```

postCreateCommandにて、
pip3を使用しrequirements.txtに記載されたツールをインストールします。

```json:postCreateCommand
"postCreateCommand": "pip3 install -r requirements.txt",
```

##requirements.txt
requirements.txtにて「online-judge-tools」を指定します。

```text:requirements.txt
online-judge-tools
```

##tasks.json
argsにてC++14を指定します。
「${relativeFile}」で現在開いてアクティブになっているファイルをコンパイルするように指定します。
また、online-judge-toolsの「oj t」にて指定するのは「a.out」の為、コンパイル時に出力するバイナリを「a.out」に指定します。
これで「oj t」をターミナルに入力するだけでサンプルケースをテストできます。

```json:tasks.json
            "args": [
                "-std=c++14",
                "-g",
                "${relativeFile}",
                "-o",
                "a.out"
            ],
```

##launch.json
デバッグ実行時の設定を行います。
「a.out」を実行するように指定。
また入力値を「input.txt"」を使用するようにします。
デバッグ実行の度にINPUT値をコピペしなくてよくなります。

```json:launch.json(C++設定)
            "program": "${workspaceFolder}/a.out",
            "args": ["<input.txt"],
```

ここにpython3のデバックを起動した際の設定を追加します。
「Python: Current File」にて、作業中のファイルを実行します。
C++と同じように「args」の設定をする事で「input.txt」の値を使用するようにします。

```json:launch.json(python)
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "args": [
                "<input.txt"
            ],
        },
```

##online judge toolsでやっておくこと

online judge toolsのログインのコマンドを実行し、ログインを行いましょう。
本番中のコンテストはログインをしないとコマンドが実行できません。

```cmd:ログインのcmd
oj login 
```


##まとめ
今まで勉強したターミナル、コマンドプロンプト、docker、vscodeの知識を使用しました。
実際の開発でもdockerとgitは必須知識です。
基礎はできるようにしておきましょう。

##次回
vscodeはnpmスクリプトを覚えるともっと便利に使えます。
npmスクリプトを勉強していきます。
AmazonランキングをBeautifulSoapでスクレイピングしてAmazonアソシエイトタグ付きをTweepyでつぶやく

#　目的

ものすごく久々にGoogle App Engine(GAE/P)を触りたくなった。
Twitter投稿も以前は、PHPで書いていたので、Pythonで。
以前は、GAEランチャーアプリがあったが、今は見当たらなく、CUIにてデプロイするようだ。

# 手順
1.Amazon ランキングページのURLをBeautifulSoapに入れて、スクレイピング。
2.商品情報を取得して、URLにアソシエイトタグを追加
3.Tweepyでつぶやく
4.定期実行で定期的に実行する。

１〜３は、こんな感じ。

```　main.py
from flask import Flask
import requests
from bs4 import BeautifulSoup
import logging
import tweepy
import datetime
import time

app = Flask(__name__)

@app.route('/aibooksranking')
def aibooksranking():
    url = "https://www.amazon.co.jp/gp/bestsellers/books/720370/ref=pd_zg_hrsr_books"
    htmltext = requests.get(url).text
    soup = BeautifulSoup(htmltext,'html.parser')

    s = ''
    for el in soup.find_all("li", class_="zg-item-immersion"):  # zg_itemRow
        rank = el.find("span", "zg-badge-text").get_text()
        name = el.find("div", "p13n-sc-truncate").get_text().lstrip()
        item_urls = "https://www.amazon.co.jp" + el.find("a").attrs['href']

        poss = item_urls.find('/dp/')
        pose = item_urls.find('?', poss+4)
        jan = item_urls[poss+4:pose]
        aurl = "http://www.amazon.co.jp/dp/"+jan+"/ref=nosim?tag=xxxxxxx"
        dt_now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9)))
        today = dt_now.strftime('%Y年%m月%d日%H時')
        message = today + "の人工知能本売上"+rank +"位は\n\n" + name + "\n" + aurl
        #tweetを投稿
        consumer_key = ''
        consumer_secret = ''
        access_token = ''
        access_token_secret = ''

        auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
        auth.set_access_token(access_token, access_token_secret)
        api = tweepy.API(auth)
        api.update_status(message)

        time.sleep(60*1)

if __name__ == '__main__':
   app.run(host='127.0.0.1', port=8080, debug=True)
```

```
gcloud app deploy
```

Google App Engineの定期実行は、cron.yamlを編集する。

```
cron:
- description: tweet_post
  url: /aibooksranking
  schedule: every day 12:00
  timezone: Asia/Tokyo
```

cron.yamlをデプロイする。

```
gcloud app deploy cron.yaml
```

これで毎日、12時にランキングページから得た商品情報をつぶやく。

WEBページの構成が変わると修正しないといけないのがスクレイピングの弱み…、
Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ～jQuery × FetchAPI編～

#制作環境

Windows 10
Laravel : 6.18.35
Laravel/ui : 1.0
Laravel-mix : 5.0.1
Bootstrap : 4.0.0
axios : 0.19
Vue : 2.5.17
XAMPP
PHP : 7.4.3
Visual Studio Code

#はじめに

この記事はプログラミングをはじめたばかりの素人が、できたことをメモするのに利用しています。
内容には誤りがあるかもしれません。


前回のつづきになります。

#関連記事

[Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ～事前準備編～](https://qiita.com/Charry/items/737085257784bd9fb6e2)
[Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ～JavaScript編～](https://qiita.com/Charry/items/f605cbb686e8c0796450)
[Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ～jQuery編～](https://qiita.com/Charry/items/74c66aea1a82070a6d3d)
[Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ～JavaScript × axios編～](https://qiita.com/Charry/items/ffd6db72de2c2be96e43)
[Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ～jQuery × axios編～](https://qiita.com/Charry/items/0241c1b6a903c42cd9de)
[Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ～Vue.js × axios編～](https://qiita.com/Charry/items/7e932ce730a4d4c7e737)
[Laravel 6.x 非同期通信(Ajax) 【JavaScript】 【jQuery】 【axios】 【Vue.js】 各記述方法 ～JavaScript × FetchAPI編～](https://qiita.com/Charry/items/8297146146a6b729c8f6)

#今回作成するもの

<font color="blue">FetchAPIを利用し非同期通信を行い、自動で仕入れ先が入力される機能を実装します。</font>

##以下作成条件

* <font color="red">基本的な記述にはjQueryを使用し通信にはFetchAPIを使用します。</font>
* 数字が4桁入力されたら自動で仕入れ先を検索し、反映します。
* 検索するのにクリック操作を必要としません。`input`に入力されたら検索します。
* スクリプトの読み込みには`Laravel-mix`を使用します。
* 前回作成した`test.js`を編集して使用するで、必要なら`test6.js`等コピーを作成してバックアップしてください。

#スクリプトの作成

`resources>js`内の`test.js`を開き、以下のように記述します。
<font color="red">※前回作成した内容は全て削除してください。</font>

```JavaScript:test.js
// ここから先はjQuery編と変わらないため、詳細は割愛します
$(function() {
    $('#code').on('input', function() {
        let traderCode = $('#code').val();

        if (traderCode.length < 4) {
            return;
        }

        let url = 'form_search?trader_code=' + traderCode;
// ここまでjQuery編と変わらない

        // ここから先はJavaScript × FetchAPI編と変わらないため、詳細は割愛します
        fetch(url).then(response => response.json())
            .then(data => {
        // ここまでJavaScript × FetchAPI編と変わらない
                // 受け取ったデータ(検索結果)を仕入れ先のvalueに反映します 
                $('#supplier').val(data[0].trader_name);
            })
    })
})
```

#コンパイル

ターミナルを起動し、以下を実行してください。
<font color="red">※node.jsが必要です。インストールされていない方は、インストールを行ってください。</font>

node.js
https://nodejs.org/ja/

```PHP
npm run dev
```

#動作確認

コンパイルまで完了したら動作を確認してください。
問題無く業者名が表示されればOKです。

以上で終了です。
お疲れさまでした。
AWS api gatewayでCORSするときにつまづいたところ

## 要するに
AWSのapi gatewayを使ったCORSをしている最中に、
FireFox（個人的にやりやすかった）で「○○がない」と拒否されたら
![qiita.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217551/c4a08f68-d7af-14cb-7824-f952d422e053.png)

素直にapi gatewayのoptionメソッドのレスポンスヘッダーに追加しましょう。
![スクリーンショット 2020-11-30 11.26.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217551/1e513b41-d906-7a18-7e96-c6174600f475.png)

小文字「access-control-allow-origin」を要求されているので、
キャメルケース「Access-Control-Allow-Origin」を追加しても意味ないよ。


## 用語解説

・api gateway
AWSのAmazon Api Gatewayを指す。
[ApiGatewyへのリンク](https://aws.amazon.com/jp/api-gateway/)

・オリジン
オリジン = プロトコル + ドメイン + ポート番号
ttp://aaa.com:80 = ttp:// + aaa.com + :80
異なったオリジン間でのデータソース共有を指す。

|  CORSの例  |  オリジンが　同じ／違う  |
| ---- | ---- |
| ttp://aaa.com/index.html<br>ttp://aaa.com/search.html   |  同じ  |
| ttp://aaa.com<br>ttp://bbb.com | ドメインが違うから、オリジンも違う | 
| ttp://localhost:80<br>ttp://localhost:8080  |  ポート番号が違うから、オリジンも違う  |

・CORS
クロスオリジンリソースシェアリング（Cross Origin Resource Sharing）
オリジンが異なる場合の、データ共有の方法を指す。
異なったオリジンのリソースをシェアして使いたいときに使う技術。外部APIの利用など。
KaggleでLightGBMを使ってみた

KaggleでLightGBMを使ってみたので，その際得た知識をメモしておきたい．

``` train.py
# 正解ラベル
y_train = train_df['answered_correctly']
X_train = train_df.drop(['answered_correctly', 'user_answer'], axis=1)

models = []

# oof_train = []でも良いと思う．
oof_train = np.zeros((len(X_train),))

# K分割交差検証．汎化性能を上げる．非復元抽出．性能評価のため．
cv = KFold(n_splits=5, shuffle=True, random_state=0)

categorical_features = ['user_id', 'content_type_id', 'task_container_id', 'prior_question_had_explanation']

params = {
    'objective': 'binary',　# 最小化したい目的関数．binaryは二値分類で使う．
    'max_bin': 300,
    'learning_rate': 0.05,
    'num_leaves': 40　# 決定木の数
}

# enumerateでインデックスを取り出している．が，要らない．
# KFold.split()で分割したいデータを渡す．と，インデックスが帰ってくる．
for fold_id, (train_index, valid_index) in enumerate(cv.split(X_train)):
# loc: 名前で参照
# 番号で参照
    X_tr = X_train.loc[train_index, :]
    X_val = X_train.loc[valid_index, :]
    y_tr = y_train[train_index]
    y_val = y_train[valid_index]

    lgb_train = lgb.Dataset(X_tr, y_tr, categorical_feature=categorical_features)
    lgb_eval = lgb.Dataset(X_val, y_val, reference=lgb_train, # 訓練データと紐づける
categorical_feature=categorical_features) # 設定しないと自動で設定される．

    model = lgb.train(
        params, lgb_train,
        valid_sets=[lgb_train, lgb_eval],
        verbose_eval=10,　# 学習過程を表示する
        num_boost_round=1000,　# 計算回数
        early_stopping_rounds=10　# 過学習時に計算を打ち切る
    )

# 各クラスに属する確率を返す．
# アーリーストッピングで最も性能の良かったパラメータが選択される．
    oof_train[valid_index] = model.predict(X_val, num_iteration=model.best_iteration)
    models.append(model)

# AUC... Area Under an ROC Curve. 面積．閾値を変えつつ真陽性と偽陽性の正解率を算出．
　　roc_auc_score(y_train, oof_train)
```
【第4回】Python で競馬予想してみる　~ 単勝回収率の改善 ~

前回までに、scikit-learn のロジスティック回帰を使って競馬予測のモデルの赤ちゃんが出来上がりました。
今回は赤ちゃんから幼児くらいには成長させてみようと思います。

#モデルの検証
###前回までに作成したモデル
####説明変数
予想するレースでは、斤量のみ
n 走前のレースでは　斤量・単勝オッズ・人気・補正（補正タイム：クラス内相対値）・補9（補正タイム：絶対値）、確定順位
※前回までに作成したモデルは、1走前までのデータを使用

####予測の結果の混合行列

```text:Out
アンダーサンプリング,標準化
正解率 0.7564325552811307
混同行列
 [[ 14077  23335]
 [ 18676 116394]]
適合率 0.4297926907458859
再現率 0.3762696461028547
F値 0.40125418656025086
#学習・予測をし直してるので、第3回の記事と若干数値が異なります
```

####実際に馬券を買ったら
この予測モデルでに基づいて、単勝馬券を全て買ったらどうなるか計算してみました

```text:Out
Bet金額 3275300
収支 -718980
回収率 78.04842304521723
```

回収率 78.0% って出鱈目に買ったときと大差ないのだ

グラフにしてみると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895631/a1959253-dea6-e0b0-370e-c11c0dc9627a.png)

###説明変数を2走前までのデータに変更
####予測の結果の混合行列

```text:Out
アンダーサンプリング,標準化
正解率 0.753345762034756
混同行列
 [[ 12286  21206]
 [ 15839 100859]]
適合率 0.43683555555555553
再現率 0.3668338707751105
F値 0.398786049304575
```

1走前までの説明変数を使ったときと大差ないのだ

####実際に馬券を買ったら
この予測モデルでに基づいて、単勝馬券を全て買ったらどうなるか計算してみました

```text:Out
Bet金額 2812500
収支 -611480
回収率 78.25848888888889
```

回収率 78.3%
僅かに回収率が上昇したが、変化なし

グラフにしてみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895631/a08beb2e-eaa2-38b6-79d3-e9d78e6c230c.png)

###説明変数を3走前までのデータに変更
3走前までのデータを説明変数にする場合も試してみたが、変化なし。

###次の方針
回収率を改善するには正解率も大事だが、いかに人気薄の馬を予測し的中できるかが重要
そうすると、多くの人が注目しない説明変数を基に予測したほうがいいのかも
ということで、多くの人が注目しない説明変数で予測してみることにするのだ

###多くの人が注目する変数を使わないで予測
馬券の回収率を上げるために、多くの人が注目するような
予測レースの、単勝オッズ・人気
過去のレースの、補正（補正タイム：クラス内相対値）・補9（補正タイム：絶対値）、確定順位
などを説明変数に使わないで予測してみる。

####説明変数
予想するレースでは、斤量のみ
n 走前のレースでは　斤量、斤量体重比、枠番、馬番、脚質、キャリア、間隔
馬固有データとして、性別、年齢、父タイプ名、母父タイプ名
※2走前までのレースデータを連結して使用

####予測の結果の混合行列

```text:Out
アンダーサンプリング,標準化
正解率 0.7609278248727026
混同行列
 [[  2902  29308]
 [  4591 104993]]
適合率 0.3872948084879221
再現率 0.09009624340266997
F値 0.14618542679394503
Wall time: 7.4 s
```

再現率が、激減
説明変数が弱いから仕方ないのだ

####実際に馬券を買ったら
この予測モデルでに基づいて、単勝馬券を全て買ったらどうなるか計算してした

```text:Out
Bet金額 749300.0
収支 -130960.0
回収率 82.52235419725076
```

回収率が 82.5% なのには驚き
的中した馬券の　人気　とそのカウントを出力してみると ↓　
当たった馬券の 25% は、4番人気以下の馬なので正解率は同じ程度でも回収率が上昇したのだ

```text:Out
1     539
2     246
3     134
4      83
5      61
6      30
7      26
8      15
9       7
10      5
12      2
11      1
```


グラフにしてみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895631/23d1ca65-a03a-2c5c-7375-f88286366a8c.png)

##次回からの方針
正解率を上げようとすると、回収率が下がる（人気馬ばかり買う予測メソッドになってしまう）
人気に関わる要素（前走までの人気・オッズ・タイム）を入れないと回収率はアップするが、再現率が激減
次回からは、 ~~説明変数を変化させながら回収率を改善する方法を探るのだ~~ 良いアイデアが思い浮かばない💦

今回はここまで:wave:
Qiita記事にスラッシュ付きタグをつけると投稿できずエラーにもならないので注意

# TL;DR

Q. Qiita記事書いたけどなんか投稿できない
A. タグに入力した文字列に「/(スラッシュ)」入ってない？外してみるといいよ！

# Qiita記事が投稿出来ない！？

記事の内容自体はタイトルそのまんまですが折角なので経緯を少しだけ。
2020年のアドベントカレンダーに投稿しようとせっせと記事を書き投稿しようとした所「限定共有投稿」が出来ない事態に陥り「ナンデ！？Qiitaナンデ！？」と慌てふためいた所が始まり。

私もただの一般人ではなくエンジニアなので「動かねーぞ！バカヤロー！」とQiitaサポートチームにクレームあげる前に自分で分かる限りの対策を打ってみる事にしました。

* もしかしてNo Script有効になってた？ -> なってない
* AdBlockが原因？ -> Qiitaは除外してる
* Chromeが悪い？ -> FirefoxでもEdgeでもダメ

とある程度原因かもしれない要素を取り除きつつ試してみてあーなんかこれ本格的にQiita側がおかしそうだなという結論に思い至り、取り敢えずDeveloper toolさんを立ち上げました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536869/6afebdea-828a-8172-e388-acb48bd0f001.png)

まあ見ればわかる通りgraphqlのresponseで「Failed to process query」と返ってきているので恐らくサーバ側でrequest処理する時に想定外のparameter飛んできてerror出てんだろうなーという結論に。

じゃあどのrequestでerror出てるのか取り敢えず処理を追ってみるとどうも

1. タグのバリデーションチェック
2. 記事投稿

の順番で処理が行われているらしい。
実際にタグ何も入力しないで投稿しようとするとtoast上がるもんね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536869/7ea51c05-68f8-09df-3486-9d1a4e9121a8.png)

じゃあ多分タグのバリデーションチェックで想定外の文字列飛んでるのが原因なんだろうなーということで一番怪しげな「スラッシュ」を外してみると見事投稿に成功しましたとさ。
ちなみに「ハイフン」では正常に投稿できます。

ちなみにどんなtagだったかというと`Facebook/ent`でした。BeeXアドベントカレンダー2日目に投稿される予定です。
という訳で、BeeXアドベントカレンダー宜しくお願いします。
https://qiita.com/advent-calendar/2020/beex

内部でタグをsplitする過程でコケてるんだろうか、Qiitaさん早く治してー

おしまい
SOAPのstubファイル作成

近年RESTAPIが増えていますが、
まだまだSOAPもエンタープライズな用途としては使用する機会があると思います。

JavaのAxis2でSOAPAPIを構築した際の、wsdlファイルから呼び出し用のStubファイルを作成する手順の備忘録を載せておきます。
#環境

Windows10

#必要なもの

・SOAPのWSDLファイル（API提供元からもらってください）
・Axis2バイナリ（次項目で取得）
・JDK（事前にJAVA_HOMEを設定してください）

##手順

###1.Axis2バイナリ取得
以下のAxis2ページからDownloadsにアクセス
http://axis.apache.org/axis2/java/core/index.html

Binary distributionをダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172553/ddfdc567-4813-0428-934b-0144a8bc6327.png)


###2.作業フォルダにファイル配置
落としたファイルを下記に解凍
併せてWSDLファイルも配置

```
C:\dev
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172553/4bee749c-c0cd-b4e8-f7b5-e31cc69c9cff.png)

###3.環境変数設定
環境変数を起動し、
新規追加でAXIS2_HOMEを設定してください。
今回は以下の値
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172553/a3d26453-8438-ff01-1a3a-32cb87291a94.png)

###4.Stubファイル作成
PowerShellを起動して、対象フォルダに移動します。
※事前にJAVA_HOMEは設定しておいてください。
PowerShell起動後に行った場合は、PowerShellを再起動してください。

```
cd C:\dev
```

以下コマンドを実施

```
C:\dev\axis2-1.7.9\bin\wsdl2java -o TestSvc -uri TestSvc.wsdl
```
-uri は、WSDLへのパスです。WSDLがURLでの提供だった場合は、URLを記述します。
-o は、Stub作成先のフォルダです。

実行すると同フォルダに -o で指定したフォルダが作成され、
SOAP実行用の

```
Stub.java
CallbackHandler.java
```
のファイルがフォルダ内に作成されているかと思います。

この2つをシステムに組み込み、SOAPを実行してください！
Cloud Runでサービス全体の同時リクエスト数を制限する方法

Cloud Runでは、 サービスデプロイ時に `--concorrency` オプションを指定することで並列で裁く同時リクエスト数の上限を設定することができます。
`gcloud beta run services update [SERVICE_NAME] --concurrency=1`

しかし、このオプションはコンテナインスタンス単位の同時リクエスト数の上限設定のため、実際に来た同時リクエストの数が設定した上限を超えた場合は、別のコンテナが立ち上がり、全て並列で処理しようとします。
例えば、 `gcloud beta run services update [SERVICE_NAME] --concurrency=1` で同時リクエスト数の上限を1と設定した場合、同時リクエストが10件来た時には10個のコンテナインスタンスが立ち上がることになります。

Cloud Runのサービス全体で同時リクエスト数を制限したい場合は、 コンテナインスタンス数の上限を設定できるオプション `--max-instances` も合わせて設定することで実現可能です。
例えば、Cloud Runのサービス全体で同時リクエスト数を1としたい場合は、`--concorrency` 及び `--max-instances` をそれぞれ1に設定することで実現できます。
`gcloud run update [SERVICE_NAME] --max-instances 1 --concurrency 1`
not existsを扱う

以下のテーブルがある。

````sql
select * from testscores;

+------------+---------+-------+
| student_id | subject | score |
+------------+---------+-------+
|        100 | 国語    |    80 |
|        100 | 理科    |    80 |
|        100 | 算数    |   100 |
|        200 | 国語    |    95 |
|        200 | 算数    |    80 |
|        300 | 国語    |    90 |
|        300 | 社会    |    55 |
|        300 | 算数    |    40 |
|        400 | 算数    |    80 |
+------------+---------+-------+
````

全ての教科で50点以上取っている生徒を取得する。


````sql
select
distinct student_id
from
testscores ts1
where
not exists
(
    select
    *
    from
    testscores ts2
    where
    ts1.student_id = ts2.student_id
    and ts2.score < 50
)

+------------+
| student_id |
+------------+
|        100 |
|        200 |
|        400 |
+------------+
````

次は算数が80点以上、国語が50点以上の生徒を取得する。

````sql
select
distinct student_id
from
testscores ts1
where
subject in('算数','国語')
and not exists
(
    select
    *
    from
    testscores ts2
    where
    ts1.student_id = ts2.student_id
    and 1 =
    case when subject = '算数' and score < 80 then 1
    when subject = '国語' and score < 50 then 1
    else 0 end
)

+------------+
| student_id |
+------------+
|        100 |
|        200 |
|        400 |
+------------+
````

上記のSQLでは、国語のデータが存在しないstudent_id400の生徒が取得されてしまっている。
それを除外したい場合、行数を数えるhaving句を追加すればいい。

````sql
select
student_id
from
testscores ts1
where
subject in('算数','国語')
and not exists
(
    select
    *
    from
    testscores ts2
    where
    ts1.student_id = ts2.student_id
    and 1 =
    case when subject = '算数' and score < 80 then 1
    when subject = '国語' and score < 50 then 1
    else 0 end
)
group by student_id
having count(*) = 2

+------------+
| student_id |
+------------+
|        100 |
|        200 |
+------------+
````

こちらを参考にさせていただきました。
<a href="https://www.amazon.co.jp/%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6SQL%E5%BE%B9%E5%BA%95%E6%8C%87%E5%8D%97%E6%9B%B8-%E7%AC%AC2%E7%89%88-%E5%88%9D%E7%B4%9A%E8%80%85%E3%81%A7%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%84%E3%81%82%E3%81%AA%E3%81%9F%E3%81%B8-%E3%83%9F%E3%83%83%E3%82%AF-ebook/dp/B07GB4CNKP/ref=sr_1_1?adgrpid=48836428930&dchild=1&gclid=Cj0KCQiA48j9BRC-ARIsAMQu3WSrZJJd4-psCT9_qj0w4f0_fuN9b3Rh3DD8mwgP9UkTOLLapCJzwJwaAsG_EALw_wcB&hvadid=338547693256&hvdev=c&hvlocphy=1009306&hvnetw=g&hvqmt=e&hvrand=10462958271481352436&hvtargid=kwd-335112034228&hydadcr=4076_10899478&jp-ad-ap=0&keywords=%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6sql%E5%BE%B9%E5%BA%95%E6%8C%87%E5%8D%97%E6%9B%B8&qid=1605532234&sr=8-1&tag=googhydr-22">達人に学ぶSQL徹底指南書 第2版 初級者で終わりたくないあなたへ
</a>
Android OpenCVでエラー


`bitmapToMat`を利用したら、
エラー`cannot access class 'Bitmap'. Check your module classpath for missing or conflicting dependencies`とのこと。

該当のソース
`opencv/java/src/org/opencv/android/Utils`
を見てみると、インポートエラーを発見。なるほど。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447423/f2c27d7d-cf43-bc2e-a165-3351635287d7.png)


## 解決法
[このサイト](https://github.com/yoggy/AndroidOpenCV343Test)を参考にして、opencvのbuild.gradleでバージョンをいじったらエラーが消えました。
めでたしめでたし。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447423/aeb77938-8632-7f70-8be7-5d2c5c9c6e8d.png)

よくわからないけど、動いたからヨシ！
そんな打ち手で大丈夫か？「一番いいのを頼む」氷山モデルで一番いいのを探ってみる

本エントリは[iCARE Advent Calendar 2020](https://qiita.com/advent-calendar/2020/icare)の２日目です。

# はじめに

タイトルは約10年前に一世を風靡したゲーム「[エルシャダイ](http://elshaddai.jp/elshaddai_crim/index.html)」の主人公イーノックと大天使ルシフェルの会話のやりとりをオマージュしています。

作中で、大天使ルシフェルが、敵との戦闘に挑むイーノックのあまりにも頼りない装備を目にし、「そんな装備で大丈夫か？」と声をかけます。
その質問にイーノックは、「大丈夫だ、問題ない」と答え、颯爽と戦場に降り立ちますが、問題ありまくりで、あえなく返り討ちに遭ってしまいます。

そして、再度先頭の場面に戻り、「そんな装備で大丈夫か？」とルシフェルが声をかけると、「一番いいのを頼む」と返事をし、最強の装備を手に入れたイーノックは見事敵を倒す、という場面があります。(本編をよく見ると回避性能が向上しているように見えるので、装備のお陰ではないかもしれない)

これを氷山モデルになぞらえて考えてみます。

# 氷山モデルとは？

まず、氷山モデルとは、元々は心理学の概念で、自閉症の人の様々な行動を水面上の一角に例え、水面から上の部分の見えている部分ではなく水面下の要因に着目する考え方です。転じて、ビジネス視点にも応用されています。

## 図解

氷山モデルは、氷山の一番上の部分から、

![](https://d39kau1ie0fw3g.cloudfront.net/wp-content/uploads/2020/10/23184026/iceberg_model_sample-600x330.png)

という階層になっていて、1以外は水面下のもので、外からは見えません。

## イーノックの行動を氷山モデルで考えてみる

今回のイーノックの戦闘を氷山モデルで考えてみると、

![](https://d39kau1ie0fw3g.cloudfront.net/wp-content/uploads/2020/10/23184215/inoc-600x336.png)

となるかと思います。(完全に妄想です)

つまり、4の部分の改善すれば、そんな装備で大丈夫か？という問いに対し、何の根拠もなく、「大丈夫だ、問題ない」という返答は出ないはずですし、1回目の戦闘から「一番いいやつ」をオーダーできて、戦闘に勝利することができたと考えられます。

また、今回はたまたま「装備が貧弱だった」のが敗北した原因でしたが、
もし1の「事実」だけを基に打ち手を考えた場合、「負けたのはイーノックの俊敏性が足りなかったせいだ。だから、重たい防具は脱いで戦った方がいい」みたいな打ち手になることも考えられます。

何が言いたいかというと、事実だけを元に打ち手を考えることは極めて危険だということです。

## 事実だけをもとに打ち手を考えるのはやってしまいがち

「そんなこと言われなくてもわかってるわ」
「ちゃんとデータで裏付け取った上で打ち手考えているし」

みたいな外野からの声が聞こえてきそうですが、我々エンジニアの開発現場では、「事実だけを元に打ち手を考える」は意外とやってしまいがちです。

例えば、あなたがPjM(プロジェクトマネージャー)だとしましょう。

そして、「開発スピードがなかなか上がらない」という事実について、どういう打ち手を行うか考えているとしましょう。

現場からはよく、「人手が足りない」というぼやきが聞こえてきます。

この現状を踏まえて、予算の制約もあり、ひとまずオフショア開発会社からリソースの調達を行うことにしました。

それから3ヶ月経ちましたが、一向に開発スピードは上がっていません。

チームメンバーの様子をよく観察し、ヒアリングを行ってみたところ、「実装難度の高い箇所がある」「テーブル設計をどうすればいいか決められない」「要望がふわっとしていて仕様まで落とし込みきれない」という意見が上がって来ました。

今回の妄想ケースの場合、本当に必要だったのは単純な人手ではなく、上流から下流までこなせる「エンジニアリーダー」的なスキルを持つ人材だったことがわかります。

# まとめ

このように、「氷山の一角」だけを見て打ち手を考えても、物事がうまく回ることは難しいかと思います。水面下の「行動パターン」や、「構造」、「メンタル・モデル」までしっかり掘り下げた上で打ち手を模索することで、よりよい案が出てくるかと思います。

# iCAREテックブログもよろしくね！！

https://www.icare.jpn.com/dev_cat/
[Rails]ページネーション機能

# 実装したいこと
![完成形](https://i.gyazo.com/ef9c2a2789c70a954bbe3a16d9fb55cb.gif)

投稿が多くなってくると一覧表示した時に見にくくなってしまうのでページを分けました。

# 目次
- 1. kaminariのインストール
- 2. ページネーションの表示
- 3. デザイン
- 4. ラベルの変更

# 1. kaminariのインストール
Gemfileの一番下に以下を記述し、ターミナルでbundle installを実行します。

```ruby:Gemfile
gem 'kaminari'
```

# 2. ページネーションの表示
今回はbefore_actionを用いて投稿一覧を表示しています。
ページネーションを表示させたいデータに**.page(params[:page])**を追記します。
また、**.per(10)**を追記することで1ページに10件のデータを表示するという設定をします。
デフォルトでは25件が表示されるようになっています。

```ruby:app/controllers/posts_controller.rb
def index_post
  @posts = Post.order(created_at: :desc).page(params[:page]).per(10)
end
```

ページネーションを表示させたいところに**<%= paginate @posts %>**を追記します。

```ruby:app/views/posts/index.html.erb
~略~
  <div class='item-contents'>
    <h2 class='title'>クチコミ一覧</h2>
    <%= render "shared/posts" %>
    <%= paginate @posts %>   # 追記
  </div>
</div>
```

# 3. デザイン
今回はbootstrapとFont Awesomeを用いて実装しました。
まずbootstrapとFont Awesomeを読み込みます。

```ruby:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>CosmeticReview</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    # 以下を追記　Font Awesome読み込み
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.9.0/css/all.css">
    # 以下を追記　bootstrap読み込み
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%# <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```

次に、kaminariにbootstrapを適用させます。
ターミナルで以下を実行します。
##### ターミナル
```
rails g kaminari:views bootstrap3
```

実行後、app/views/kaminariフォルダが自動生成され、ページネーションにbootstrapが適用されます。

CSSでさらに自分の好みのデザインに変更します。

```css:app/assets/stylesheets/index.css
/* ページネーション */
.pagination {
  display: flex;
  justify-content: center;
}
.pagination > li > a {
  border: none;
  color: #999;
}
.pagination > li > a:hover {
  color: turquoise;
  background-color: white;
}
.pagination > .active > a {
  color: turquoise;
  background-color: white;
}
.pagination > .active > a:hover {
  background-color: white;
  color: turquoise;
}
/* --ページネーション */
```

# 4. ラベルの変更
今回はラベルにアイコンを用いて実装しました。

```ruby:config/locales/ja.yml
ja:
 views:
     pagination:
       first: <i class="fas fa-angle-double-left"></i>
       last: <i class="fas fa-angle-double-right"></i>
       previous: <i class="fas fa-angle-left"></i>
       next: <i class="fas fa-angle-right"></i>
       truncate: "..."
```

#3 参考リンク
https://github.com/kaminari/kaminari
https://qiita.com/rio_threehouse/items/313824b90a31268b0074
Ruby on Rails モデル検証〜文字列長の検証を追加〜



<h1>モデルの検証に文字列長の検証を追加</h1>

データベースの定義でnameカラムの文字列を30文字以下に制御しているが

```ruby:app/models/task.rb

class Task < ApplicationRecord
  validates :name, presence: true
end

```

このままだと、30文字を超える文字列を超える文字列が入力された場合、登録や更新の際に例外が発生してしまう。
これではユーザーが問題の原因に気づきづらく、動線も不便になってしまうので、30文字を超える入力の時に
わかりやすい検証エラーが表示されるようにしたいと思います。

まずTaskモデル(app/models/task.rb)にコードを追加します。

```ruby:app/models/task.rb
validates :name, length: { maximum: 30 }
```

これで30文字を超えるとエラーメッセージが返ってきます。

文字数制限を加えたい場合は参考にしてみてください。
CordovaのUIWebViewをWKWebViewへ移行しようとしてハマった

## はじめに
UIWebViewを使ったiOSのアプリが近い将来AppStoreで受け付けてくれなくなるので Cordovaで作成していたアプリの移行作業を行いました。

[CordovaのUIWebView→WKWebView移行についてまとめ](https://qiita.com/kishisuke/items/d201790aeae2129ff2e3)
こちらのサイトで丁寧に説明されているので移行作業はすぐに終わるものと想定していましたが、自分の環境ではうまくいきませんでした。
自分が解決に至った手順を同じ現象の方の参考になればと思い共有します。

## 行ったこと
* cordova-plugin-wkwebview-engine プラグイン追加
* cordova-plugin-wkwebview-file-xhr プラグイン追加
* config.xml に定義を追加
* apiサーバーのCORS対応

## 発生した問題
* jQuery Mobile のSPAアプリで、wwwディレクトリのhtmlファイルが not found になる
* インターネット上のapiサーバーとのajax通信で、BASIC認証後のPOSTが
HTTP401（Unauthorized）で失敗する

## 解決に至った手順
[No local file access #883](https://github.com/apache/cordova-ios/issues/883)
こちらのサイトにcordova-plugin-wkwebviewxhrfix を使えとあったので、cordova-plugin-wkwebview-file-xhrを削除してこのプラグインを追加
> I've faced the same issue and it fixes it, only need to install @ahovakimyan/cordova-plugin-wkwebviewxhrfix

## CORS対策は不要だった
サーバー側で、

```config
Header always set Access-Control-Allow-Origin "*"
```
とか

```config
Header always set Access-Control-Allow-Origin "file://"
```
等なにをやってもダメでしたが cordova-plugin-wkwebviewxhrfix を入れたらサーバー側のCORS対策がなくても問題ありませんでした

## iOS@5.1.1で動作した環境
cordova-plugin-wkwebviewxhrfixプラグインはバージョン0.1.0を入れます。

```config
cordova plugin add cordova-plugin-wkwebviewxhrfix@0.1.0
```
#### 各種バージョン

|項目|内容|
|---|---|
|Cordova|Version9.0.0|
|Cordova platform|iOS@5.1.1|
|cordova-plugin-wkwebview-engine|1.2.2|
|cordova-plugin-wkwebviewxhrfix|0.1.0|

#### 設定ファイル
```config:config.xml
<preference name="WKWebViewOnly" value="true"/>
<preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine"/>
<feature name="CDVWKWebViewEngine">
    <param name="ios-package" value="CDVWKWebViewEngine"/>
</feature>
```

## iOS@6.2.0で動作した環境 2021/09/29追記
Cordovaのバージョンを10、iOSのバージョンを6に上げて、
iOS@6用のcordova-plugin-wkwebviewxhrfixプラグインに変更します。

```config
cordova plugin rm cordova-plugin-wkwebviewxhrfix
cordova plugin add https://github.com/AraHovakimyan/cordova-plugin-wkwebviewxhrfix
```

#### 各種バージョン

|項目|内容|
|---|---|
|Cordova|Version10.0.0|
|Cordova platform|iOS@6.2.0|
|cordova-plugin-wkwebview-engine|iOS@6に統合されたので削除|
|cordova-plugin-wkwebviewxhrfix|1.0.0|
config.xmlの内容はiOS@5.1.1から変更していません。

## iOS@6.2.0でxcodeの実行ログにエラー 2021/09/29追記
iOS@6に上げたら以下のエラーが表示されるようになりましたが動作上は問題ありません。（気持ち悪いですが）

```config
CDVPlugin class WKWebViewXHRFix (pluginName: wkwebviewxhrfix) does not exist
```

## さいごに
半日で終わる予定が丸３日かかってしまいました。
<del>なお、iOS@6.1.1での動作確認は行っていません。</del>
論文用holoviewsの設定

matplotlibのラッパーであるholoviewsの論文用の設定メモ

matplotlibの設定は https://qiita.com/MENDY/items/fe9b0c50383d8b2fd919 を参考にした。


```
import numpy as np
import holoviews as hv
hv.extension('matplotlib') 

from matplotlib import rcParams
rcParams['font.family'] = 'Times New Roman' # font familyの設定
rcParams['mathtext.fontset'] = 'stix' # math fontの設定
rcParams["font.size"] = 24 # 全体のフォントサイズが変更されます。
rcParams['xtick.labelsize'] = 24 # 軸だけ変更されます。
rcParams['ytick.labelsize'] = 24 # 軸だけ変更されます

options_dict = {
    'Curve':
    {
        'fig_size':200,
        'fontsize': 15,
        # 'fontsize': {'labels': 24, 'legend': 18}, 細かく指定もできる
        'show_frame': True,
        #'show_grid':True,
        'xlabel': r'Using Tex $\alpha$', # 今回は非表示にしている
        'ylabel': 'Cross-Entropy loss',
    },
}


x = np.linspace(-np.pi, np.pi, 100)
y = np.sin(x)
img = (hv.Curve((x, y), label='aaa')*hv.Curve((x, 0.5*y), label='b')).options(options_dict)
renderer = hv.renderer('matplotlib').instance(fig='pdf')
renderer.save(img, 'file_name', style=dict(Image={'cmap':'jet'}))
img
```


結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53186/34f793b8-6101-a7fd-9a33-95586eca8837.png)