OmniAICreator/Qiita-1.07M huggingface dataset:
プログラミングを学ぶ方へ

この記事は、[ゆうとクラブ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/yuto-club)の25日目の記事です。

プログラミングを学ぶ方に向けて、私が大切だと考えるテーマを紹介します。

## 想定する読者
この記事は、次の読者を想定します。

* プログラミングを学ぶかどうか悩んでいる方
* プログラミングを学びはじめた方
* プログラミングの学習サイクルを知りたい方

## プログラミングの勧め
今日、コンピュータはあらゆる場面で応用され私たちの生活を豊かにしています。パソコンを持たない人でも、スマートフォン、家電、自動車など多くのものからその恩恵を受けています。

1989年にパロアルト研究所が、「社会や生活の至る所にコンピュータが存在し、環境にすっかり溶け込み消えてしまう」というユビキタスコンピューティングの概念を提唱しましたが、まさに2019年現在、ユビキタスコンピューティングの時代が到来しつつあります。

これからも世界中で、コンピュータの重要性は増す一方です。インターネット電話サービスSkypeを生み出したIT先進国エストニアでは、2012年にプログラミング教育推進プログラムが開始されました。日本においても2020年度から小学校プログラミング教育が全面実施されます。

未来の話としては、レイ・カーツワイルによって「人工知能の発展で2045年以降は人間の脳では予測不可能な未来が到来する」と予言さています。この予言は、シンギュラリティと呼ばれています。本当にシンギュラリティが到来するかどうかはわかりませんが、まさに我々人類は、いま大きな変革の最中にいると言えるでしょう。

変革の中では、過去に美徳とされた価値観が足枷になることもあります。プログラマの三大美徳は、「怠惰」「短気」「傲慢」とされています。一見すると悪いことのように思えるかもしれません。しかしこれらは、プログラマにとって重要な素質なのです。プログラマにとってもはや用済みとなった古い価値観は、切り捨てたほうが俊敏に行動できます。

インテルの創業者アンディ・グローブは、「シリコンバレーではパラノイア(偏執病・誇大妄想者)のみが生き残る」と語っています。プログラマは、10年後の当たり前をつくっていかないといけないのです。そのためには病的なまでの妄想力が必要となります。そして、その妄想を現実にするために我々プログラマはコードを書くのです。

## どんなサイクルで学習するか
マイケル・ロンバルドとロバート・アイチンガーは「人はおよそ70％を経験から学び、20％は観察学習や他者からのアドバイスによって学び、残りの10％は研修や書籍などから学ぶ」としています。プログラミング学習においても、この考えを体系化した経験学習モデルを採用できます。

経験学習モデルでは、次の4つの段階をサイクルとして定義しています。

1. 具体的経験 (Concrete Experience)
2. 内省的省察 (Reflective Observation)
3. 抽象的概念化 (Abstract Conceptualization)
4. 積極的実践 (Active Experimentation)

それぞれの段階でどんな手法・行動があるのか私のお気に入りを紹介します。

| 段階         | 手法・行動                                                 |
|--------------|-----------------------------------------------------------|
| 具体的経験   | ハンズオン、モブプログラミング、ペアプログラミング、写経                        |
| 内省的省察   | マイクロブログの活用、目をつむって考える              |
| 抽象的概念化 | 技術系記事の投稿、ドキュメント作成                        |
| 積極的実践   | OSSへのコントリビュート、ハッカソン     |

プログラミングを学ぶことに王道はありません。時代や状況に応じて手法・行動はアップデートされるべきです。しかし、どの手法・行動を選択するにせよ、フィードバックの受けやすさを重視することで学びを得る機会が増えます。したがって、プログラミング学習においてもコードを書くだけではなく自然言語を含むコミュニケーションを学習することが重要なのです。

## どんなテーマが大切か
プログラミングを学習する上で私が大切にしている三つのテーマを紹介します。

### 同じ哲学を共有し、強い絆で結ばれた集団に属す。
宗教によって戦争が起こるように、プログラミング界隈においても宗教的な派閥や対立が存在し議論が繰り広げられています。

下記は、その典型な例です。

* Vim VS Emacs
* 伽藍 VS バザール方式
* マイクロカーネル VS モノリシックカーネル
* オブジェクト指向 VS 関数型プログラミング
* 暗号通貨 VS 法定通貨

これらの議論は、終末のないフレーム論争です。こういった対立の中、どんなツール、思考法に重きを置き選択するかは、もはやプログラマの哲学とも呼べます。

これらの哲学について議論することも有意義ですが、一つの答えに辿りつくのは困難でしょう。しかし分かりあえた仲間がいればその結束は強いものです。

### 学習の金銭的コストを考慮する。
様々なソフトウェア・サービスを無償で利用できる現代ですが、今もなお、プログラミング学習には様々な金銭的コストがかかります。

* 書籍購入費
* ドメイン取得費
* サーバーレンタル費
* ソフトウェア購入費
* コンピュータや周辺機器の購入費
* 快適なインターネット回線

これらは学習のために絶対に必要とは限りませんが、経済的判断が原因で、学習の効率が制限されてしまうこともあります。効率的に学習できる環境を手にいれましょう。

### 矜持を持って社会に貢献する。
プログラミングという行為は、うまく使えば人々の生活を豊かにしてくれますが、倫理がペアであってこそであり、そうでなければ社会に悪い影響を与えてしまうことがあります。

逆に、技術の伴わない倫理のみが存在しても良い結果は得られません。倫理をもっていても重大なバグで社会に悪影響を与えてしまうこともあります。

したがって技術と倫理のペアを同時に学ぶことは大切な矜持です。そしてその矜持を持った上で、社会に貢献しましょう。

## 最後に
プログラミング学習においては、困難なことや苦痛に感じることも多々あると思います。これはプログラミングに限りませんが、どんなにクリエイティブな活動でも大半は退屈な作業なのです。それでも達成したときの嬉しさがあれば、きっと苦労は報われます。

みなさまがコンピュータとプログラミングを活用して少しでも理想の社会を実現できることを心から願っています。
Rails + Cloudinaryでレスポンシブ対応した画像表示

Railsでアップロードした画像のレスポンシブ表示（スマホ向けに縮小した画像表示）の実装は何が主流でしょうか？私の経験では「RMagickでスマホ向けの縮小画像を生成して表示する」くらいしかありませんでした。ですが、この方法だと複数のディスプレイサイズに細かく対応するのが大変だったり、スマホ・PCで画像を使い分けるのが面倒でした。
ここでは、Cloudinary(CDN + 画像変換サービス)を使って複数のディスプレイサイズに対応したサイズの画像を表示する方法紹介します。

# ゴール

