OmniAICreator/Qiita-1.07M huggingface dataset:
ajaxでrailsに数字を送る。

![c.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465210/eb136eaa-b44e-8cf8-1595-fd07f5caa03f.gif)

動画のような非同期のカウンターアプリを作った時に苦労したので共有します。

#　実装した手順
1.現在の番号をHTMLから取得
2.その番号をajaxでrailsのAPIに送信
3.API内で　送った番号 + 1　の数字にactive recordeの該当カラムを更新。
4.jbuilderでデータを返し、HTML上に反映。

この手順のうち、3で苦戦しました。
この記事では3のみ解説します。

##　当初のコード
```js:js
$(function(){
  $(".counter").on("click", function(){
    var ccc = Number($(this).text()); //カウンターをクリックするとカウンターの数字を文字列から数字に変換する。
    $.ajax({
      type: 'post',
      url: "/counter",
      data: {count: ccc},
      dataType: 'json'
    })

    .done(function(data){
      $(".counter").text(data.count); //railsでデータを返し、HTMLを更新する。
    })
  });
});
```
```ruby:controller.rb
def create #ajaxではpatchメソッドに対応していないブラウザがあるようなのでpostメソッド内でupdateを行なっています。
    @user = User.find(current_user.id)
    @co = params[:count] +  1 #ここで送られた数字＋1を定義。
    @user.update(counter: @co) #usersテーブルのcounterカラムを更新
    respond_to do |format|
      format.html
      format.json #返すデータはjson.jbuilderで定義。
     end
  end

#jbuilderファイルは省略。
```

このコードだと以下のエラーを吐き出しました。

```
TypeError in CounterController#create

no implicit conversion of Integer into String
Extracted source (around line #9)
//(around line #9)は　@co = params[:count] +  1　をさしています。
```
意味としては整数(この場合は`1`)を文字列に変えてくださいという内容です。
つまりは、`+`を四則演算ではなく、文字列結合に使おうとしているようです。
原因がわからず手当たり次第にコードを変えたら、以下のコードで問題なく動作しました。

```ruby:controller.rb

def create 
    @user = User.find(current_user.id)
    @co = params[:count].to_i +  1 #この行のみ変更
    @user.update(counter: @co)
    respond_to do |format|
      format.html
      format.json 
     end
  end
```
##　結論
結論としてはajaxで送られた数字は、paramsで取得すると、文字列となってしまうということです。
ちなみにrails内のみで渡したparamsも元データの形に関わらず、文字列となるようです。（この辺りは実験がまだ足りていないので要検証）。

##　別解
```js:js
$(function(){
  $(".counter").on("click", function(){
    var ccc = Number($(this).text()) + 1; //ここのみ変更
    $.ajax({
      type: 'post',
      url: "/counter",
      data: {count: ccc},
      dataType: 'json'
    })

    .done(function(data){
      $(".counter").text(data.count); //railsでデータを返し、HTMLを更新する。
    })
  });
});
```

そもそも`入手した数字+1`の処理をjs内ですれば
`update(counter: params[:count])`
だけでできた・・・
herokuでJpegが使えない

Ruby on rails で作成したアプリをherokuにpushし、本番環境にアクセスしたら「We're sorry, but something went wrong」、「If you are the application owner check the logs for more information.」というメッセージが出てしまいました。

![スクリーンショット 2019-09-11 5.06.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/495507/753572a3-b52f-fca7-5908-26cba79bb198.png)

ローカル環境では正常に動作していたのですが・・・・・

写真を多量に使用したので容量オーバーかなと思い、リサイズしましたが効果がなかったため、ページで使用している写真を半分削除してもう一度pushして見たら正常に作動しました。

容量オーバーとかではなく、削除した半分のデータに不具合があったのかなと思い、削除した半分の画像データを見てみると・・・・・・ん、拡張子が「jpg」となっている画像の中に、一個だけ拡張子が「jpeg」という画像データが！！

実際は「jpg」とほぼ同じみたいですが、herokuでは拡張子「jpeg」は使用できないみたいです。拡張子を「jpeg」から「jpg」に変更したら問題なくウェブサイトにアクセスできました。
Windowsでcredentials.yml.encを編集する with VSCode

# 概要
credentials.yml.encをWindowsで編集しようとして詰まった。

Windowsでの情報があんまりなさそうだったのでメモ

# バージョンなど
- OS:Windows10 HOME
- Ruby 2.6.3
- Rails 5.2.3
- VSCode 1.32.3

# やったこと
やったことはほぼ下記サイトの内容
>（Rails5.2）APIキーを直接コードに埋め込まないCredentials.yml.encの使い方
>https://qrunch.net/@WEkFtOQhlqcyDEsy/entries/bvfUcf0RmWqQ2NVH

環境変数EDITORで使用するエディタを指定してやればいい。

# 手順
コントロールパネル -> システムとセキュリティ -> システム -> システムの詳細設定 -> 環境変数(N)

環境変数の設定を開いてユーザー環境変数を新規(N)から作成

変数名(N)は`EDIOER`
変数値(V)に以下の内容を入力

```
"code" -w
```

codeでVSCodeを起動する(Windowsならデフォルトでコマンドが使えるはず)。

`-w`はファイルの保存待ちをするオプションらしい。無いと`credentials.yml.enc`が開く前にコマンドが終了してしまう。

あとは普通に以下のコマンドをたたけばいいだけ

```
rails credentials:edit
```

以上
[Rails]カスタムフォントの使用方法

#はじめに
個人アプリを作成する際にカスタムフォントを使用して文字のデザインを変更したので、その方法についてと本番環境でカスタムフォントが適用されなかったので本番環境で適用させる方法について書きたいと思います。

#カスタムフォントについて
まずはカスタムフォントを取り扱っているサイトから素材をダウンロードし`app/assets/fonts`以下にダウンロードしたカスタムフォント(拡張子は主に.ttf)を保存します。
次にcssファイルを作成し、以下の記述を追加します。

```ruby:font.scss
@font-face {
  font-family: "名前";
  src: url('ファイル名') format("truetype");
  font-weight: normal;
  font-style: normal;
}
```
後は適用したいcssのクラスに`font-family`を追加すればOKです。

```ruby:test.scss
.title {
    font-family: "名前";
  }
```
必要な場合はapplication.scssにて@importでファイルを読み込ませるのを忘れずに

#本番環境でも適用させる場合
この記述だと本番環境ではカスタムフォントが適用されない為、urlの所を`src: asset_url`を指定する事で本番環境でも適用させる事が出来ます。

```ruby:font.scss
@font-face {
  font-family: "名前";
  src: asset_url('ファイル名') format("truetype");
  font-weight: normal;
  font-style: normal;
}
```

#まとめ
画像もURLを正しく指定しないと本番環境にて読み込まれないですが、カスタムフォントも同様に指定しないと読み込まれないのははじめて知りました。今回はこの一文を修正するだけで上手くいったのでよかったです。

以下、参考にさせて頂いた資料です。
https://codeday.me/jp/qa/20190222/302271.html
jqでcsv変換する前にjsonの中のカンマを削除する

# やりたいこと
jsonファイルをcsvにして使用している。
csvにしたデータをawkでいじろうとしたとき、区切り文字以外にデータの中身にカンマがあり、うまく処理できない。
jsonファイルの中にあるカンマを削除する

# テストファイル
```test.json
[
 {
  "id": "1",
  "text": "text1 , test1"
 },
 {
  "id": "2",
  "text": "text2 , test2"
 }
[
```
# jqのgsub→失敗
tostringで配列が崩れて、@csvができなくなってしまう。

```
# cat test.json | jq '.[]|tostring|gsub(",";"comma")'
 "{\"id\": \"1\"comma\"text\": \"text1 comma test1\"}"
 "{\"id\": \"2\"comma\"text\": \"text2 comma test2\"}"
```

# 結局sedに頼る
分かりやすさのため、下記の例ではカンマ除去は削除ではなく、commaに変更している
カンマ除去の確認

```
# cat test.json | sed s/[^\"|^\}],/comma/g
[
 {
  "id": "1",
  "text": "text1 comma test1"
 },
 {
  "id": "2",
  "text": "text2 comma test2"
 }
[
```

CSV変換

```
# cat test.json | sed s/[^\"|^\}],/comma/g| jq -r '.[]|[.id, .text]|@csv'
"id": "1","text": "text1 comma test1"
"id": "2","text": "text2 comma test2"
```
Julia でロジスティック方程式を解く

# 0. 前書き：大学図書館で面白い本を見つけた

とある日、大学の図書館をいつものように物色していると数学の棚にあった１冊の本を手に取った。

**微分方程式で数学モデルを作ろう・日本評論社（書籍詳細は[こちら](https://www.nippyo.co.jp/shop/book/1240.html)）**

微分方程式で様々な現象をモデル化しているようだ。Julia で数値計算だったり微分方程式を解く手段だったりを知った直後だったので練習したいと思い図書館から借りてきた。

この記事では、この書籍に書いてある「人口問題」について実際にJulia で解いてみたので報告する。
まあ、タイトルにもあるように「ロジスティック方程式」を解いてみたのだ。

#1. ロジスティック方程式とは

[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%AD%E3%82%B8%E3%82%B9%E3%83%86%E3%82%A3%E3%83%83%E3%82%AF%E6%96%B9%E7%A8%8B%E5%BC%8F) によると、

>ロジスティック方程式（ロジスティックほうていしき、英語：logistic equation[1]）は、生物の個体数の変化の様子を表す数理モデルの一種である。ある単一種の生物が一定環境内で増殖するようなときに、その生物の個体数（個体群サイズ）の変動を予測できる。人間の場合でいえば、人口の変動を表すモデルである。

と書かれている。人間で言うところの人口変動を表すモデル、これでなんとなく理解はしていただけただろう。

具体的に、ロジスティック方程式は

$$
\frac{dN}{dt} = \gamma N\left(1 - \frac{N}{N_{\infty}}\right)
$$

のように記述される。ここで、$N = N(t)$ は「任意の時刻$t$におけるとある国の総人口」を表す。$N_{\infty}$ は「人口が増加した上限」である。

これを微分積分学の知識を用いて厳密に解くと、
$$
N(t) = \frac{N_{\infty}}{1 - \left(1 - \frac{N_{\infty}}{N_0}\right)e^{-\gamma t}}
$$

となる。ここで初期条件を $N(0) = N_0$ としている。
定数について、今回は

```math
N_0 = 3.9 \times 10^6 \\
N_{\infty} = 1.97 \times 10^8 \\
\gamma = 0.3134
```
とする。

#2. コードに落とし込む

それでは今回も [Ordinary Differential Equations](http://docs.juliadiffeq.org/latest/tutorials/ode_example.html) を参考にしながらコーディングしていこう。

```Julia:PopulationProblem.jl
using DifferentialEquations
using Plots; gr()

#微分方程式を定義
f(y , t) = 0.3134y*(1-y/1.97e8)

#初期値
y0 = 3.9e6

#時間間隔
tspan = (0.0, 70.0)

#微分方程式を解かせる
prob = ODEProblem(f, y0, tspan)
sol = solve(prob)

#グラフをplot
plot(sol; legend=:topleft , title = "PopulationProblem" , lw = 5 , label = "Numerical" , color =:black)

#厳密解を定義してグラフに追加する
g(t) = 1.97e8/(1 - (1 - 1.97e8/3.9e6)*exp.(-0.3134*t))
plot!(g , linestyle =:dash , lw = 3 , label = "Exact" , color =:red)
```
これを実行すると、きちんとグラフを出すことができた。$t \to \infty$ で$N(t) \to N_{\infty}$ に収束することは厳密解からも分かる。
<img width="1680" alt="スクリーンショット 2019-09-11 2.23.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367076/4366ca1a-b0b2-97eb-d3cd-f8dbe20f4b9a.png">

#3. 最後に
Twitterで助言をいただきながら今回も書くことができました。参考資料は本文中にリンクを埋めています。
Julia はとても簡単に記述できますね！
シェルスクリプトでキー入力のイベントを受け取る

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">read -t 1 の代替手段って何か無いかな。<br><br>for i in 3 2 1; do<br> printf &quot;%d 秒後に画面を再描画します\r&quot; <a href="https://twitter.com/search?q=%24i&amp;src=ctag&amp;ref_src=twsrc%5Etfw">$i</a><br> read -t 1 &amp;&amp; break<br>done<br><br>みたいに、基本3秒待つけれど Return を入力したらすぐに次に進むってのをやりたいんだけれど。</p>&mdash; いわもと こういち (@ttdoda) <a href="https://twitter.com/ttdoda/status/1171275191298576385?ref_src=twsrc%5Etfw">September 10, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">端末に詳しくないので何か穴がないかわからないですが、こんなのが見つかりました。<a href="https://t.co/rVTZ9xISHc">https://t.co/rVTZ9xISHc</a></p>&mdash; ふみやす＠シェルまおう(自称でない) FGO:838,149,789 (@satoh_fumiyasu) <a href="https://twitter.com/satoh_fumiyasu/status/1171295958065303552?ref_src=twsrc%5Etfw">September 10, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

`read -t N`のPOSIXシェルの範囲内でできる代替って無いのかなというのは以前から気になってたので、このやりとりを見つけてかなりすっきりしました。

https://stackoverflow.com/questions/32213758/posix-alternative-to-bash-read-with-timeout-and-character-limit

`min`と`time`はたしかにPOSIXに記載があります。
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/stty.html

ここで紹介されていた方法を応用すると、ゲームっぽいものもつくれそうな気がします。

```sh
#!/bin/sh

getch() {
  old=$(stty -g)
  stty raw -echo min 0 time 1
  printf '%s' $(dd bs=1 count=1 2>/dev/null)
  stty $old
}

print_aa() {
  _pos="${1}"
  _state="${2}"
  if [ "${_state}" = "0" ]; then
    _format="% ${_pos}s\\(^q^)/"
  elif [ "${_state}" = "1" ]; then 
    _format="% ${_pos}s/(^q^)\\"
  fi
  printf "${_format}"
}

pos=0
aa_state=0
aa_state_change_count=0

clear
print_aa "${pos}"

while :; do
  c=$(getch)
  case ${c} in
    "q" )
      break
      ;;
    "h" )
      [ "${pos}" -gt 0 ] && pos=$((pos-1))
      ;;
    "l" )
      [ "${pos}" -lt 30 ] && pos=$((pos+1))
      ;;
    * )
      ;;
  esac
  if [ "${aa_state_change_count}" -lt 4 ]; then
    aa_state_change_count=$((aa_state_change_count + 1))
  else
    aa_state_change_count=0
    if [ "${aa_state}" = "0" ]; then
      aa_state=1
    else
      aa_state=0
    fi
  fi
  clear
  print_aa "${pos}" "${aa_state}"
done

clear
```

`h`を押すと左に、`l`を押すと右に、`q`を押すと終了します。

![screenshot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26038/b7f5fdfb-6d58-427e-e112-08aab633bcb2.gif)

入力がある場合も最低何ミリ秒待つみたいなことができそうにないので、本当にゲームをつくるのは厳しいかも。
pythonでフォークト関数(Voigt function)をプロットする方法

# フォークト関数 (Voigt function)とは?

[フォークト関数 (Voigt function) ](https://en.wikipedia.org/wiki/Voigt_profile)は、ガウス分布とローレンツ分布の畳み込みした関数のことである。英語版のwikipediaには詳細な記載はあるが、日本語版にはない。

蛍光X線の自然幅が無視できないような精密分光をする場合などは避けては通れない関数である。畳み込みを計算するよりは、Faddeeva function を使うほうが早い。ここではpythonで簡単にVoigt関数を書く方法を紹介したい。一応，定義を書き下しておく．

```math:

V(x;\sigma,\gamma) \equiv \int_{-\infty}^{\infty} G(x';\sigma) L(x-x';\gamma)dx' = \frac{Re[w(z)]}{\sigma \sqrt{2\pi}}
```
とかける，ここで，Voigt関数は$V(x;\sigma,\gamma)$ であり，
ガウス関数は G(x;σ)と，ローレンツ関数 L(x;γ)の畳み込みとして定義される．

$Re[w(z)]$ は [Faddeeva 関数](http://wiki.analytica.com/Faddeeva)の実部で，$z = (x + i \gamma)/ σ\sqrt{2}$ の意味である．


## python で voigt function のプロットのサンプル

[scipy.special.wofz](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.wofz.html) が Faddeeva function を返してくれるので、これを用いればOK。

``` plot_voigt.py:

#!/usr/bin/env python
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'serif'
import numpy as np
import scipy as sp
import scipy.special

def voigt(xval,params):
    norm,center,lw,gw = params
    # norm : normalization 
    # center : center of Lorentzian line
    # lw : HWFM of Lorentzian 
    # gw : sigma of the gaussian 
    z = (xval - center + 1j*lw)/(gw * np.sqrt(2.0))
    w = scipy.special.wofz(z)
    model_y = norm * (w.real)/(gw * np.sqrt(2.0*np.pi))
    return model_y

# plot init function 
plt.title("Voigt function")
x = np.arange(0,100,0.1)

y0 = voigt(x,[1,np.mean(x),1,1])
plt.plot(x, y0/np.amax(y0), 'k-', label = "lw = 1, gw = 1")

y1 = voigt(x,[1,np.mean(x),1,10])
plt.plot(x, y1/np.amax(y1), '-', label = "lw = 1, gw = 10")

y2 = voigt(x,[1,np.mean(x),10,1])
plt.plot(x, y2/np.amax(y2), '-', label = "lw = 10, gw = 1")

y3 = voigt(x,[1,np.mean(x),10,10])
plt.plot(x, y3/np.amax(y3), '-', label = "lw = 10, gw = 10")

plt.legend(numpoints=1, frameon=False, loc="best")
plt.grid(linestyle='dotted',alpha=0.5)
plt.savefig("voigt.png")
plt.show()
```

生成される図はこちら。ピークは同じ高さになるように規格化してある。lw が Lorentzianの幅で、gwがGaussianの幅である。Lerentzianの方が裾が幅広なので、lw が効くと裾の大きい形状になる。

![voigt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179652/c9862fe7-428f-e6d7-91ae-5752fde233ae.png)

分光においては、Lorentzianの裾を定量的に知りたいときがあるので、
[半値幅の整数倍で見るガウシアンとローレンチアンの違い](https://qiita.com/yamadasuzaku/items/2c053ef5c6e9e9020501) の記事も書いたので気になった方は参考ください。

### Voigt 関数を用いたフィットの例

[pythonでパラメータの制限付きでfittingを行う方法](https://qiita.com/yamadasuzaku/items/c8fb95631956bf36f2a8) を参考。

### その他のライブラリ

ROOTには、TMathクラスに [TMath:Voigt](https://root.cern.ch/root/html524/TMath.html#TMath:Voigt) が定義されている。上記と同様にFaddeeva関数を用いた実装である。
WSL2におけるVcXsrvの設定

# WSL2でmatplotlibをプロットしようと思ったら...
なぜか出力するディスプレイが見つからないということを言われてしまったので, いろいろと調べてみました.

# (9/21/2021) 追加情報
現在、InsiderProgram上で[WSLg](https://github.com/microsoft/wslg)の開発が走っているので、将来的にはVcXsrvを使わずともネイティヴにGUI環境を実行できるようになるかと思います！
参考記事: [Windows 10 HomeでWSLgをさっそく試してみた](https://www.eisbahn.jp/yoichiro/2021/06/wslg.html)

# 参考としたサイト
[Can't use X-Server in WSL 2 #4106](https://github.com/microsoft/WSL/issues/4106)
こちらのサイトにほとんど解決策が載っておりますので, こちらの記事から抽出してまとめました.

# VcXsrvの自動起動設定
1. **xlaunch.exe**という実行ファイルがあると思いますので, 起動します.
2. multiple window を選んで, 次へを選択します.
3. start no client を選んで, 次へを選択します.
4. clipboard を使用したければ, clipboardにチェックを入れます.
5. **Additional parameters for VcXsrv** という入力フォームに **-ac** と入力して, 次へを選択します.
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269455/22041d37-0ab3-5c18-46e8-94aea8a1b0d0.png)

6. Save configuration を押して, どこかアクセスしやすい場所(デスクトップとか)に保存してください.
7. 完了を押してxlaunchを終了します.
8. 続いて, `Windowsキー + r`を押して, *shell:startup*と入力して検索します.
9. **スタートアップ**というフォルダが開きますので, ここに先ほどxlaunchを用いて作成したファイルを移動してしまってください.

これで, 自動的にVcXsrvがパソコンの起動時に立ち上がるようになりました.

# WSL上のディスプレイの設定
最後にVcXsrvの存在をWSLに教えてあげましょう.

1. Windows PowerShell を開きます.
2. ```ipconfig```と入力します.
3. *イーサネット アダプター vEthernet (WSL)*という項がありますので, その部分の***IPv4 アドレス*** をメモしておきます. 仮にここでは ```aaa.bbb.ccc.ddd``` としておきます.
4. WSLを開きます.
5. vim や nano などで`~/.bashrc`を開きます.
6. 開いた.bashrcの最後の行に, 以下のコマンドを追記して保存してください.

```shell:.bashrc
   export DISPLAY=aaa.bbb.ccc.ddd:0
```

最後にWSLを再起動すると, 先ほど編集した.bashrcが読み込まれて, 設定が反映されます.

# まだ改善できていない点
WSLに割り当てられるIPアドレスは再起動を行うたびに変更してしまうそうです。今の所IPアドレスを固定する術が見当たらないため、なにか情報がありますとありがたいです。
~~2019年9月現在はps1ファイルを作成してIPアドレスの割当を行っております。~~

# 追記
[Microsoftのissue](https://github.com/microsoft/WSL/issues/4106#issuecomment-501885675)にIPアドレスの割当方法が解決されていましたのでご紹介します。

```shell:~/.bashrc
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0
```
上の項で説明したexportの指示をこちらに変えていただけたらと思います。

# 追記2
[taichi-ishitani](https://qiita.com/taichi-ishitani)さまによると、次の方法で`/etc/resolv.conf`を参照せずともIPアドレスを割り当てることができるとコメントしていただきました。情報提供のほど感謝いたします。

```shell:~/.bashrc
export DISPLAY=`hostname`.mshome.net:0.0
```
参考記事: [WSL2 での DISPLAY 設定](https://qiita.com/taichi-ishitani/items/b627e31a97fef24c6ee4)


# 最後に
VcXsrv側に```-ac``` というオプションを加えましたが, 参考サイトによりますとパブリックアクセスを許可するコマンドであるそうです. WSL2が新たなコンテナシステムを形成したことによるのかと思われます。

## 以前の記事
[WSLでmatplotlibやgnuplotでプロットができない](https://qiita.com/ryoi084/items/c4339996c50c0cf39df4)
KotlinでQRコードを生成してみた

#まずはじめに
KotlinでQRコードの生成方法を学んだので、簡単にですが記録に残したいと思います。
参考になれば幸いです。

##使用するライブラリ
**ZXing**というライブラリを使用します。

###ライブラリの追加
`build.gradle(Module: app)`内の`dependencies`に以下を追加します。

```build.gradle
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
```
##MainActivity内の処理

####・QRコードをBitmapで作成

```
val bitmap = barcodeEncoder.encodeBitmap(data, BarcodeFormat.QR_CODE, size, size)
```

`data`…QRコードへ反映される文字列
`size`…QRコードの大きさを指定
直に指定しても変数で用意してもOK

####・生成したQRコードを画面上に配置

```
val imageQr = findViewById<ImageView>(R.id.qrCode)
imageQr.setImageBitmap(bitmap)
```

`imageQr`…`activity_main.xml`で設定した`ImageView`

###MainActivity内への追加コード

```kotlin:MainActivity.kt
try {
     val barcodeEncoder = BarcodeEncoder()
     val bitmap = barcodeEncoder.encodeBitmap(data, BarcodeFormat.QR_CODE, size, size)
     val imageQr = findViewById<ImageView>(R.id.qrCode)
     imageQr.setImageBitmap(bitmap)
    } catch (e: Exception) {

    }
```

#最後に
決済や入場管理などQRコードを利用する機会がなにかと増えている今日この頃、とにかく一度作成してみました。割と簡単に出来たかな、という印象です。ここから応用していければと思います。
Angularを試す為にdocker環境を準備する無駄さ

# Angularをdockerで手軽に楽しむ

って感じですが、試すくらいであれば優秀な、[StackBlitz](https://stackblitz.com/)が一番素晴らしです。是非とも使ってください。

![The online code editor for web apps  Powered by Visual Studio Code  - StackBlitz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/ec7c945d-fdfb-d12a-fea8-599c98bded87.png)

でも、cliとかでちょこちょこしたいや若干複雑なことしたい場合は選択肢的には、dockerもありだと思います。dockerじゃなくて普通にインストールがいいですが、ポイ捨てできるので試すくらいならありかと。

##### Table of Contents

1. docker fileを作成する
2. Angularのapplicationを作成する
3. ちょっと動かす

## 1. docker fileを作成する

[dockerのimageファイル](https://hub.docker.com/search?q=anuglar&type=image)さがしたんですが、なかったので、nodejsのイメージを使って作成します。

```terminal
$ mkdir sample && cd sample
$ touch Dockerfile
```

Angularの[setting up](https://angular.io/guide/setup-local)と同様にすすめていくので、
nodeのimageの取得と angular/cliをインストールします。

```Dockerfile
FROM node:10.16.3-alpine
WORKDIR  /myapp
CMD [ "npm", "install", "-g", "@angular/cli" ]
```

Angularのdev serverが4200番Portで動くので、portの追加と、面倒なのでプロジェクト全体をbindします。

```docker-compose.yml
version: "3.7"

services:
  client:
    build: .
    tty: true
    ports:
      - "4200:4200"
    volumes:
      - type: bind
        source: .
        target: /myapp

```

現状のtree構造は以下になります。

```terminal
$ tree -l
.
├── Dockerfile
├── README.md
└── docker-compose.yml
```

## 2. AngularのApplicationを作成する

流れとしては、docker containerを作成、中に入ってプロジェクトを作成していきます。

### 2-1. docker container作成

```
$ pwd
project/path
$ docker-compse up
```

でうだうだ時間がかかり、ついでにangular/cliもインストールしてくれます。

### 2-2. Angular Applicationの作成

作ったcontainerにアクセスして、Angular プロジェクトを作成していきます。

プロジェクトディレクトリにそのまま作成したいのですが、Schematicsでerrorはかれるので、
clientディレクトリを作成してそこにつっこみます。(nestjsはできるのに。。。)

```
$ docker exec -it CONTAINER_NAME bash
$ ng new client
# routingとstyleの質問に答えるとAngular applicationが作成されていきます。
# Google のPrivacy Policyの質問もいつのまにか増えた。
```

## 2-3. ちょっと動かす

ちょっと動かします。
っていっても、serverを起動させて画面上から見れる状況にします。

```
# Containerの内部に入り、
$ docker exec -it CONTAINER_NAME bash
# hostをかえて、dev serverを起動させます。
$ npm run start -- --host=0.0.0.0
```

そいでブラウザから localhost:4200 にアクセスして以下の画面がみれれば大丈夫かと。開発環境として使うのはもっとちゃんとした方がいいですが、お試しくらいならこの程度でいいと思います。

![Client.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/08a87154-14d5-6ca4-566c-b8ff3c5f1e3f.png)
格安VPN対応ルータの紹介

# 概要
　格安で拠点間VPNを導入できる、という話です。

　実際には2,000円程度で購入できるVPNルータのご紹介です。　
　拠点間VPNを業者にお願いすると数十万では済まないというか、ルータだけでも普通は数万以上の世界なので・・・
　個人的には非常に良いものでしたが、まぁ、あくまでネタ投稿です。　

![20190910_153543081_iOS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/95eb4e8b-b7a8-2454-080f-7180ebb580cc.jpeg)
![20190910_153616536_iOS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/dbf2e94d-5a21-7244-b3c4-df2a3dbcfa85.jpeg)

OpenVPNサーバを構築していることが前提なので、
https://qiita.com/SSMU3/items/8ea901031b2a0e7bb8f2
などを参考に、VPNサーバを構築しておきます。

# 設定方法

## 配線
### インターネットにつながっているルータから、ケーブルを引っ張ってきて、WANの接続口にLANケーブルを接続します。
### LANの接続口とパソコンのLANポートを接続します。
![20190910_153634352_iOS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/dc952ca6-f1c6-2a0f-0c22-f1e6a6126b62.jpeg)


## ルータの設定
### リンクアップしたらブラウザを開いて、URLに「192.168.8.1」と入力します。
### 初期画面が開いたら、言語を選択して、「Next」をクリックします。
![WS000004.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/6d7e146b-89f6-4b6d-ce49-c8ead2ac59ff.jpeg)
### パスワードを入力して、「Submit」をクリックします。
![WS000005.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/0d848c3c-2b67-a5de-6955-6073c0c7fc28.jpeg)
### 設定画面が開きます。
![WS000006.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/fd0f6fbf-465b-cdfe-1e26-1a41867864f4.jpeg)
### 左のメニューより「VPN」を選択し、「OpenVPN Client」をクリックします。
![WS000007.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/20bbf779-61d0-06cb-caf3-b45f7fb8351e.jpeg)
### 「+Add a New OpenVPN Configuration」をクリックします。
![WS000008.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/f5a0c941-bf43-ab64-4a91-7a7d6899e6a2.jpeg)
### 「ovpn形式(拡張子が「.ovpn」のOpenVPNファイル」を用意して、「Select a file or drag it hire.」にドラッグします。
![WS000009.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/e75e858e-49c8-728c-4a4b-65666f4ae693.jpeg)
### うまくアップロード出来たら、次の画面になるので、「Connect」をクリックします。
![WS000010.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/72a3730d-be0d-edfd-27c3-60881d21c87a.jpeg)
### 以下の画面が出たら接続完了です。
![WS000013.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/a7413eb1-da2c-7efd-8baf-d2460b75dd7b.jpeg)

## DNS設定
### 私の環境では、DNSの解決がうまくいかなかったので、個別に設定しました。
![WS000015.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400941/e8eaca1f-e64a-cea5-5188-11bfceaa4dec.jpeg)

# 終了
以上です。
私の環境では、これでOpenVPNのサーバにも、他にクライアント接続しているホストにもRDPやSSH接続することができました。
怪しげな製品ではありますが、通信を暗号化して使うなら、まぁありかなと。
ただし、あくまで自己責任で。

# 購入先
Amazonで購入できます。
https://www.amazon.co.jp/-iNet-MTK7628NN-WiFiミニ無線LANルーター-OPENWRT中継-USB給電ホテル用/dp/B073TSK26W/ref=sr_1_47?__mk_ja_JP=カタカナ&keywords=ルータ+ｖｐｎ&qid=1568131322&s=gateway&sr=8-47
Ruby学習メモ１『配列』

## Ruby 配列についての学習メモ


実行結果につきましては、irbコマンドを用い出力しております。


### 配列の要素を順に取り出すには


eachメソッドを用いた場合

``` ruby:index.rb
a = ["a", "i", "u", "e", "o"]

a.each do |x|
  puts x
end
```

forメソッドを用いた場合

``` ruby:index.rb
a = ["a", "i", "u", "e", "o"]

for x in a
  puts x
end
```

eachメソッドを用いた場合も、forメソッドを用いた場合も出力結果は同じ。putsなので、改行されて出力されます。

```
a
i
u
e
o
```

### 配列の要素をn個組み合わせた、順列を取り出すには

``` ruby:index.rb
n = 3
a = ["a", "i", "u", "e", "o"]

puts a.permutation(n).collect {|i| i.join }.join(" ")
```
permutationメソッドにより、配列の要素から引数n個の文字をつなげ、順列を作ります。

```
aiu aie aio aui aue auo aei aeu aeo aoi aou aoe iau iae iao iua iue iuo iea ieu ieo ioa iou ioe uai uae uao uia uie uio uea uei ueo uoa uoi uoe eai eau eao eia eiu eio eua eui euo eoa eoi eou oai oau oae oia oiu oie oua oui oue oea oei oeu
```

### 配列の要素をn個組み合わせた、重複順列を取り出すには

``` ruby:index.rb
n = 3
a = ["a", "i", "u", "e", "o"]

puts a.repeated_permutation(n).collect {|i| i.join }.join(" ")
```
repeated_permutationメソッドにより、配列の要素から引数n個の文字をつなげ、重複順列（順序あり、重複を許す組合せ）を作ります。

```
aaa aai aau aae aao aia aii aiu aie aio aua aui auu aue auo aea aei aeu aee aeo aoa aoi aou aoe aoo iaa iai iau iae iao iia iii iiu iie iio iua iui iuu iue iuo iea iei ieu iee ieo ioa ioi iou ioe ioo uaa uai uau uae uao uia uii uiu uie uio uua uui uuu uue uuo uea uei ueu uee ueo uoa uoi uou uoe uoo eaa eai eau eae eao eia eii eiu eie eio eua eui euu eue euo eea eei eeu eee eeo eoa eoi eou eoe eoo oaa oai oau oae oao oia oii oiu oie oio oua oui ouu oue ouo oea oei oeu oee oeo ooa ooi oou ooe ooo
```

ちなみにcollectは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作って返すメソッドです。

##参考資料

現場で使えるRuby on Rails 5 速習実践ガイド
[Rubyリファレンス](https://ref.xaio.jp/ruby)
[Matplotlib]3D散布図の底面に画像を挿入してみた

#導入
卒業研究の過程で3D散布図を作ることになった．

具体的にはアイトラッキングの研究の際に，PC画面に画像を表示させ被験者に一定時間見せた時の視線のx座標，y座標，時間tの3次元データ(csv）を元に散布図を作るときに底面（x，y面）に，見せていた画像を表示させるとわかりやすいと思ったのがきっかけである．

しかし，いくら探せど日本語の記事が見つからなかったので（2Dグラフの背景画像挿入は簡単みたいでいくつか記事は見つかった），今回筆をとった次第である．
>>謝辞 : Twitterでアドバイスをくださった先輩方にこの場を借りて心から感謝したい．

#対象者・救える人
3Dグラフ（散布図でなくても）を作る際に，底面(ひいてはx,y平面に水平)に任意の画像を表示したいという方．

#動作環境
anacondaで環境構築すれば全て標準でインストールされている．
- python : 3.7
- matplotlib : 3.1.0
- pandas : 0.24.2
- numpy : 1.16.4
- 同ディレクトリにPythonファイルとcsvファイル，画像ファイル(2018.png)を配置

#コード
```momosuke.py
# 諸々のモジュールのインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
from matplotlib._png import read_png
from matplotlib.cbook import get_sample_data
from pylab import *

# col_namesでカラム名を指定してcsvファイルを読み込む　*
col_names = ['x', 'y', 't']
data = pd.read_csv('kisisan.csv', names=col_names)

# 分かりやすいようにそれぞれ配列へ格納（自分がpython初心者のため）　*
listX = data["x"]
listY = data["y"]
listT = data["t"]
# データ数がめちゃ多かったので100ごとにスキップして再格納　*
listX = listX[::100]
listY = listY[::100]
listT = listT[::100]

# 3Dグラフを作る時のテンプレートみたいなもの（ax＝のところの書き方は複数あるっぽい)
fig = plt.figure()
ax = Axes3D(fig)

# 挿入画像を読み込む
fn = get_sample_data("/Users/momosuke/eye-tracking-for-efficiency-improvement-of-transfer/2018.png", asfileobj=False)
arr = read_png(fn)

# 画像を挿入（1094000000のところは挿入するZ座標．0など任意の値にどうぞ）
X1, Y1 = ogrid[0:arr.shape[0], 0:arr.shape[1]]
ax.plot_surface(X1, Y1, np.atleast_2d(1094000000), rstride=5, cstride=5, facecolors=arr)

# メインの散布図を挿入　*
p = ax.scatter(listX, listY, listT, s=100, alpha=0.8, c=listT, cmap='hot', label='eye-position')
fig.colorbar(p)
ax.plot(listX, listY, listT, linewidth=3, color='lightsalmon')

# 各座標軸のラベルの設定
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('t')

# 描画
plt.show()
```

# 実行結果
![insert-background.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331294/0850faba-38b9-582e-18a6-1a16d53d5309.png)

# 注意点
- コード中で#での説明文の右に`*`が入ってるのは散布図に関するコードなので本題の画像挿入には関係ないので適宜無視して活用してほしい．

- コード中の`get_sample_data()`で指定するパスは**相対パスではなく絶対パス**にすることを推奨する．相対パスにすると`FileNotFoundError: [Errno 2] No such file or directory: '/Users/momosuke/anaconda3/lib/python3.7/site-packages/matplotlib/mpl-data/sample_data/2018.png'`というエラーを吐かれる．要は相対パスを使いたいなら，`~/sample_data`に対象画像を置いてそれを参照してくれみたいなこと．

- この記事は画像挿入する方法を与えるものでグラフの細かいパラメータ設定は省いてるので詳細部は各々で調整してほしい．

# 参考文献
- [Image overlay in 3d plot using python](https://stackoverflow.com/questions/13570287/image-overlay-in-3d-plot-using-python)
- [Matplotlib: Show Backgroundimage in 3D Graph with plot_Surface](https://stackoverflow.com/questions/47744942/matplotlib-show-backgroundimage-in-3d-graph-with-plot-surface)
- [Python 3.7.4 ドキュメント](https://docs.python.org/ja/3/)
相互相関関数の計算方法の違いによる処理速度の差

# はじめに
相互相関関数を計算するときに，時間領域で直接計算（直接法）する方法とフーリエ変換を利用して周波数領域で計算する方法（FFT法）があります．計算時間はFFT法のほうが速いと聞きましたが，Numpyのcorrelate関数は直接法でしか計算できません．そこで，勉強を兼ねてFFT法を実装して試してみようと思います．
作り終わってから気が付きましたが，Scipyのcorrelate関数はFFT法が使えます．

# 参考
こちらの資料を参考にさせていただきました．
[コンボリューション関数（conv）と相関関数(xcorr)と離散フーリエ変換関数（fft）の関係](https://www.ikko.k.hosei.ac.jp/~matlab/xcorr.pdf)

# プログラム
ここからプログラム本体です．Juputer notebookで作成しました．
## 1. import

```python
#coding:utf-8
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
import scipy.signal as sg
```

## 2. 試験信号
ランダムな信号を作成します．

```python
N = 512
x, y = np.random.randn(2, N)
#正規化
x -= np.average(x)
x /= np.std(x)
y -= np.average(y)
y /= np.std(y)
```

## 3. 直接法

```python
corr = np.correlate(x, y, mode="full") / N
```
![直接法.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455608/06977af1-b593-710e-cd5c-220cc146d34d.png)


## 4. FFT法 巡回問題対策済み


```python
def xcorr(x, y):
    N = len(x) if len(x) > len(y) else len(y)
    #xとyの長さが同じになるように0を加える
    xz = np.append(x, np.zeros(len(y)-1))
    yz = np.append(np.zeros(len(x)-1), y)
    
    XY = np.fft.fft(xz) * np.conj(np.fft.fft(yz))
    xy = np.real(np.fft.ifft(XY)) / N
    return xy
```

## 5. 直接法とFFT法の計算結果の比較
FFT法では巡回問題を解決するために0を加えたため，インデックスが1つずれます．
1つずらして差分を取ると，両者の値は一致します．

```python
diff = np.real(xy)[1:N*2-1]-np.append(0.0,corr)[1:N*2-1]
```
![差分.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455608/e181f6bc-8252-83cf-6185-f07d07edf875.png)

# 処理速度の比較
直接法とFFT法の処理速度を比較します．処理対象のデータ点数が少ないときはNumpyの関数が速いですが，点数が増えてくるとFFT法の利点が顕著に見れます．
![処理速度.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455608/c996b0c7-1e87-37e9-0b81-3271a73be078.png)

# まとめ
FFT法は直接法に比べて処理速度が速かったです．ただ，遅れ時間がそれほど大きくないことがわかっているときは，直接法で計算範囲を絞ったほうが速いと思います．
InteliJのインストールと使いかた

# Introduction

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/3f0fc712-2380-8fe8-0241-0bb5a9460363.png)

# InteliJのインストール



[InteliJ](https://www.jetbrains.com/toolbox/download/download-thanks.html)からInteliJ ToolBoxをダウンロードします。

ダウンロードできたらdmgファイルを開いて、あとはよしなに設定します。
正常にダウンロードできたらToolBoxアイコンがMac画面の右上に出てくると思うのでそこをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/87164a5c-eaab-d8bd-8158-896e54f3f1eb.png)

するとToolBoxが開きます。
そして"community"のversionを選んでインストールしたら完了です。更新もこのToolBoxアイコンから簡単にできます。




# InteliJの設定　for Scala
まずは起動してみましょう。
loanch padなどから起動すると以下のような画面が出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/8aa81848-a79f-84db-5713-bb19a708164d.png)


次に、IDEAの Scalaプラグインをインストールする必要があります。

起動画面のConfigure->Pluginsをクリック

起動画面のConfigure 「Browse repositories」をクリックします。

検索窓からscalaで絞り込みインストールします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/dfdb6445-6c3e-9e26-d968-13802d99402f.png)

完了したら「Restart IntelliJ IDEA」をクリックします。




再起動後、起動画面で「Create New Project」をクリックし、次の画面のようになっていればインストールは成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/ee3be684-84db-bc5d-5657-382ff88f0b90.png)


# sbtプロジェクトのスタート

sbtプロジェクトのインポート
次に、単純なsbtプロジェクトをIntelliJ IDEAにインポートしてみます。
あらかじめ用意しておいたscala-sandboxプロジェクトを使います。 
[scala-sandboxプロジェクト]
(https://github.com/dwango/scala-sandbox)からgit cloneでcloneして適切なディレクトリにクローンしましょう。

scala-sandboxプロジェクトは次のような構成になっていれば大丈夫です。

```shell
scala-sandbox
├── src/main/scala/HelloWorld.scala
├── project/build.properties
└── build.sbt

```
このscala-sandboxディレクトリをIntelliJ IDEAに取り込みます。

まず、IntelliJ IDEAの起動画面から、「Import Project」を選択します。

ファイル選択の中からbuild.sbtをクリックして、OKします。

「Project JDK」が空の場合がありますが、その場合は、「New」を選択して自分で、JDKのホームディレクトリにあるJDKを指定します。


最後に、OKします。最初は、sbt自体のソースを取得などするため時間がかかりますが、しばらく待つとプロジェクト画面が開きます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/0afb8394-6cf2-69fe-5c51-c9555242f328.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/fe331d5b-917c-7e00-ac33-df1a0220fe0f.png)


上記の画面が出てきたら成功です！


# プログラムの実行方法

最後に、このHelloWorldプログラムを実行します。HelloWorld.scalaをIDEのエディタで開いた状態でメニューからRun -> Runと選択します。

Hello Worldを選択します。


すると、Hello Worldプログラムの最初のコンパイルが始まるので少し待ちます。その後、次のような画面が表示されたら成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/7b1eef08-78f1-45da-4d96-d241be3f129f.png)



# おわり

次回はScalaの基本的な構文などを勉強していきます。
その過程でオブジェクト志向プログラミングと関数型プログラミングについても勉強していこうと思います。
unix コマンドラインtips~ヘルスケアwebサービスを自分で作る医者の日記~

unix コマンドライン　bash

```
[vagrant@localhost unix_lessons]$ ls myapp/
hello.txt
[vagrant@localhost unix_lessons]$ cd !$
cd myapp/
```

rails の開発環境が再現できず、
unixのコマンドラインから勉強中
matplotlibの文字化けを解決する

# 環境
- Windows10 Pro
- Jupyter Notebook

# ダウンロード
[IPAexフォント](https://ipafont.ipa.go.jp/node26#jp)

# 関連するmatplotlibディレクトリの位置を確認

```python

import matplotlib
# 1.設定ファイル
print(matplotlib.matplotlib_fname())
# 2.設定ディレクトリ
print(matplotlib.get_configdir())

```
1.で表示される設定ファイル(matplotlibrc)のパスを使って、
2.で表示されるディレクトリへとコピーする

一例ですが、自分はWindowsなので以下のような場所に設定ファイルがあった。

```bash
C:\Users\user\Anaconda3\envs\環境\lib\site-packages\matplotlib\mpl-data\matplotlibrc
```

またユーザー用ディレクトリは以下の場所

```bash
C:\Users\user\.matplotlib
```



コピーしたあと、その設定ファイル(matplotlibrc)の最下部に以下を追加する

```
font.family : IPAexGothic
```
# フォントをコピーする

1.で表示した元の設定ファイルがあった場所にfontsというディレクトリがある。
更にそのディレクトリの下にttfというディレクトリがあるので、そこにダウンロードした「ipaexg.ttf」をコピーする。
`C:\Users\user\Anaconda3\envs\環境\lib\site-packages\matplotlib\mpl-data/fonts/ttf`


# フォントキャッシュを削除する
2.の「.matplotlib」ディレクトリにフォントキャッシュファイルがいくつか残っているはずなので、削除する
fontList.cache
fontList.py3k.cache
というファイルです。
自分の場合は「fontlist-v300.json」というファイルを消してJupyterを再起動したら日本語表示がでるきようになりました。


# 確認する

```python
import matplotlib.pyplot as plt
plt.figure()
plt.xlabel('テスト')
plt.title('テスト')
```

これで表示されるはずです。

# 参考
[matplotlibの文字化け問題でハマった時のメモ](https://qiita.com/ldap2017/items/f014f1c22de269012273)
[【matplotlib】図解！日本語フォントの設定方法](https://gcbgarden.com/2017/05/04/matplotlib-japanese/)
heroku本番環境（production）でデプロイ後の接続エラー対処方法

課題が終わると思ったらエラーが、、
データベース接続設定を忘れていたので、忘備録のために。。後学の初心者の為に。。。
#webアプリをherokuへデプロイして、アプリを開こうとしたら、エラーの文字が。。
We're sorry, but something went wrong.
If you are the application owner check the logs for more information.

#原因は..

**Rails側の設定でPostgreSQLを使用するための設定を忘れたのが原因だった。**
本来なら以下の手順でしていれば問題なかった。
1.Gemfile
2.config/database.yml

1の最後の行に

```ruby:Gemfile
group :production do
  gem 'pg', '>= 0.18', '< 2.0'
end
```

を追加。

$ bundle install --without production

実行。

```ruby:config/database.yml
production:
  adapter: postgresql
  encoding: unicode
  pool: 5
  database: アプリ名_production
  username: アプリ名
  password:<%= ENV['大文字アプリ名_DATABASE_PASSWORD'] %>
```

コミットを忘れずに。
$ git add .
$ git commit -m'#'

もう一度デプロイ。
$ git push heroku master

開くか確認。
https://Herokuアプリ名.herokuapp.com/
OKなら、
$ heroku run rails db:migrate
本来この手順ならここで終わりだが。。

私の場合は
**最初のデプロイでconfig/database.ymlを設定せずにいたために**
PostgreSQLが自動的にインストールされませんでした。

これを解決するには手動でインストール。
 ＄ heroku addons:create heroku-postgresql:hobby-dev

再度マイグレーション。

$ heroku run rails db:migrate

これでPostgreSQLに接続できるはずです。。。
GitHubって何？？

#GitHubとは
VCSの仕組みを利用したwebサービスの一種です。
#VCSとは
VCSは”Version Control System”の略で、ファイルやディレクトリのバージョンを管理するためのシステムのことを言います。

また、ファイルなどのバージョンを管理するデータベースを”***リポジトリ***”といいます。
##VCSの仕組み
VCSの仕組みは大きく分けて２種類あります。

- 集中型バージョン管理

サーバーにある一つのリポジトリを複数人で使用するものです。

- 分散型バージョン管理

各利用者のローカルにリポジトリを複製できます。サーバー上の利用者全員の共有のものを”***リモートリポジトリ***”、各利用者のローカル上のものを”***ローカルリポジトリ***”といいます。
#Gitの使い方
Gitは分散型バージョン管理の一種です。
##基本操作
1. clone(クローン)

     ローカルにリモートリポジトリの複製を作ります。

2. add(アド)

     ローカル上での変更点をcommit(コミット)の対象とします。

3. commit(コミット)

     addされたものをローカルリポジトリに登録します。

4. push(プッシュ)

     更新されたローカルリポジトリの情報をリモートリポジトリに反映させます。

5. pull(プル)

     他の利用者が更新したリモートリポジトリの情報をローカルリポジトリに反映させます。



１でローカルリポジトリを作った後、２～５を繰り返し行い、作業が進行していきます。
##branch(ブランチ)機能
例えば、機能ごとにチームを分けて開発していた場合、ほかの機能が出来上がってから自分の機能を追加させた方が効率的だなぁってことがあるかと思います。

そういう時に、以下のbranch機能が役立ちます！
###branch機能
リモートリポジトリに各チームのコピーを作成して、互いのチームの作業が干渉しないようにします。

このリモートリポジトリのおおもとのデータを”***マスターブランチ***”と呼び、各チームの情報（ブランチ）をマスターブランチに反映することを”***マージ***”といいます。
#GitとSVNの違い
Gitに対し、SVN(Subversion)は集中型バージョン管理の一つです。

もともと集中型バージョン管理の後に、分散型バージョン管理が登場したのですが、それには理由があります。

SVN(Subversion)には以下のような欠点があったのです。

- 全てのチームの作業が完了しないとコミットできず
     -  エラーが起きた際に原因をさかのぼるのが困難
     -  変更点がわからない
     -  誰が変更したかわからない

- レビューする人は全ての修正をまとめて確認しなくてはいけない
- ブランチ機能があるが、コンフリクトが発生した時が大変（Gitのマージ機能は優秀なのです。）

その点を改善するべく生まれたのがGitなどの分散型バージョン管理でした。

しかし、セキュリティが厳しくブラウザが使用できなかったり、特定のアドレスにしかアクセスできないような環境の開発現場では、SVNなどが使用されています。
#VCSのホスティングサービスの種類
##SVNのホスティングサービス
SVN(Subversion)の代表的なホスティングサービスには
![300px-Assembla_Logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446126/0f7884b2-cfe3-ac2a-6fdd-dc70a7971dbb.png)
ASSEMBLAなどがあります。
##Gitのホスティングサービス
Gitの代表的なホスティングサービスには
![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446126/992cbc2a-3311-ec72-68d7-bdd7e91436d7.png)
GitHubなどがあります。
配列とリストのシャッフル

シャッフルのアルゴリズムは、計算量$ O(n) $で効率が良いことで有名な **[Fisher-Yates shuffle](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC%E2%80%93%E3%82%A4%E3%82%A7%E3%83%BC%E3%83%84%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%95%E3%83%AB)** アルゴリズムを使います。

配列とリスト（`List<T>`）は `IList<T>` インターフェースを実装しているので、そこに拡張メソッドを定義すると両方で使えるようになります。
> C# 2.0 以降、下限が 0 の一次元配列は自動的に `IList<T>` を実装します。 これにより、同じコードで配列や他のコレクション型を反復処理できるジェネリック メソッドを作成できます。
[ジェネリックと配列 (C# プログラミング ガイド)](https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/generics/generics-and-arrays)

```C#
using System.Collections.Generic;
using UnityEngine;

public static class Extensions
{
    public static void Shuffle<T>(this IList<T> list) {
        for (int i = list.Count - 1; i > 0; i--) {
            int j = Random.Range(0, i + 1);
            var tmp = list[i];
            list[i] = list[j];
            list[j] = tmp;
        }
    }
}
```
Unity Android Build

https://forum.unity.com/threads/gradle-build-failed.647581/
ここにあった。
一応日本語で要約。

#UnityからAndroid Buildすると失敗する時のチェックの１つ

Android Studioで、Gradleの最新がRCだったらBuildで失敗する。

その場合、Android StudioのSDK Managerで、RCを削除しておけばOK
OpenCvSharpでピクセルに高速アクセス(1.1)

#OpenCvSharpのIplImageを用いて任意ピクセルに値の取得と変更
unsafeオプションをつけてコンパイルする必要がある．
GetPixel(...)は値取得
SetPixel(...)は値変更
Hoge(in string f)は呼び出し元．in string fは処理を行いたいファイルのパス

    using OpenCvSharp;
    public static unsafe byte GetPixel(IplImage src_img, int x, int y) {
        byte* src = (byte*)src_img.ImageData;
        return src[src_img.WidthStep * y + x];
    }

    public static unsafe bool SetPixel(IplImage src_img, int x, int y, byte PixelValue) {
        byte* src = (byte*)src_img.ImageData;
        src[src_img.WidthStep * y + x] = PixelValue;
        return true;
    }

    private static unsafe bool Hoge(in string f) {
        IplImage InputGrayImage = Cv.LoadImage(f, LoadMode.GrayScale);//グレースケールで読み込み
        SetPixel(InputGrayImage,5,4,36)
        byte hage = GetPixel(InputGrayImage,5,4)
        Cv.SaveImage("NewImage.png",InputGrayImage,new ImageEncodingParam(ImageEncodingID.PngCompression,0));//画像を保存
        Cv.ReleaseImage(InputGrayImage);
    }

#順次(シーケンシャル)アクセスの場合

       using OpenCvSharp;
       private static unsafe bool BinarizeImage(in string f) {
            IplImage InputGrayImage = Cv.LoadImage(f, LoadMode.GrayScale);//グレースケールで読み込み
            byte* src = (byte*)InputGrayImage.ImageData, dst = (byte*)FixedImage.ImageData;
            for (int y = 0; y < InputGrayImage.Height ; ++y) {
                for (int x = 0; x < InputGrayImage.Width ; ++x) {
                    if (src[InputGrayImage.WidthStep * y + x] > 127) {//ピクセル値が56以上だったらなんかする
                        src[InputGrayImage.WidthStep * y + x]=255;//代入処理 
                    }else src[InputGrayImage.WidthStep * y + x]=0;//代入処理           
             Cv.SaveImage("NewImage.png",InputGrayImage,new ImageEncodingParam(ImageEncodingID.PngCompression,0));//画像を保存
             Cv.ReleaseImage(InputGrayImage);
        }
##24bit三色カラーの場合
格納されている配列はBGRの順になるのが注意
offsetに予めポインタの位置を格納しておくと早くなる気がする．InputColorImage.WidthStep * yを計算しておくなど(可読性が下がるので注意,コンパイラが仕事してほしい)．
InputColorImage.NChannelsが味噌．jpgのカラー画像の場合3色(rgb)なので"3"．しかしPNGの32bitカラーの場合透明度(α)が1 Byteあるので"4"になっている．そのときはsrc[offset + 3]でアクセスできる．

       using OpenCvSharp;
       private static unsafe bool Hage(in string f) {
            IplImage InputColorImage = Cv.LoadImage(f, LoadMode.Color);//カラーで読み込み
            byte* src = (byte*)InputColorImage.ImageData;
            for (int y = 0; y < InputColorImage.Height ; ++y) {
                for (int x = 0; x < InputColorImage.Width ; ++x) {
                    int offset = InputColorImage.WidthStep * y + x*InputColorImage.NChannels;
                    if (src[offset + 0] > 127) {//blue
                    }
                    if (src[offset + 1] > 120) {//green
                    }
                    if (src[offset + 2] > 120) {//red
                    }
             Cv.SaveImage("NewImage.png",InputColorImage ,new ImageEncodingParam(ImageEncodingID.PngCompression,0));//カラーで保存される
             Cv.ReleaseImage(InputColorImage);
        }
ImageViewの画像サイズ処理　〜縮小させずに表示したい〜　

# とある開発中の一コマ
よし、じゃあここにUIImageViewを配置して…と
うんうん、正方形にしたいから縦横比は1:1に設定して
待って。。。画像が縮小されてる？！

![スクリーンショット 2019-09-10 22.08.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236122/4d9ce6bb-b4b8-9663-37bf-256236c7c2aa.png)
＊　ImageViewの背景色はグレーに設定してあります。

ImageViewには端から端まで画像をしっかり表示させたいですよね。 
意外と情報が少なかったので忘備録として残しておきたいと思います。

# 1. scaleAspectFill
ImageViewのサイズの比率はそのままで、空白を作らず表示する。
縦長なら横幅、横長なら縦幅がImageViewぴったりになります。
画像の中心とImageViewの中心は同じで、はみ出た部分は表示されません。

``` Swift:ViewController.swift
class ViewController: UIViewController {
    @IBOutlet weak var landscapeImageView: UIImageView!
    @IBOutlet weak var portraitImageView: UIImageView!
    
    let landscapeImage: UIImage = UIImage(named: "landscapeImage")!
    let portraitImage: UIImage = UIImage(named: "portraitImage")!
   
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        landscapeImageView.image = landscapeImage
        portraitImageView.image = portraitImage
        landscapeImageView.contentMode = UIView.ContentMode.scaleAspectFill
        portraitImageView.contentMode = UIView.ContentMode.scaleAspectFill 
    }
}
```
![スクリーンショット 2019-09-10 23.04.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236122/274b8a43-be4b-ca8c-cd62-f12209a29849.png)


# 2. CGImage.cropping(to:)
ImageView目一杯というよりは切抜きです。

``` Swift:ViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        cutImage(view: landscapeImageView, image: landscapeImage)
        cutImage(view: portraitImageView, image: portraitImage)  
    }

    func cutImage(view: UIImageView, image: UIImage) {
        let width: CGFloat = image.size.width
        let height: CGFloat = image.size.height
        if width != height {
            guard let cutImageRef: CGImage = image.cgImage?.cropping(to: CGRect(x: width/2, y: height/2, width: height, height: height))
            else {
                return
            }
            view.image = UIImage(cgImage: cutImageRef)
        } else {
            view.image = image
        }
    }
```

![スクリーンショット 2019-09-10 23.02.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236122/052c487d-f67c-48a8-9894-fc340fe66e7a.png)

# 最後に
基本的にはscaleAspectFillを使うのが一番だと思います。
croppingはもう少し設定を加えてあげると、scaleAspectFillよりも柔軟な画像サイズ処理を行えそうです。
あとは、cropped(to:)というお仲間さんがいてそれも便利なんだとか。
↑リンク貼っておきます！

# 参考にしたサイト
[SwiftにおけるUIImageView・contentMode 別の画像表示](https://blog.officekoma.co.jp/2016/10/swiftuiimageviewcontentmode.html)
https://developer.apple.com/documentation/coregraphics/cgimage/1454683-cropping
https://developer.apple.com/documentation/coreimage/ciimage/1437833-cropped
NVIDIA GeForce 入り PC で Ubuntu インストーラ(GUI版)の表示が壊れてた場合

# はじめに

NVIDIA GeForce 入り PC に Ubuntu を入れようとして GUI 版インストーラの画面が崩れる時は、とりあえずパラメータ編集で linux 行に nomodeset 追加を試してみては如何でしょう？ というだけのエントリです。

# 現象

RTX2080 入りPC で Ubuntu18 インストーラを起動すると画面がこんな感じでした。

| |
|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/d4cc180f-5130-0cc6-df9c-2a96a706cb49.png)|

```
Couldn’t get size: 0x800000000000000e
```

の文字がかすかに読めるので、これをヒントに探したりしました。

# 試行錯誤

UEFI が怪しいという情報ばかり見つかるので、非 UEFI モードを試したり。

| |
|---|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/04b553cb-c066-ebae-37a0-62282cd76071.png)|

secure boot を disable にして解決した声を見つけたが、管理者パスワードを設定しても disable が選択できなかったり。(これを可能にするパッケージがあるのを、その後で見つけるが試していない)

fastboot 無効は真っ先に試したし。ディスク4台が多過ぎかもと１台しか認識しないようにしたり。BIOSメニューで弄れる設定を片っ端から試して挫折。

# 解決

神の声。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"> @yoya CPUのGPU(マザボ映像出力)有のモデルですか？
外部GPUを外して内臓GPUだけで試してみるのはありかもしれません。
というのもログからはDRM(DirectRenderingManager)らしき文字が見えるので。
あとはインストーラーの起動時にカーネルパラメータ"nomodeset nvidia-drm.modeset=0 nouveau.modeset=0"か </p>&mdash; ʍoɹɐɥs (@sharow) <a href="https://twitter.com/yoya/status/1168452785219571712">2019年9月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

このうち nomodeset で解決しました。

具体的には、Install Ubuntu のメニューが出るところで、eボタンを押すとカーネルパラメータ設定がいじれて、linux 行の末尾におもむろに nomodeset を追記するだけです。

<!-- ![IMG_4514.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/8ca35ea2-190a-7920-e4ce-89ae0c3e1b2d.jpeg -->

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/b77148dc-a5f8-bea6-283d-677a0e0af34a.png)|
|---|
| ![IMG_5115.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798/b8d660fd-d829-65eb-a8a7-faa9a10d7994.jpeg) |

# 原因(推測)

どうやら、NVIDIA GPU を動かすドライバ nouveau がちゃんと動かないようです。無効にしてインストール後に改めて、NVIDIA 謹製ドライバを入れる必要があるみたい。権利関係でインストーラに公式ドライバが入れられないのではないかと。そういえば、NVIDIA が情報を出し渋ってるって話がありましたね。。

# 追加でやる事

boot パラメータを以下のように書き換えましょう。でないと多分、次の起動時に困る事になります。

- /etc/default/grub

```
#GRUB_CMDLINE_LINUX=""
GRUB_CMDLINE_LINUX="nomodeset"
```

- 反映はこのコマンドで。

```
% sudo update-grub
```

NVIDIA のドライバ追加はこちらが参考になると思います。

- Ubuntu 18.04 にNVIDIA公式グラフィックドライバを入れてみる 的な
  - http://sy07-sub.hatenablog.com/entry/2018/10/14/003750
 
# さいごに

自分は GTX980 入り PC に Ubuntu16 を、 RTX2080 の PC に Ubuntu18 をインストールする時に検索で一向に役に立つ情報が見つからず、数日潰れました… 神の声がなかったら一旦諦めてたと思う。

といいますかですね。

```
というのもログからはDRM(DirectRenderingManager)らしき文字が見えるので。
```

直接モニタみてる自分が読むの諦めたというのに、雑なツイッターのスクショからキーになる文字を読み取って教えてくれるなんて、優しすぎませんか。(*ノノ

# 参考

- GRUB2のインストール、設定の反映についてのメモ
  - http://nnnamani.hateblo.jp/entry/2014/11/13/000031|
Scalaを触ってみた

# introduction

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/357e4aaa-89c4-c547-e9e4-62fcab612cef.png)

Scalaについて学び始めたので備忘録として書いていきます。
開発環境はMacOS Mojave ver10.14.6です。



# Scalaのための環境構築fot Mac
### Javaのインストール　
こちらはもうわざわざ書く必要はないかもしれません。
適宜公式や必要なQiitaの記事をみて最新版をインストールしてください。

### sbtのインストール

MacOSの場合簡単に

```scala
brew install sbt
```
と入力するだけでインストールできます。

そして以下のコマンドでコンソールが出現します。
コンソールを立ち上げる際にはディレクトリを下げてから実行すると良いです。
コンソールを立ち上げた際にはtargetというディレクトリが出現するのでカレントを汚したくない人はディレクトリを下げることをお勧めします。

```scala
sbt console
```
終了したい時には

```scala
scala> :quit

```

と入力すればOKです。


# Scalaの基本

### Hello,World!

それではconsoleを起動してscalaが動くことを確認してみましょう。

```scala
println("Hello, World!")
>>>Hello, World!
```
printlnの書き方がJavaと似ていますね。
ScalaはJavaと同じく静的な型を持つ言語で、コードの実行時に型がチェックされる仕組みになっています。

### 変数の取り扱いについて注意

Scalaにも当然変数という概念がありますが、注意が必要なのはScalaの変数にはvalとvarの2種類があることです。

val:一度変数に値を格納したら変更不可能
var:(CやJavaの通常の変数のように)変更可能


Scalaでは基本的にvalのみでプログラミングします。
（ここも関数型っぽさがありますね。。）

```scala
val x = 3 * 2
>>>x: Int = 6
```

となります。Javaなどと異なっているのは変数の型を宣言していないことです。これは3*2の計算結果の型からコンパイラが自動でxの型を推論しているからです。

これを（ローカル）型推論と言います。
またvalを用いたことにより、他の型として扱うとエラーが出ることと、変数の変更（再代入）ができないことを確認してみます。

```scala
//新しい変数の宣言
var x = 3 * 3
>>>x: Int = 9

x = "Hello, World!"
>>>
<console>:8: error: type mismatch;
 found   : String("Hello, World!")
 required: Int
       x = "Hello, World!"
           ^

x = 3 * 4
>>>x: Int = 12

//変更できない変数の実験
val y = 3*2
>>>y: Int = 6


y = 3*3
>>>
<console>:12: error: reassignment to val
       y = 3*3
         ^

```


もちろんScalaで型を明示して宣言することもできます。

```scala
'val'もしくは'var' <変数名> : <型名> = <式>
//例
val x: Int = 3 * 3
```

このように結果がなります。
ここで　"=<式>"と書いているのがきになるかもしれませんが、これはScalaが関数型であるからです。基本的に関数型言語には式しかありません。

# Scalaの特徴について

### Scalaとは

「Scalaは2003年にスイス連邦工科大学ローザンヌ校（EPFL）のMartin Odersky教授によって開発されたプログラミング言語です。Scalaではオブジェクト指向と関数型プログラミングの両方を行えるところに特徴があります。また、処理系はJVM上で動作するため1、Java言語のライブラリのほとんどをシームレスに利用することができます。」

とのことです。

先にもみた通り、ScalaはJavaにも似ていますが関数型です。つまりオブジェクト志向likeであり、かつ関数型プログラミング言語であるサラブレッドのような言語らしいです。

### 関数型であるということ

Scalaという言語はオブジェクト指向の概念で関数型の機能を解釈し取り込んでいるそうです。それにより必要以上に言語仕様を肥大化させることなく関数型の機能を実現しています。 

また関数型言語の大事な特徴として式の評価に関する話題や、不変性・参照透過性・純粋性などの概念も理解していかなくてはなりません。（今回は大事なんだということを頭に入れて割愛します。）

### Javaとの互換性
「ScalaはJavaとの互換性を第一に考えられた言語です。Scalaの型やメソッド呼び出しはJavaと互換性があり、Javaのライブラリは普通にScalaから使うことができます。」

つまり既存のJavaライブラリを存分に使えるらしいです！
ありがたいです。


### 非同期プログラミング、並行・分散プログラミング
「Scalaでは非同期の計算を表現するFutureが標準ライブラリに含まれており、様々なライブラリで使われています。非同期プログラミングにより、スレッド数を超えるようなクライアントの大量同時のアクセスに対応することができます。」

流行りの並行・分散プログラミングにも対応している言語だそうです。



# おわり
以上がScalaのMacへのインストールと簡単なコマンドの実行 になります。通常のプログラミング言語と違った面も多くまだ慣れないです。

次回はコンパイルとInteliJのインストールと基本的な使用方法について勉強してみます。

# 参考
本文書は、CC BY-NC-SA 3.0

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304129/f90a6264-4296-625d-0883-f2fb978b7315.png)
の元で配布されています。


https://dwango.github.io/scala_text/
58日目 最新のお買い得情報をSlackに送信！

いつもチェックしているお買い物サイト。
ふと思いついてお買い得情報をゲットしてSlackに送るボットを作ってみました。

Slackへの投稿はこちらのQiitaを参考にしました。
`pip install slackweb`してimportするだけです。
###[Python3でslackに投稿する](https://qiita.com/shtnkgm/items/4f0e4dcbb9eb52fdf316)


```getBargain.py
#Javascript対応のためseleniumとchromedriver_binaryを使います。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary

#おなじみBeautifulSoup
from bs4 import BeautifulSoup

#slackに投稿するモジュール
import slackweb

#日付時刻をファイル名につけたかったので
import datetime
#ファイルの存在チェックに使う
import os
#URLと検索語を引数で渡す
import sys

#slack投稿用URL
slack = slackweb.Slack(url="https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxx")

#対象サイトのHTMLをダウンロード。使い回す。
def gethtml(url,filename):
	if not os.path.exists(filename):
		options = Options()
		browser = webdriver.Chrome(options=options)
		browser.get(url)
		html = browser.page_source
		with open(filename, mode = 'w') as fw:
					fw.write(html)
		browser.quit()
	
def getdata(key,filename):
	html = open(filename)
	soup = BeautifulSoup(html, "html.parser")
	div = soup.find_all(class_="Bargain")
	txt = ""
	for i in div:
		fd = i.a.string
		if key in fd:
			txt = i.find(class_="Bargain-priceoff").string+"\n"
			txt = txt + i.find(class_="Bargain-shopname").string+"\n"
			txt = txt + i.a.get('href')
			print(txt)
			slack.notify(text=txt)
		if txt == "":
			txt = key+" : 0件"
			slack.notify(text=txt)

args = sys.argv
key = args[1]
tag = args[2]
url = args[3]
filename = path + tag+datetime.datetime.today().strftime('%Y%m%d%H')+".html"
gethtml(url,filename)
getdata(key,filename)
```

できたファイルをcronで３時間ごとに呼び出します。

```
0 */3 * * * /<Path>/python /<Python>/getBargain.py "商品名" "タグ" "https://URL/" 1> /dev/null
```

これでお買い得をお見逃しなくゲットできそうです！