最終的に表示するHTMLとしては、imageタグにsrcsetを設定して画像を表示します。[srcsetとは](https://parashuto.com/rriver/responsive-web/picture-srcset-use-case)

Imageタグとsrcsetの例：

```
    <img srcset="small.jpg 256w,
                 medium.jpg 512w,
                 large.jpg 1024w"
         src="medium.jpg"
         alt="It’s responsive!" />
```

# 実装

RailsからはCarrierWaveでCloudinaryに画像をアップロードします。
アップロードした画像はオリジナルのまま保存され、表示時にCloudinaryが画像を変換・キャッシュします。
この時に、`cloudinary gem` のヘルパーで `cl_image_tag` を使うことでsrcsetを設定することができます。

まずは、srcsetのブレイクポイントを設定します。
`config/initializers/cloudinary.rb`

```
# お好みで設定してください。
Cloudinary.config(srcset: {breakpoints: [576, 768, 992, 1200]})
```

次に view で imageタグをレンダリングします。
Hamlの例： `picture` がUploaderをマウントされてものです。

```
= cl_image_tag picture.full_public_id, alt: '画像', fetch_format: :auto, width: 512, height: 512, crop: :pad, class: 'img-fluid'
```

生成されるHTMLは以下のようになります。
設定する width / height と breakpoint の組み合わせで画像サイズと解像度を最適化することができます。

```
<img alt="画像" class="img-fluid" srcset="https://res.cloudinary.com/hogehoge/image/upload/c_pad,f_auto,h_640,w_640/c_scale,w_576/v1576802762/ajutulersxtryuy4g9ug 576w, 
https://res.cloudinary.com/hogehoge/image/upload/c_pad,f_auto,h_640,w_640/c_scale,w_768/v1576802762/ajutulersxtryuy4g9ug 768w, 
https://res.cloudinary.com/hogehoge/image/upload/c_pad,f_auto,h_640,w_640/c_scale,w_992/v1576802762/ajutulersxtryuy4g9ug 992w, 
https://res.cloudinary.com/hogehoge/image/upload/c_pad,f_auto,h_640,w_640/c_scale,w_1200/v1576802762/ajutulersxtryuy4g9ug 1200w" 
src="https://res.cloudinary.com/hogehoge/image/upload/c_pad,f_auto,h_640,w_640/v1576802762/ajutulersxtryuy4g9ug">
```

Cloudinaryの画像変換についての詳細はこちら。
https://cloudinary.com/blog/responsive_images_with_srcset_sizes_and_cloudinary

# 使い方はどこに？

cloudinaryの公式ドキュメントやGemのREADMEを見ても srcsetの使い方はないのでもしかしたら公式な使い方ではないのかもしれません。srcsetを使うテストは存在しているので動作は問題ないように思います。


# おわりに

Rails開発において、画像アップロードの保存場所はS3が人気だと思いますが個人的には、Cloudinaryを重宝しています。Cloudinaryはアップロード後にサイズやフォーマットなどの画像変換をすることができてとても便利です。ファイル数が少ないうちは無料で使えますし、Herokuだとaddonで導入するのも簡単なので、オススメです。
SQLのデータをtsvファイルとして出力する

## 環境

MySQL

## やりたいこと
SQLで出力されるこんな感じのデータを

```sql
> select id,name,memo from table where hoge = "fuga";
+----+--------------------------+-----------+
| id | name                     | memo      |
+----+--------------------------+-----------+
|  1 | test1                    | せやで     |
|  2 | test2                    | ほんま     |
|  3 | test3                    | かなわんなぁ |
|  4 | test4                    | がんばりや   |
|  5 | test5                    | なんでや    |
|  6 | test6                    | ねん       |
|  7 | test7                    | ほんま     |
+----+--------------------------+-----------+

```

こんな感じに出力して保存したい。

```bash
  id name    memo
  1  test1   せやで     
  2  test2   ほんま     
  3  test3   かなわんなぁ 
  4  test4   がんばりや   
  5  test5   なんでや    
  6  test6   ねん       
  7  test7   ほんま   
```

## コード

```bash
$ echo "<出力したいデータを出すためのSQL文>" | mysql -u root | tee <出力先ファイル名>
  id name    memo
  1  test1   せやで     
  2  test2   ほんま     
  3  test3   かなわんなぁ 
  4  test4   がんばりや   
  5  test5   なんでや    
  6  test6   ねん       
  7  test7   ほんま 

$ cat <出力先ファイル名>
  id name    memo
  1  test1   せやで     
  2  test2   ほんま     
  3  test3   かなわんなぁ 
  4  test4   がんばりや   
  5  test5   なんでや    
  6  test6   ねん       
  7  test7   ほんま 
```
Elixirの文字で遊ぶ

<img width="1280" alt="Advent Calnder.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540555/560bf0aa-ed4f-fb3c-0c4b-044bdfc8dceb.png">

雰囲気でエンジニアやっています。

トリなんですが昨日熱を出して最高なイブを過ごし、更にクリスマスであることすら忘れていたので、今サンタさんもびっくりなくらい大慌てなわけです。
ってなわけで何番煎じかわからないけど、Elixirの不思議（？）な文字の世界で遊びます。

# 彼女（妄想）からL○NE来た

```bash
77 101 114 114 121 67 104 114 105 115 116 109 97 115
```

Elixirって時点で勘のいい人はすぐに何が書いてあるかわかりますね。
こんなL○NEを送ってくれるバイナリアンな彼女がいたら嬉しいですね。

わからなかったらElixirをインスコしてReplを起動して、可愛い彼女のために何が書いてあるか読み解きましょう。

```bash
$ iex
Erlang/OTP 22 [erts-10.6.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe] [dtrace]

Interactive Elixir (1.9.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> <<77, 101, 114, 114, 121, 67, 104, 114, 105, 115, 116, 109, 97, 115>>
"MerryChristmas"
```

素敵なメッセージ！

# `<<>>` でバイナリの世界へ簡単にダイブ

大体どのプログラミング言語でもある、Fileを読んだりするやつを見てみます。

```elixir
File.read("hoge.wav")
# {:ok,
# <<82, 73, 70, 70, 252, 94, 66, 2, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0,
#   0, 1, 0, 2, 0, 68, 172, 0, 0, 16, 177, 2, 0, 4, 0, 16, 0, 100, 97, 116, 97,
#   236, 93, 66, 2, 0, 0, 0, 0, ...>>}
```

ここでWaveファイルをせっかく読んだのでちらっとヘッダを覗いてみます。Waveファイルの構造については別途参照ください。

```elixir
defmodule Wave do
  def parse(file) do
    File.read(file)
    |> header()
  end

  def header({:error, _}), do: {:error, "読み込み失敗"}
  def header({:ok, body}) do
    <<riff :: binary-size(4), size :: unsigned-size(32), wave_header :: binary-size(4), fmt_chunk :: binary-size(4), rest :: binary>> = body
    IO.inspect riff
    IO.inspect size
    IO.inspect wave_header
    IO.inspect fmt_chunk
    IO.inspect rest
  end
end
```

適当なWaveファイルを読ませてみます。

```bash
$ iex -S mix
iex(1)> Wave.parse("hoge.wav")
"RIFF"
4234035714
"WAVE"
"fmt "
<<16, 0, 0, 0, 1, 0, 2, 0, 68, 172, 0, 0, 16, 177, 2, 0, 4, 0, 16, 0, 100, 97,
  116, 97, 236, 93, 66, 2, 0, 0, 0, 0, 0, 0, 255, 255, 1, 0, 2, 0, 254, 255,
  253, 255, 3, 0, 4, 0, 252, 255, ...>>
```

パターンマッチ最高。

# 文字もバイナリ

なんです。

```elixir
"a" <> "b" # "ab"
"a" <> <<0>> # <<97, 0>>
match? "a", <<97>> # true
```

結局その数字は何かってASCIIなんですね。
まぁこの辺はElixirのチュートリアルでも書いてあることですね。

# もっと分解してみる

先程の彼女からのメッセージの頭文字 "M" でちょっと深堀りします。
`"M" <> <<0>>` が `<<77, 0>>` なので `<<77>> == "M"` ですね(`?M`だけでも調べられます)。
`77` は２進数で `1001101` ですね。これをElixir的に書くと

```elixir
<<0::1, 1::1, 0::1, 0::1, 1::1, 1::1, 0::1, 1::1>>
```

ということは

```bash
$ iex -S mix
iex(1)> <<0::1, 1::1, 0::1, 0::1, 1::1, 1::1, 0::1, 1::1>>
"M"
iex(2)> match? "M", <<0::1, 1::1, 0::1, 0::1, 1::1, 1::1, 0::1, 1::1>>
true
```

これだけ見るとわけがわかりませんね。

# まとめ

普段はあまり触れない0/1の世界へ、意外と手軽に入っていける面白さがElixirにはあるなぁと思います。
フワッと理解していたbitとかの単位についてがクリアになるなぁと。
あとElixirのパターンマッチのおかげでこの手のコードは短く書けると思います。
前前前職ではElixirを使って結構バイナリいじって楽しんでました。そのときに作ったライブラリがいくつか公開していたはず……

意外と話が広がらなくて困りましたが、とりあえずメリークリスマス。
みなさんアドベントカレンダお疲れさまでした。
2019年の3Dセンサを振り返る

基本的にTwitterベースになりますが、2019年に起きた3Dセンサ界隈のニュースをまとめてみたいと思います。

# Azure Kinect
今年の7月にマイクロソフトからデベロッパー向けのkinectの発売が開始されました。日本ではまだ発売されてませんが、海外から取り寄せられるみたいです。

![azurekinect](https://techcrunchjp.files.wordpress.com/2019/07/2019-07-12-kinect-2019-07-11_1114.png)

# Canon Vision Edition-U
[FA技術アドベントカレンダー](https://qiita.com/neka-nat@github/items/aeebcef10a6d62ba06b0)でも取り上げさせてもらいましたが、Canonが協働ロボット用の3Dセンサの発売を開始しました。
ユニバーサルロボットという世界で最も売れている協働ロボットと組み合わせて使用することができます。

![canon](https://robotstart.info/wp-content/uploads/2019/08/canon-ur-01.jpg)

# ZED2
STEREOLABSからZED2が発売されました。深層学習を使ったステレオによる3次元計測を行っているようです。

![zed2](https://cdn.stereolabs.com/assets/images/zed-2/zed-2-front.jpg)

# パイオニア 3D-LiDARセンサー
こちらはパイオニアからCESで発表された3D-LiDARです。2020年の秋ごろから発売開始するそうです。

![パイオニア](https://response.jp/imgs/thumb_h2/1487466.jpg)

# Pixel4
最近増えてきていますが、Googleが開発した3D認識できるスマホということで取り上げてみました。
顔認識や空間ジェスチャに3D認識を使用しているそうです。

![pixel4](https://mobilelaby.com/wp/wp-content/uploads/slider106/pixel-4-render-white.jpeg)

# CIS ToFカメラセンサROSパッケージ
ROS界隈もウォッチをしているのですが、CISが販売しているToFカメラがROSから簡単に使えるパッケージが公開されました。国産のセンサ・国産のROSパッケージということで取り上げてみました。

![cis](https://raw.githubusercontent.com/tork-a/cis_camera/master/doc/images/cis-tof-camera_dcc-rgbd1.jpg)

# iPad Pro
発売は来年になりますが、Appleも時期iPadに3Dセンサの搭載を予定しているようです。

![ipad](https://assets.media-platform.com/gizmodo/dist/images/2019/11/14/191114_ipad_pro-w1280.jpg)

# RealSense LiDAR L515
インテルからLiDARタイプの新型のデプスカメラが発売されることが発表されました。プレオーダが開始されており発注した人には4月に届くそうです。

![realsense](https://www.moguravr.com/wp-content/uploads/2019/12/201912131230906000.jpg)

# オムロン ロボットハンド搭載型3Dセンサー
こちらも発売は2020年の予定ですが、ロボットハンドに搭載できる小型軽量タイプの3Dセンサがオムロンから発表されました。産業ロボット界隈では位相シフト方式を用いた3Dセンサが多かったのですが、認識に時間がかかるのが問題でした。
こちらは約0.5秒で物体認識が可能だそうです。

![オムロン](https://s3-ap-northeast-1.amazonaws.com/iotnews-media/images/20191111210724/35.jpg)

# ケーブル認識に特化したロボット用3Dビジョンセンサ
クラボウから販売されているケーブル認識に特化した3Dビジョンセンサです。
ケーブルのような柔軟物は産業ロボットでは扱いにくい物体の1つとして自動化が進まない領域でした。ケーブルを正確に認識することで、ケーブルのハンドリングを可能にしました。

![cable](https://image.itmedia.co.jp/mn/articles/1912/25/kmishima_irex_kurabo1_w590.jpg)

# Structure Sensor (MARK II)
iPadに取り付けられる3DセンサであるStructure Sensorの新型が発売されました。6年ぶりの更新で、前回より小型化、広視野角、精度向上が行われているようです。

![mark2](https://3d-modely.com/blog/wp-content/uploads/2019/08/image1-2-660x400.jpg)

# MultiVu
深層学習によって単眼のカメラから3次元データを取る技術を開発しているMuliVuが700万ドルのシードラウンドを発表しました。単眼での3次元認識によって、従来のセンサと比べ小型化・安価になることが期待されています。

![multivu](https://techcrunchjp.files.wordpress.com/2019/05/gettyimages-1149242342.jpg)

# パイオニアとキャノン
パイオニアとキャノンがLiDARの共同開発を行うことが発表されました。

![cp](https://response.jp/imgs/thumb_h2/1409263.jpg)

# まとめ
他にも様々なニュースがあったかと思いますが、2019年も多くの3次元センサが発売・発表されました。来年も引き続きウォッチしていきたいと思います。
Go lang でファイルパスの最後のみ取得する

Go lang で、ファイルパスの最後のみを返すメソッドないかなと思って調査した。`filepath.Base` がそれで、パスの最後の要素を返す関数。

```golang
// Base returns the last element of path.
// Trailing path separators are removed before extracting the last element.
// If the path is empty, Base returns ".".
// If the path consists entirely of separators, Base returns a single separator.
func Base(path string) string {
```

良さげだが、両方のパスで動作するか確かめてみる。Windows の環境で、Windows ベースのファイル区切り文字と、Linuxベースの両方を試してみる。

## Linux ベース on Windows

```golang
package main

import (
	"fmt"
	"path/filepath"
)

func main() {
	path := "/some/path/to/foo.txt"
	file := filepath.Base(path)
	fmt.Println(file)
}
```

### 実行結果

```bash
$ go run main.go
foo.txt
```

## Windows ベース on Windows

```golang
package main

import (
	"fmt"
	"path/filepath"
)

func main() {
	path := "C:\\Users\\tsushi\\Downloads\\stress-testing\\terraform"
	file := filepath.Base(path)
	fmt.Println(file)
}
```

### 実行結果

```bash
$ go run main.go
terraform
```

どちらでも無事動きそう。
Webページのスクリーンショットをとる。Macショートカット,Chromeデベロッパーツール(拡張機能なし)

よく質問されるので「ここ見てね」的なものとして作成。

# 対象環境
* Mac
* Google Chrome

※外部ツールやブラウザの拡張機能をなど利用せず、OSやブラウザの標準機能を利用する。

# ■お気軽にキャプチャをとる
Macにて、選択した範囲のキャプチャをとるショートカット。
ショートカットなので、サクサクとることができる。

## 選択範囲の画像をデスクトップに出力する
```shift + command + 5```
or
```shift + command + 4```

## 選択範囲の画像をクリップボードに出力する
```shift + control + command + 4```
※これは地味に便利。

## その他ショートカットいろいろ
[Mac でスクリーンショットを撮る方法(本家)](https://support.apple.com/ja-jp/HT201361)

# ■さまざまなパターンのキャプチャをとる
Google Chromeのデベロッパーツールを利用したキャプチャのとりかた。

## キャプチャをとる
Google Chromeを開き、キャプチャをとりたいページを開く。
その画面上で右クリック押下し、メニュー内の「検証」を押下。
それにより、デベロッパーツールが起動する。
![img-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/7f81dbdb-2d1f-4479-72eb-2c8b1e3bfd60.png)

赤枠のボタンを押下。
![img-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/8a95ab18-2f98-e5d0-bbab-2dfad3100891.png)

表示したいデバイスを選択する。
![img-3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/1489ef05-ea2e-e75d-e897-f38506b1b06c.png)

表示可能なデバイスはいろいろある。お好みで。
![img-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/2f3515d1-3df5-6062-4f58-0595177a2683.png)
![img-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/ec2a8735-d28f-f2b8-bcd0-f8daedd5ffa7.png)

右上のボタン押下でメニューが表示される。
![img-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/a1ceb495-a334-992d-db0c-037e0ee382ff.png)

「Capture screenshot」押下で画面に表示されている領域のみ、キャプチャをとることができる。
![img-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/2658415e-fbe1-95f3-a633-2c070b9a2419.png)
<img width="375" alt="img-4-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/f8892484-e464-14ce-2392-e5b1845c3fbd.png">

「Capture full size screenshot」押下で、ページ全体のキャプチャをとることができる。
※画像は割愛

## いろいろできる
### デバイスフレームを表示する
「Show device frame」を押下すると、デバイスのフレームを表示することができる。
このままキャプチャをとれば、フレームも一緒に出力することができる。
![img-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/df06ef76-8aa3-d22c-a079-acdee5d8144c.png)

こんなかんじ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/7a73b2f6-b6d6-a7a3-90bc-81dedf433ca9.png)

### 表示の向きを横にする
赤枠のボタンを押下することで、表示を横にすることが可能。
![img-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269537/aa31cd9e-ebb9-4920-4053-6508a1a59b7e.png)

# まとめ
キャプチャのとりかたはいろいろあるので、お好みでいろいろと試してみるといいかも。
SQLでカラム名からテーブル名を割り出す方法

## 環境
MySQL

## やりたいこと
カラムからどこのテーブルにあるのか知りたい。

## コード

```sql
> SELECT table_name, column_name FROM information_schema.columns WHERE column_name = "<カラム名>";
```

## 解説
information_shema.columns というテーブルに、カラムに関する情報が詰まっているので、そこから逆引きをする。

興味がある人は「show columns from information_schema.columns」とかで中身を見てみると面白いですよ!!

## 最後に

私はよく使うので、Clipyのスニペットに登録しています。

option + s で、SQLでよく使う系のやつをまとめて登録してます^^
Flutterで広告マネタイズしたい

アプリをリリースするだけではなく、マネタイズもしたいですよね？？？
弊社ではFlutterで作ったアプリでマネタイズをしているので使ってきたプラグインや使い心地を紹介出来たらな〜と思います。

Flutterで広告を出そうとしたことがある方はわかるかもしれませんが、出すだけなら難しくないです。
ですが、好きな位置に出したり、いい感じにコントロールすることは手間がかかります。

#広告用プラグイン
pub.dev で admob や ad で検索したら色々と出てきますが、今回は使ったことがあるプラグイン３つを紹介させていただきます。

[firebase_admob](https://pub.dev/packages/firebase_admob)
FlutterFireリポジトリ内にあり、Flutter で広告を出したい人が一度は使うであろうプラグイン。
PlatformView　で実装されていないので Flutter の Widget の前に出てきて Widget を覆い隠してしまいます。
さらに表示位置も基本的には上か下かしか選べません。
Android で戻るボタンを押した時に広告が消えないで残ることがありますが、上部か下部に固定して表示するなら問題ないと思います。

[admob_flutter](https://pub.dev/packages/admob_flutter)
PlatformView で実装されているプラグインです。
数ヶ月前までメンテナーを探していてあまり更新がされていませんでしたが最近は更新されてきています。
firebase_admob　と迷いましたが選考段階ではメンテナンスがされていなかったので使用するのをやめました。
先日 1.0.0-beta が出てきたので今後のリリースに注目です。
Widget として広告を扱いたい場合には選択しても良いのでは？？

[flutter_google_ad_manager](https://pub.dev/packages/flutter_google_ad_manager)
[@ko2icさん](https://qiita.com/ko2ic)が作ってくださったプラグイン
admob_flutter と同じく PlatformView で実装されており、Widget として扱うことが出来ます。
動画リワードで動画再生時や動画終了時のEventListenerなどもあり、上記２つのプラグインより動画リワードを使用する場合は使いやすくなっています。
バナーも問題なく使用できます

弊社では、前々から使用していた`firebase_admob`と動画リワードの扱いやすさで`flutter_google_ad_manager`を場所に応じて使い分けています。
`flutter_google_ad_manager`に統一して良いと思っているのですが、書き換えるほどのものでもないので残しています。

#flutter_google_ad_managerで動画リワードを実装してみる

特に難しいことは無いです。
issuesにもあるように`onVideoCompleted`がiosで動かないことがあるので、少し変わった使い方をしています。

```dart
DFPRewardedAd _rewardedAd;

@override
void initState() {
  super.initState();
  _rewardedAd = DFPRewardedAd(
    isDevelop: false,
    adUnitId: adUnitId,
    onAdClosed:  {
      print('onAdClosed');
    },
    onAdLoaded:  {
      print('onAdLoaded');
    },
    onAdFailedToLoad: (int code) async {
      /// code: 0
      /// ERROR_CODE_INTERNAL_ERROR（アドネットワーク側のエラー）
      /// code: 1
      /// ERROR_CODE_INVALID_REQUEST（設定間違い）
      /// code: 2
      /// ERROR_CODE_NETWORK_ERROR（ネットワークエラー）
      /// code: 3
      /// ERROR_CODE_NO_FILL（リクエストは成功しているが、広告の表示ができない）
      print('onAdFailedToLoad(${code})');
    },
    onVideoCompleted: (int code) async {
       print('onVideoCompleted');
    },
    onRewarded: (String item, int amount) {
      // iosの特定バージョンで動作しないので`onVideoCompleted`で動画視聴完了フラグを立てる
      print('onRewarded');
    }
  );
  _rewardedAd.load();
}


Future<void> showRewardAd() async {
  try {
    await _rewardedAd.show();
  } on PlatformException catch (err)  {
    // 動画リワードが読み込めていないので再度読み込み
    if (err.message == 'not_loaded_yet') {
      await _rewardedAd.load();
    }
  }
}
```

#おわりに
`firebase_admob`と`flutter_google_ad_manager`を使っていると書いていますが、google ad managerのコンソールでの対応に限界が来たので カスタムイベントを追加したプラグインを開発しています。
SDKをバンドルしているので使用しているものを公開することは出来ませんが、SDKとカスタムイベントを外した分か、作り方をまとめたもののどちらかは公開したいと思います。


弊社ではFlutter エンジニアを募集しています。
ご興味がある方は下記のリンクからコーポレートサイトと募集要項など見てみてください。
[Flutterエンジニア(コーポレートサイト)](https://www.torico-corp.com/recruit/job/25/)
Qiitaの記事、消しませんか？日本人エンジニアの幸せのために

ポエムです。

## 要約

Qiitaの機能で、「これは1年前以上に書かれた記事です」って表示されているものの、とはいえ大丈夫だろうとそのまま動かしてみてどっぷりハマったという経験を誰しもお持ち（正月前だからか**お餅**って変換された！ｗ）だと思います。その他にも、習得したてで書いたけど今あらためて見返すと未熟！、とかいろいろあると思います。いいねの数は増えるかもしれないけど、検索でその記事を見つけてしまって不幸な人を増やしてしまっているかもしれません。Advent calendarで記事が増えきった後の年末大掃除、皆さん自分の記事を整理してみませんか？？

## 技術別地雷化年数

独断と偏見の、これより古い年数の記事は危険！目安

- R言語: 3〜10年（これが常識だと思ってた、、）
- JavaScript: 0.x〜、、、 

って書いていこうかと思ったのですが論争になると面倒なので省略

## 自分は以下の記事を消しました

酔った勢いで以下の記事は消去しました。

- Shinyapps.ioからAWS S3とファイルをやり取りする(標準化したので)
- GitpodでHTMLのサーバー経由previewを行う（機能アップで解消されたので）
- クラウドIDEでionic開発環境を構築してみよう（すぐできるじゃん、、）
- JINS MEME で首を大きく振った時に反応するアルゴリズム(R版)（JS版のほうが有用なので）
Laravel で使うデータベースの設定

# Laravelでデーターベースを使うための準備

最近Laravelを使ったWebサービスの開発に携わることになりました。
学習を始めたばかりなので、まとめがてらQiitaに書いていこうと思います。

今回は自分がLaravelを学習している過程で学んだデータベースを使うときの設定方法についてまとめました。

## 設定ファイルをいじる

これから扱うファイルは`config/database.php`と`.env`(隠しファイル)の2つである。
`.env`は 開発環境と本番環境で使い分けるのでgitの管理下に置くべきでないファイルである。

Laravelで使用するDBの情報は`config/database.php`で設定されている。
以下はそのファイルの一部である。今回はMySQLについて扱うので、それ以外の部分を省略して表示している。

```php:config/database.php
<?php

return [
  'default' => env('DB_CONNECTION', 'mysql'),

  'connections' => [

        'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ], 

   # 〜以下省略〜
];
```

大半の項目は `env()` というヘルパ関数によって .envファイルから値を読み込んでいる。
ヘルパ関数はLaravelで定義されている関数のことである。
`env(A,B)`は.envファイルないの`A`という環境変数を参照し、もしそれが存在しなかったら`B`を返す。したがって以下の場合であれば、.envファイルの環境変数`DB_CONNECTION`を参照し、それが存在しなければ`mysql`をデフォルトのデータベースとして用いる。

```php
    'default' => env('DB_CONNECTION', 'mysql'),
```

Laravelがデフォルトで生成した`.env`ではDBに関する環境変数は下記のようになっているはずだ。

```:.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
```

MySQL以外のDBを使う場合は`DB_CONNECTION`を適切なものに書き換える必要がある。
他の`DB_DATABASE`、`DB_USERNAME`、`DB_PASSWORD`あたりも適宜書き換える。

## ローカルのデータベース接続がうまくいかない時

自分はLaravelを初めてやるときにDBの接続がうまくいかなかったのですが、以下のようにしたらうまくいったのでメモ。

### mysql.sockファイルを探す

ターミナルなどで以下を実行する

```terminal
$ mysql_config --socket
/tmp/mysql.sock
```
この場合`/tmp/mysql.sock`に mysql.sockがあるらしい。もしmysql.sockがなかったら自分で生成すればいいらしい。

### .envに環境変数を追加する

`DB_PASSWORD`の下あたりに以下の一行を追加しておく。

```:.env
DB_SOCKET=/tmp/mysql.sock
```
自分の場合はこれでDBにうまく接続することができた。

## 参考にした記事

* [Laravelのenv関数とは](https://qiita.com/t_kanno/items/c110bb4e3363e2ee5fdc)
* [入門者のためのLaravel .envファイルの基礎と理解](https://reffect.co.jp/laravel/env-file-basic-understanding)
* [MySQL mysql.socketがどこにあるか探したい。](https://chaika.hatenablog.com/entry/2019/01/17/160000)
BitVisorでAMD-Vi(IOMMU)隠蔽(失敗)

BitVisorにはIntel VT-dの隠蔽機能(ACPI DMARテーブルを潰すだけの簡単なもの、CONFIG_DISABLE_VTD)はあるのですが、AMD-Viの隠蔽機能がありません。それをやってみたら失敗した話です。

# 環境

* ASUS B350M-A
* AMD Ryzen 7 2700
* Debian GNU/Linux 10

# IOMMUデバイスを隠蔽してみる

AMD-Viでは、PCIデバイスとして以下のようにIOMMUのデバイスが見えています。

```shell
# lspci -nnv -s 00:00.2  
00:00.2 IOMMU [0806]: Advanced Micro Devices, Inc. [AMD] Family 17h (Models 00h-0fh) I/O Memory Management Unit [1022:1451]
        Subsystem: ASUSTeK Computer Inc. Family 17h (Models 00h-0fh) I/O Memory Management Unit [1043:8747]
        Flags: fast devsel, IRQ 27
        Capabilities: [40] Secure device <?>
        Capabilities: [64] MSI: Enable+ Count=1/4 Maskable- 64bit+
        Capabilities: [74] HyperTransport: MSI Mapping Enable+ Fixed+

```

これをBitVisorで隠蔽してしまえば、ゲストオペレーティングシステムから見えなくなるのではないかと思ったわけです。そこで以下のような設定で試しました:

```
vmm.driver.pci=class=0806, driver=conceal
```

その結果、GNU GRUBまでは動いていましたが、Linuxは起動しませんでした。

# ACPI IVRSテーブルを隠蔽してみる

AMD-Viでも、ACPIにも関連するテーブル、IVRSがあります。DMARと同様に、IVRSを消してしまえばいいのではないかと思ったわけです。そこで以下のような修正で試しました:

```diff
diff --git a/core/acpi.c b/core/acpi.c
--- a/core/acpi.c
+++ b/core/acpi.c
@@ -981,6 +981,13 @@ acpi_init_global (void)
        }
        pm1a_cnt_found = true;
        save_mcfg ();
+       {
+         char*p=find_entry("IVRS");
+         if(p){
+           printf("Found IVRS %p\n",p);
+           memset(p,0,4);
+         }
+       }
 }
 
 INITFUNC ("global3", acpi_init_global);
```

その結果... 上述のIOMMUデバイス隠蔽をしていた場合はLinuxが起動しないのは変わらず、隠蔽していなかった場合は、ゲストオペレーティングシステムが起動すると、 **なぜかIVRSテーブルが復活している** という結果でした。

# まとめ

結局うまくいっていないのですが、幸いUEFI Setup/BIOS Setup画面から、AMD-Vi(IOMMU)を無効にすることはできますので、BitVisorを試す場合はとりあえずはそれでいくことになります。まぁ、Intelでもその点は同様なんですが、Macのようにそのようなオプションがないコンピューターもありますので、CONFIG_DISABLE_VTDは引き続き役に立ちます。
AZ-900:Microsoft Azure Fundamentalsの対策

本記事はAzure Advent Calendar 2019の25日目の記事になります。


#はじめに
AZ-900:Microsoft Azure Fundamentalsを受けるにあたり対策方法を探したのですが
書籍や記事が少なかったため、これから受ける方の参考になれば良いと思い書き残します。

#AZ-900:Microsoft Azure Fundamentalsとは？
Microsoft Azureが出している試験の中で一番初心者向けの入門試験です。
Azureサービスの知識だけというよりは、Azureの各サービス＆クラウドの概念を
広く浅く学べる資格です。
AWSなら[クラウドプラクティショナー](https://aws.amazon.com/jp/certification/certified-cloud-practitioner/)、GCPなら[Associate Cloud Engineer](https://cloud.google.com/certification/cloud-engineer?hl=ja)が
同じ位置づけの資格になります。
※なおAZ-900の受験料は2019年12月25日時点で13500円です。

#試験の概要/申し込み方法

問題数：44問
時間：90分
合格点：700点/1000点
試験申し込み：https://www.microsoft.com/ja-jp/learning/exam-az-900.aspx
上記リンク(ピアソン)から申し込めます。
※Microsoftアカウントが必要なため注意。

**【試験範囲】**
Cloudの概念の理解 (15-20%)
コアな Azure サービスの理解 (30-35%)
セキュリティ、プライバシー、コンプライアンス、信用についての理解 (25-30%)
Azure の料金プランとサポートについての理解 (20-25%)

当たり前といえばそうですが、
やはりAzureサービスそのものとセキュリティ周りについての配分が多いですね。


#学習方法/教材
以下に学習に使えそうな情報を記載します。

**[①Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/paths/azure-fundamentals/)**
リンク先の**【Azureの基礎】**がモロに試験範囲のなので、
最低1周はした方が良いと思います。
1周に掛かる時間は10時間とありますが、1周読んでみた感想としては
実際はもっと短い時間で読めます。

**[②AZ-900 Microsoft Azure Fundamental対応 クラウド基礎講座](https://www.microsoftevents.com/profile/form/index.cfm?PKformID=0x7830243abcd)**
Microsoftが定期的に提供しているAZ900の基礎講座です。
AZ900の講座、問題集、試験のバウチャーなどもらえるのでかなりおススメです
（**もうこれだけで良いんじゃないかな**）
デメリットとしては平日のみ開催なのでスケジュールの調整が必要な点でしょうか。

**[③udemyの動画講座（英語）](https://www.udemy.com/course/silver-bullet-to-crack-az900-azure-fundamental-certification/)**
2019年12月現在では英語の講座のみあります。英語と聞いて拒否反応を出してしまう方も多いと思いますが、
グーグルの機械翻訳を使えば理解は出来るレベルの翻訳はしてくれるので
教材としては良いと思います（というかAZ900の場合教材といえるものがこれくらいしかない）
なお、よくセールやってるので1200円くらいの時に買いましょう。
※上記リンクは一例なので、Udemy内で"AZ-900"と検索すれば複数講座が出てきます



#終わりに
ここまで色々書いて来ましたが実は私自身は来月この資格を受ける予定です
なので具体的にどんな問題が出るのかは分からないのですが
合格したら、公開しても問題ないレベルで追記したいと思います。

ここまでの内容がこれから受ける方の参考になれば幸いです。

※追記
その後試験を受け無事に合格しました。
体感ですが、②の講座でいただいた問題集がかなり良く、実際の試験でも似た問題が
多数出題されていました。
※現在コロナの影響で講座がオンラインになっているので問題集は貰えないかもしれません。

※追記2
以下の書籍ですが後半にある問題集が実際の試験に沿った形で記載されているため、
問題集が手に入らない方はこちらで代用可能かと思います。
**[④合格対策Microsoft認定AZ-900:Microsoft Azure Fundamentalsテキスト＆問題集](https://www.amazon.co.jp/dp/B0872LVYD6/ref=cm_sw_r_tw_dp_x_OajCFbXWNYGQA)**
初心者によるプログラミング学習ログ 194日目

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

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

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

194日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>194日目<br><br>udemyでjquery<br>動画編集もやろうと思ったら寝落ちした<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアとつながりたい</a> <a href="https://twitter.com/hashtag/%E5%8B%95%E7%94%BB%E7%B7%A8%E9%9B%86?src=hash&amp;ref_src=twsrc%5Etfw">#動画編集</a><a href="https://twitter.com/hashtag/MovieHacks?src=hash&amp;ref_src=twsrc%5Etfw">#MovieHacks</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1209564227419009024?ref_src=twsrc%5Etfw">December 24, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
円を描く

小ネタ
#円の方程式
```math
x^2\times y^2 = 1\\
\therefore  y = \pm\sqrt{1 - x ^2}
```
#作ってみる。
```java:SPL
| makeresults count=2
| streamstats count
| eval x=if(count=1,-1.100,1.100) 
| makecontinuous span=0.001 x
| dedup x
| eval y = exact(sqrt(1 - pow(x,2)))
| eval y = if(abs(x) <= 1,y,NULL)
| eval yy = -y
| table x y yy
```
#解説
一旦作ってみたら−１と１のところの線が切れ気味だったので余白を作成。
`dedup`が入っているのは、なぜか**x**が重複したため。なんでだろう :thinking: 
精度が大事ということで`exact()`は必要です。
#表示
```xml:circle
<dashboard>
  <label>circle</label>
  <row>
    <panel depends="$alwaysHideCSS$">
      <html>
         <style>
           #chartPanel{
             width:500px !important;
           }
         </style>
       </html>
    </panel>
  </row>
  <row>
    <panel id="chartPanel">
      <chart>
        <search>
          <query>| makeresults count=2
| streamstats count
| eval x=if(count=1,-1.100,1.100) 
| makecontinuous span=0.001 x
| dedup x
| eval y = exact(sqrt(1 - pow(x,2)))
| eval y = if(abs(x) &lt;= 1,y,NULL)
| eval yy = -y
| table x y yy</query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
          <sampleRatio>1</sampleRatio>
        </search>
        <option name="charting.chart">line</option>
        <option name="charting.legend.placement">none</option>
        <option name="charting.fieldColors">{y:#000000, yy:#000000}</option>
        <option name="height">550</option>
      </chart>
    </panel>
  </row>
</dashboard>
```
サーチ画面で描画すると縦横の比率の問題できれいに見えないのでダッシュボードを作成。
縦はSimpleXMLにオプションがあるのに横はCSSを書かないといけないのが切ない。
##完成図
![qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130729/b4c33272-0fb5-0b64-df07-43c7781cb2b6.png)
#まとめ
結構きれいに描けるな〜
Splunkの使い方としては全力で別方向に向かってると思います。
最初方程式の展開をミスしていて、歪な形になったのは秘密です。:sweat:
Atomic Design：コンポーネントの分け方

イブがクリスマスの後にやって来ました。
アトラエアドベントカレンダー24日目の記事です

Atomic Designの話をしようと思います。
デザイナーの視点から、Atomic Designのコンポーネントのイメージしづらい部分をどう捉えるとよさそうかを書いて見ようと思います。

## 課題感：分子と有機体の境界線
私が最初に当たったのが「分子と有機体の境界線がわからない」ということでした。定義では理解しているつもりでも、実際にデザインする段階になるとイメージがしづらいポイントだと感じました。
複雑さや抽象的な目的は定義として曖昧です。実装までをイメージすると、明確な定義があったほうがデザインを詰める段階ではとくに重要になるはずです。

## コンポーネントの目的で分類してみる
そもそもAtomic Designはコンポーネント設計におけるフレームワークです。
各コンポーネントが何を目的として設計されているかを整理して考えてみます。

| Atomic Design | デザインの関心 | コンポーネントの進化のベクトル |
|:---|:---|:---|:---|
|原子|デザインのトンマナ | デザインの変更 / 機能の明瞭性 |
|分子| 行動を阻害しない機能を提供 | 機能の明瞭性 |
|有機体| 行動を促す独立したコンテンツ | ユーザー体験にあったコンテンツの見せ方 |
|テンプレート| ページのレイアウト（情報設計） | ユーザー体験にあったコンテンツの配置 |

こんな感じです。

## あらためて、関心の範囲から有機体というものを捉えてみる
そのコンポーネントがもつプロパティも「従業員のデータ」や「今日の友人の投稿」など、そのプロダクトの特性に強く依存する具体性の強いものになります。（内容適当です）
そのプロダクトが独自に持つデータ、つまりコンテンツに強く依存するコンポーネントは有機体です。
逆にコンテンツに依存してしまったコンポーネントは分子になりえません。それはコンテキストに強く依存するので、汎用化しづらいからです。

結局の所、Atomic Designでは何を目的にそのコンポーネントが集められたかが重要なのであって、それが共通化できるかどうかや複雑かどうかはあまり関係ないと考えたほうが、かえって齟齬がなくてわかりやすいかもしれません。

## デザインへのフィードバックに活かす
すこし余談かもしれませんが、上記の例がうまくいけばデザインのフィードバックもエンジニアと共通言語をもってコミュニケーションすることができるようになります。
Google広告スクリプトを使って自動でリスティング開始・停止させる

#背景
Webサイトの在庫状況が、「在庫なし」のときに自動でリスティングを停止させたい。
在庫なしのときにリスティングをしても無駄な出費となるため。

#大まかな仕組み
1. Google広告スクリプトを使って1時間ごとにWebサイトをスクレイピング
2. Webサイト上に「在庫なし」の文言が入っていた場合、リスティングを停止
3. 文言が入っていない場合はリスティングを開始

#実装方法
##1. Google広告にログインし、「ツールと設定」→一括操作の「スクリプト」をクリック
![スクリーンショット 2019-12-25 20.27.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118677/5b2a10ed-5cb9-0b90-7c80-4d7762de2d59.png)

##2. 青い+ボタンをクリックして新しいスクリプトを追加
![スクリーンショット 2019-12-25 20.27.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118677/0b7fd8d5-3ea7-7910-b182-605e75692cd1.png)

##3. 以下のコードをコピー
github上に上げています。
https://github.com/szkjp/AutoListingSwitcher/blob/master/code.js

##4. コピーしたコードを貼り付ける
・スクリプト名は適当でOK
・スクリプトの承認みたいな表示されている場合は、承認をクリックして承認しておく
![スクリーンショット 2019-12-25 20.47.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118677/adc3b36c-a720-52bf-fe16-4f14cbb8460b.png)

##5. 設定値を変更
最初の方の行の設定値（5行目〜15行目）を各々のWebサイトの設定にして保存

##6. プレビューして動作確認
問題無ければこんな感じのログになります。
ステータス（開始とか一時停止）に変更がある場合はメール通知が飛びます
![スクリーンショット-2019-12-25-20.53.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118677/753407eb-b946-b302-0160-a7798529703b.png)

##7. 問題無ければ定期実行させるようにして設定（1時間ごとなど）

#注意点
確実に動作するかは保証できません。
「在庫なし」などの文言は汎用的すぎて誤動作する可能性があるので、もう少し詳細な文言で設定することをおすすめします。
初めての独学Python①　

Python学習の備忘録です。
初めての方でもこの記事で学習ができるよう
編集していきます。

#Pythonって？
Pythonは読みやすさを重視して開発された
プログラミング言語です。
少ないコード量で簡単にプログラムを
書くことができます。


```python:hello.py
print("Hello World!")
```
\>>Hello World!

近年は人工知能やWeb開発など幅広い分野で
使われています。

下記のサイトに分かりやすくまとまっています。
[Samurai Blog](https://www.sejuku.net/blog/7720)

#コードを動かす
Pythonコードの実行はColaboratoryがおすすめ。
ColaboratoryはWebブラウザさえあれば
面倒なインストール作業なしでプログラミングが
出来るサービスです。

下記リンク先よりアクセス可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557030/67c43e89-1cb6-0370-cd2c-3b28c9c02ee3.png)
[Colaboratory](https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja#scrollTo=5fCEDCU_qrC0)

Colaboratoryにアクセスして左上の「＋コード」をクリックします。
そうするとコード入力画面のようなものが出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557030/c4e05fb8-6baf-dce2-cf18-c783d8d920ad.png)


実際にコード入力して左の再生マークか
Ctrl+Enterでプログラム実行することが可能です。
下に実行結果が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557030/46900df5-e5f4-8e4e-228e-ce08744de0e5.png)

この環境であればインストール作業なしで
手軽にプログラミング可能です。
しかもTesorFlowなどの人気のライブラリを
使うこともできます。

#for文
Hello World!を１０回出力します。

```python
#10回出力（コメントは＃で書きます）
for i in range(10):
    print("Hello World!")
```
\>>Hello World!
\>>Hello World!
\>>Hello World!
...

#キーワード
キーワードは特別な意味を持つ単語です。
コードを複数回実行するforもキーワードです。

下記のコードでどんな単語がキーワードなのかを調べることができます。

```python
import keyword
import pprint

pprint.pprint(keyword.kwlist, compact=True)
```
\>>['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue',
\>>'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global',
\>> 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise',
\>> 'return', 'try', 'while', 'with', 'yield']

参考
https://note.nkmk.me/python-keyword-reserved-word/

#条件文
if elif elseを条件文に使用します。

```python

food = "すし"
if food == "ラーメン":
    print("ラーメン食べたい")
elif food == "焼肉":
    print("焼肉食べたい")
else:
    print("すし食べたい")
```
\>>すし食べたい
VRChatUDONでHelloWorld

#この記事の目的と背景
VRC SDK3が発表され、VRChat上でUDONというノードベースプログラミングが扱えるようになった。
本記事はノンプログラマ(グラフィッカー)である筆者が、UDONの環境構築とHelloWorldを行ったので
実施した内容、詰まった所などの活動記録を兼ねる。

#環境構築
**[VRChat Udon (OPEN ALPHA) ことはじめ](https://qiita.com/amamagi/items/ac497db1b20cb754a1e6)**
を参考に

**unity2018.4.14f1**環境で以下のunitypackageをインポートした。
**VRCSDK3-2019.12.21.16.01.unitypackage**
**UDONSDK-2019.12.22.12.32_Public.unitypackage**

##バージョンに関する警告

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507319/3619361c-4ff7-e60b-3090-fc71ed0d552e.png)
また、(2019/12/25現在)上記環境下でUnity上のVRC SDKウインドウに
Wrong Unity version.Please use 2017.4.28f1などと表示されるが
筆者環境ではUnity 2017.4.28f1ではSDK3が動作しなかった。

#HelloWorld
構築したノードグラフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507319/e4be3a54-46c0-5939-cdcc-347e99761749.png)
プログラムはさっぱりわからないので、
とりあえず適当にHello!Mohya!という文字列を入れた変数newVariableをデバッグログに流した。
実行するとUnityConsole上でHello!Mohya!の文字が表示された。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507319/349ca547-5aad-6d3f-9f31-d38a6f4a4c3e.png)

#VRC SDK3で構築したワールドをVRChat上で開く方法

UDONを弄る事はできたので、VRChat上で動作確認をしてみたいと思ったが
SDK3で構築したワールドをLocal testingしようとすると、
VRChat上でワールドが開かれると同時に強制終了し、ホームに戻されてしまった。

色々と調べたが自力では答えに行きつけなかったので、
素直にtwitterの集合知に助けを求めることにした。
<blockquote class="twitter-tweet" lang="ja"><p>VRChat SDK3で作ったワールド（当たり判定のあるPlaneの床と、VRC WorldのPrefabだけ置いた最小構成）が、ローカルテストでワールド開いた直後に落ちるのですが、原因や対策ご存知の方はいらっしゃいますか？SDK2で同じことをやった場合、問題なくワールドを開けます。<a href="https://twitter.com/tukimi_negitoro/status/1209699241746145281">2019, 12月 25</a></p></blockquote>

<blockquote class="twitter-tweet" lang="ja"><p>VRCSDK3はまだVRChatのオープンベータ環境でしか使えないのでSteamからベータ環境へ変更する必要があると思います<a href="https://twitter.com/gatosyocora_vrc/status/1209700480294588417">2019, 12月 25</a></p></blockquote>

<blockquote class="twitter-tweet" lang="ja"><p>【参加方法】Steamで、VRChatの項目を右クリックして、プロパティーを開く。ベータタブでopen-betaを選択（なしに戻すことで通常版に戻せる）

ベータに参加してる人は通常版を起動してる人と同じインスタンスに入れないので、予めほかの人と連絡を取ってから一緒に入ることをお勧めします。<a href="https://twitter.com/bd_j/status/1139730197341560832">2019, 6月 15</a></p></blockquote>

結果、親切ながとーしょこらさんにVRChatをOpendetaに切り替える必要があることを教えてもらって、VRC SDK3環境で構築したワールドを開くことができた。

#VRChatのDebug log
とはいえ、上記Hello!WorldはあくまでUnityのDebug Logに流す事しかしていないため、VRChat上で動作確認ができるものではない。
VRChatにもDebug Logが存在するが、UnityのDebug Logとは別物なので、こちらにHello!Worldの文字列が流れてくることはない。
UDONのノードにもこちらのデバッグログに情報を流す為のものらしきものは、今回は見つける事が出来なかった。

また、OpenBetaでは通常版のVRChatのようにRightShift + ` +3で呼び出すことはできないようで、もしVRChatのデバッグログを確認したい場合には、とりあえずのところC:\users\(ユーザ名)\AppData\LocalLow\VRChat\vrchatのoutput_log_xx-xx-xx.txtから確認の必要があるようだ。

#参考記事
- [VRChat Udon (OPEN ALPHA) ことはじめ](https://qiita.com/amamagi/items/ac497db1b20cb754a1e6)
- [Programming in VRChat] (http://vrcprog.hatenablog.jp/entry/data-Log_file)
Microsoft Learn 25日目

12月は、毎日 Microsoft Learn を受講していこうという記録。
※受講後に書き込むので公開に間に合わないこと多々あります(アドベントカレンダーの意味ｗ)

12/25 は
Azure におけるセキュリティ、責任、信頼
- Azure Security Center からヒントを得る

を受講。以下、簡易メモ。

# Azure におけるセキュリティ、責任、信頼
## Azure Security Center からヒントを得る
Security Center は、Azure とオンプレミスの両方において、すべてのサービスに対して脅威からの保護を提供する監視サービス。Security Center には以下の機能がある。

* 構成、リソース、およびネットワークに基づいて、セキュリティに関する推奨事項を提供する。
* オンプレミスおよびクラウドのワークロード全体のセキュリティ設定を監視し、新しいサービスがオンラインになると必要なセキュリティを自動的に適用する。
* すべてのサービスを継続的に監視し、自動的なセキュリティ評価を実行して、潜在的脆弱性を、悪用される前に特定する。
* 機械学習を使用して、マルウェアが仮想マシンやサービスにインストールされる前に検出してブロックする。 また、許可されるアプリケーションの一覧を定義して、検証対象のアプリのみが確実に実行を許可されるようにすることもできる。
* 受信攻撃の可能性を分析および特定し、脅威および発生した可能性がある侵害後のアクティビティの調査を支援する。
* ポートに対する Just-In-Time アクセス制御を提供し、必要なトラフィックのみがネットワークで許可されるようにして、攻撃対象の領域を減らす。

### 使用できるレベル
Azure Security Center は 2 つのレベルで使用できる。

* Free：サブスクリプションの一部として使用できる。Azure リソースの評価と推奨のみに制限されている。
* Standard：継続的な監視、脅威の検出、ポートの Just-In-Time アクセス制御など、セキュリティ関連のサービス一式を提供している。

### 使用シナリオ

* インシデント対応に Security Center を使用する。
* Security Center の推奨事項を使用してセキュリティを強化する。
*
ExcelにおけるFill?フィル？を関数のみで表現


こんな感じの歯抜けのデータを
![2019-12-25_20h33_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51918/40b3886c-3f45-5f74-e585-83258b64f26b.png)


空白行は上の行をコピー

`=IF(INDIRECT("B"&ROW()),TEXT(INDIRECT("B"&ROW()),"YYYY/M/D") &" "& TEXT(INDIRECT("C"&ROW()),"hh:mm:ss"),INDIRECT("Z"&(ROW()-1)))`

![2019-12-25_20h35_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51918/5cef87f0-29a4-b5f2-2ba3-8bb01e137620.png)

日にちと時間を結合して分かりづらいので、C列とZ列で簡単に解説

```:Excel
//もし表示対象Cに値があればCを表示し、Cに値がなければ、出力行の一つ上の値を表示する
=IF(INDIRECT("C"&ROW()),INDIRECT("C"&ROW()) ,INDIRECT("Z"&(ROW()-1)))
```

ということです
SwiftUI Viewの動的サイズを取得するには（メモ）

#SwiftUIの動的に計算されているViewサイズの確認

##やりたいこと
デバッグ時など、以下のように領域いっぱいにサイズ指定をした場合に、どういう値になっているのかを取得するメモです。

``` swift
        Text("Hello")
            .frame(height:60)
            .frame(minWidth: 0, maxWidth: .infinity)
            .background(Color.red)
```

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59249/67ba2183-b039-6e3a-b2d4-7071737cb82f.png)|
|:-:|


##GeometryReaderをView要素のbackgroundに使う
ポイントは戻り値に空のTextなど描画対象となるViewを指定することのようで、EmptyViewなどではだめでした。

``` swift
            .background(GeometryReader{ geometry -> Text in
                print("******", geometry.size)
                return Text("")
            })
```

##実装例
``` swift
        Text("Hello")
            .frame(height:60)
            .frame(minWidth: 0, maxWidth: .infinity)
            .background(Color.red)
            //追加
            .background(GeometryReader{ geometry -> Text in
                print("******", geometry.size)
                return Text("")
            })
```

``` swift:実行結果
****** (375.0, 60.0)  //Portraitモード
****** (724.0, 60.0)  //Landscapeモード
```

##Viewのframe全体を確認

GeometryReaderを用いてViewのframeを取得する場合には、.globalと.localで値を取ることができます。（UIViewのframeとboundsの違いのようで、親からの相対位置を取るなら.global）

``` swift
            .background(GeometryReader{ geometry -> Text in
                // size → frame
                print("******",geometry.frame(in: .global))
                return Text("")
            })
```

``` swift:実行結果
****** (0.0, 381.0, 375.0, 60.0)   //Portraitモード
****** (44.0, 147.0, 724.0, 60.0)  //Landscapeモード
```

SwiftUIはStoryboardを使っていた頃のAutolayout設定と比べて非常にシンプルに書けるのがありがたいですが、レイアウトが自動調整されたときにどういう値になっているのか想定と違う時があるので確認重要です。
Raspberry Pi 4 のセットアップに関する備忘録

###はじめに
raspberry pi 4　を初心者がネット情報をもとにOSなどをインストールした。
その時の　躓きや気づいたことを備忘録として残すことにした。
（2019/12/20時点の情報です。）

###対象
raspberry pi 4も使いたいと思っている初心者。
インターネットが使える環境でPCをすでに１台所有している。
###Raspberry pi 4 のセットアップまでの流れ
情報収集ー＞予算を決めて必要なものを見積もるー＞発注する
ー＞届いたものを確認ー＞公式ホームページの情報をまず確認（重要）
ー＞microSDCardにOSをインストール（PCとインターネット環境が必要）
　　初期設定、追加ソフトが必要であればインストールする
ー＞microSDCardのバックアップをとる。
####情報収集
ヒートシンク、ファンをつけたほうがよい。
電源ケーブルは　スイッチのついたものが便利
microSDの最大容量は公式ホームページでは３２GB
microSDはバックアップを取っておいたほうがよい。
####購入したもの
pi4本体
ケース（外付けファン、ヒートシンク付き）
電源ケーブル（スイッチのついたもの）
モニター変換ケーブル２本、
microSD->USBアダプター
公式のカメラモジュール、
microSD(32GB,128GB)
###RaspbianOSのインストール
32GBのmicroSD：公式サイトの手順にしたがってFormat、
Noobsを公式サイトからDownloadしてmicroSDにCopyでOK
128GBのmicroSD:FormatはできるもののNoobsでCopyしたものは
Pi4で認識されない（緑のランプが点灯しない、再検はしていません）
再度フォーマットして公式サイトのDebianのimageCopyでOK
（検証していませんが　後処理が必要なようです、上級者向け？）
####追加ソフトのインストール
（画面　左上のイチゴアイコンをクリック->設定->Add/Remove Software から検索）
インストールに成功するとカテゴリー分けされ簡単に起動できるようになります
今回　Add/Removeから検索してspyder3,gretl,Rをインストール
プログラミング python3用　Spyder3
参考文献「Raspberry Piではじめる機械学習」補足情報トップ
教育・教養　　統計ソフト gretl
参考文献　やさしい計量経済学　プログラミングなしで身につける実証分析
グラフィック　R(ggplot2）
参考文献　O'REILLY Rグラフィックス　クックブック　第２版
##### RaspberryPi4の環境設定　（設定->raspberry Piの設定）
SSHを有効にして　PCとraspberrypi4でファイルの転送を可能にする。
keyboardの設定を　日本語配列にする。
keyboardに関して　記号の配列が変わってしまうことがあるようです。
設定を有効にするためには　sudo rebootする必要がある。
####バックアップ　microSD全体をバックアップ。
RaspberryPi4のmicroSDと同じ容量（３２GB)のFormatしたmicroSDを
アダプターを介してRaspberryPi4のUSBに接続
RaspberryPi4のイチゴアイコン->アクセサリー->SDCardCopierで　
バックアップをとる。（Copyが正常に動くか確認）
バックアップしたmicroSDをPCに接続　imgファイルに変換してPCのハードディスクに保存
######最新の情報は　公式ページで確認をお勧めします。
最後に　Rの散布図を添付しておきます
####![rasp000.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435503/aaddf6ae-54fd-7396-c9c1-9abf1db897c2.png)
参考文献
これ１冊でできる！ラズベリーパイ超入門（pi3 ModelB+対応）改定第５版
福田和宏　著
Raspberry Piではじめる機械学習
金丸隆志　著
やさしい計量経済学
加藤久和　著
Rグラフィックス　クックブック　第２版
Winston Chang 著
エクセルVBAで重複を除いた数を数える

##はじめに

エクセルで重複を除いたアイテムの個数を数えたい時が結構あります。
連想配列(ディクショナリー)を使って数える方法がよく紹介されていますが、今回もう少し複雑な状況に遭遇したので投稿します。

具体的には、こんな状況です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507401/b61c3f41-e0ce-c623-729e-047f6a16932a.png)



つまり、1つのセルにccc/aaaのように複数のアイテムを"/"で区切ってあって、これを「ccc」と「aaa」と区別した上で重複していないアイテムの個数を数えたいという状況です。

##コード
関数として定義します。引数としてセル範囲を指定し、整数を返します。
<br>
流れとしては、
1. 連想配列dictを作成
2. 引数のセル範囲の各セルに対してループ処理を実行(3～4)
3. セルの値がdictのキーに存在している場合は、次のセルへ
4. セルが空白セルでなければ、dictのキーにセルの値を、値に1を追加
5. 次に、dictの各キーに対してのループ処理を実行(6～)
6. キーに"/"が含まれていたら、そのキーを"/"で分離して別の変数splitTxtに配列として格納し、このキー自体はdictから削除
7. splitTxtの中でループ処理を実行(8～9)
8. 分離した文字列txtがdictのキーに存在している場合は、次のtxtへ
9. そうでなければtxtをdictのキーに追加し、値は1とする
10. countNumberの戻り値としてdictの要素数を返す

```VB
Function countNumber(rng As Range) As Long

Dim dict As Object

Dim x As Range
Dim keyTxt As String
Dim key, splitTxt, txt As Variant

Set dict = CreateObject("Scripting.Dictionary")

For Each x In rng
    If dict.exists(x.Value) Then
        GoTo continue1
    End If

    If Not IsEmpty(x) Then
        dict.Add x.Value, 1
    End If
continue1:
Next


For Each key In dict
    If key Like "*/*" Then
        keyTxt = key
        splitTxt = Split(keyTxt, "/")
        dict.Remove key
        
        For Each txt In splitTxt
            If dict.exists(txt) Then
                GoTo continue2
            Else
                dict.Add txt, 1
            End If
continue2:
        Next
    End If
Next

countNumber = dict.Count

End Function
```

##簡単に解説

まずVBAで連想配列を使う場合は、変数をオブジェクトとして宣言してCreateObject関数を使う必要があります。

```VB
Dim dict As Object

Set dict = CreateObject("Scripting.Dictionary")
```
<br>
次に、連想配列のキーに各セルの値を入れていきます。キーに対する値はなんでも良いので１としました。
さて、引数のセル範囲中の各セルに対して処理を行うためにFor Each文を使います。最初のIf文は、「連想配列dictにすでにキーが存在している場合、continue1まで行ってね。」という処理です。一般的なプログラミング言語では、continue文というのがありますが(ループを１回スキップする)、VBAにはないので、こういう処理にします。
2つ目のIf文は、セルが空白セルでなければdictのキーにセルの値を、値に１を追加する処理です。
これで一通りセルの値を重複することなくdictのキーに追加することができました(そもそも連想配列はキーを重複させられません=>重複させようとするとエラーになります)。

```VB
For Each x In rng
    If dict.exists(x.Value) Then
        GoTo continue1
    End If

    If Not IsEmpty(x) Then
        dict.Add x.Value, 1
    End If
continue1:
Next
```
<br>
ここからが今回の大事な部分です。
dict中の各キーに対してループ処理を行います。キーが"/"を含んでいる場合に別の文字列変数keyTxtに格納します。そして、Split関数を使って、"/"で分離した文字列をを要素とする配列をsplitTxtに格納します。このキーは要らないので削除します。

(参考サイト)Split関数の使い方：[Split関数で文字列を区切る](http://officetanaka.net/excel/vba/tips/tips62.htm)


次に、配列splitTxt内でループ処理を行います。配列内の各要素がdictの要素として存在していれば、ループをスキップし(先ほどと同様)、そうでなければキーとして加えます。これでdictのキーには、重複のないアイテムが揃ったことになります。

```VB

For Each key In dict
    If key Like "*/*" Then
        keyTxt = key
        splitTxt = Split(keyTxt, "/")
        dict.Remove key
        
        For Each txt In splitTxt
            If dict.exists(txt) Then
                GoTo continue2
            Else
                dict.Add txt, 1
            End If
continue2:
        Next
    End If
Next

```
TensorFlow 2.0 で微分方程式の数値計算をした話

# はじめに

TensorFlow 2.0 はディープラーニングを初めとした機械学習に利用できる非常に強力なフレームワークです。TensorFlow では数値計算のアルゴリズムを「計算グラフ」という形で抽象的に取り扱います。

SQL でいう実行計画っぽいですね。これによって「アルゴリズムの定義」と「その実行」を分離することができそうです。うまく使えば、機械学習だけでなく一般の数値計算に利用する上でも非常に役立つのでは？

# と思ってやってみた

今回は Lotka-Volterra 方程式を解いてみましょう！ 捕食者と被食者の個体数の変動をモデル化した方程式です。自然界でも見られる「周期解」が再現されることでも有名ですね。

```python
import tensorflow as tf
import matplotlib.pyplot as plt
import timeit

a = 0.2
b = 0.04
c = 0.4
d = 0.05

d_esa = lambda esa, hoshokusha: a*esa - b*esa*hoshokusha
d_hoshokusha = lambda esa, hoshokusha: -c*hoshokusha + d*esa*hoshokusha

def runge_kutta(f, x, y, dt):
    k1 = dt*f(x,y)
    k2 = dt*f(x+0.5*k1, y+0.5*k1)
    k3 = dt*f(x+0.5*k2, y+0.5*k2)
    k4 = dt*f(x+k3, y+k3)
    return (k1+2.0*k2+2.0*k3+k4)/6.0

@tf.function
def lotka_volterra(t_max, t_num, esa_init, hoshokusha_init):
    esa_result = []
    hoshokusha_result = []
    t_result = []

    t = 0.0
    esa = esa_init
    hoshokusha = hoshokusha_init
    
    esa_result.append(esa)
    hoshokusha_result.append(hoshokusha)
    t_result.append(t)

    dt = t_max / t_num

    while t < t_max:
        t += dt
        esa += runge_kutta(d_esa, esa, hoshokusha, dt)
        hoshokusha += runge_kutta(d_hoshokusha, esa, hoshokusha, dt)

        esa_result.append(esa)
        hoshokusha_result.append(hoshokusha)
        t_result.append(t)
    
    return esa_result, hoshokusha_result, t_result

# warm up！！！！！！
esa_result, hoshokusha_result, t_result = lotka_volterra(100.0, 2000, 10, 1)
print(timeit.timeit(lambda: lotka_volterra(100.0, 2000, 10, 1), number=1))

plt.plot(t_result, esa_result)
plt.plot(t_result, hoshokusha_result)
plt.show()
```

`tf.function` デコレータをつけることで、内部の計算が TensorFlow 上のグラフとして計算されることになります。Tensorflow 2.0 から「Python コードと織り交ぜて書く」こともある程度可能になりました。ありがたいですね。今回の場合は `tf.function` を取ることで「ピュアな Python コード」としてすぐに実行することが可能です。

なお、私個人の環境で `tf.function` を付けたほうが4倍程度実行時間が遅くなりました。（CPU）
もちろん今回はオーバーヘッドにしかなってないから、当然ですね(´・ω・`)

# おわりに

いかがでしたか？

Lotka-Volterra 方程式程度なら TensorFlow 2.0 を全く使う必要がないことがわかりました！

偏微分方程式など、行列（テンソル）の演算を多用するような、今回よりかなり重たい数値計算であれば TensorFlow が活躍できるかもしれません。

やろうとしたけれど、うまくいかなかったのはサンタさんとの秘密だよ！
良いお年を :dogeza: