OmniAICreator/Qiita-1.07M huggingface dataset:
Rails環境構築をやってみた【Rails5.2.2】

##前提条件
* Homebrewインストール済み
* rbenvインストール済み（本記事ではバージョン2.6.0のrubyを使用します）

##1. Bundlerをインストール
以下のコマンドを実行

```
$ gem install bundler
```

`Users/ユーザー名/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems`に最新のbundlerがインストールされます。（rbenvでバージョン2.6.0をインストールした際、bundlerもインストールされているようなので、このコマンドが必須なのかは不明）

##2. アプリディレクトリの作成・移動
今回は`Users/ユーザー名/Documents/workspace`に`test_app`ディレクトリを作成します。
その後以下のコマンドを入力し、`test_app`ディレクトリに移動します。
（本記事では`test_app`としていますが、任意のディレクトリ名で大丈夫です。本記事では説明のため`test_app`を作成・使用します）

```
$ cd Users/ユーザー名/Documents/workspace/test_app
```

##3. Gemfileの作成
以下のコマンドを入力

```
$ bundle init
```

`test_app`ディレクトリにGemfileが作成されます。

##4. Railsのインストール

```text:Gemfile
# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

# gem "rails"
```

4行目の`# gem "rails"`の`#`を削除して保存します。
その後以下のコマンドを入力します。

```
$ bundle install --path vendor/bundle
```

`Users/ユーザー名/Documents/workspace/test_app/vendor/bundle/ruby/2.6.0/gems`にrailsおよび関係するgemがインストールされます。

##5. Railsアプリの作成
以下のコマンドを実行

```
$ bundle exec rails new . --skip-bundle
```

`test_app`ディレクトリに`app`や`bin`ディレクトリなどが作成されます。
（test_appアプリが作成される）

上記のコマンドを入力した際、Gemfileを上書きするか聞かれるため、あらかじめ古いGemfileは削除しておいても良いかもしれません。

##6. bundle installの実行
`test_app`ディレクトリに新しいGemfileが作成されているので

```
$ bundle install
```

を入力し、Gemfile内に記述されているgemをインストールします。
（4. で`$ bundle install --path vendor/bundle`を入力したので`Users/ユーザー名/Documents/workspace/test_app/vendor/bundle/ruby/2.6.0/gems`にgemがインストールされます）
（`test_app`ディレクトリの`.bundle`ファイルに`BUNDLE_PATH: "vendor/bundle"`と記載されています）

##7. Railsサーバーの起動

```
$ bundle exec rails s
```

を実行します。
その後、`http://localhost:3000`にアクセスすると...

<img width="940" alt="rails_ss.png" src="https://qiita-image-store.s3.amazonaws.com/0/321820/516cd67e-15b2-dc06-ba7d-899db86a1957.png">

環境構築成功です！！

※投稿時点（2019年３月上旬）時点で、sqlite3のバージョンによるエラーが確認されています。Gemfileのsqlite3部分を`gem 'sqlite3', '~> 1.3.6'`とすると解決するようです。


##なぜbundle execが必要なのか？
`bundle exec`を書くことで、bundlerでインストールされたgemを使用することができます。
`bundle exec`を書かない場合、システム側（`Users/ユーザー名/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems`）のgemを参照してしまいます。
今回、システム側にはrailsのgemをインストールしていないため、`bundle exec`無しではrailsのコマンドを使用することができません。（たぶん...）

##備考
「３. Gemfileの作成」以降のコマンドは全て`test_app`ディレクトリにいる状態で実行しています。

##最後に
cloud9を卒業して、環境構築を行ってみました。
初投稿&初心者のため、内容に誤り・不適切な記述がありましたら、ご指摘いただけると幸いです。

####参考サイト
* https://qiita.com/osamtimizer/items/3a241f365c85356394a8
* https://qiita.com/hisonl/items/162f70e612e8e96dba50
* https://qiita.com/ChaaaBooo/items/9ca71b839f29c6050ce0
* https://techracho.bpsinc.jp/hachi8833/2016_12_13/30751
* https://teratail.com/questions/62084
計算してみよう

前回:https://qiita.com/New_enpitsu_15/items/2647d3b929bf0e9e7113
次回:https://qiita.com/New_enpitsu_15/items/ff7bd650f3e439060a8f
目次:https://qiita.com/New_enpitsu_15/private/479c69897780cabd01f4


今回はPythonを使って、"計算"をしていきます。

前回までにも2つほど計算が出てきましたね。
そう、

```python
var = 1
print(var + 5)
#6
```
[※"変数と代入"より引用](https://qiita.com/New_enpitsu_15/items/cf3993ddc1a5b748f6d4#%E5%8F%82%E7%85%A7%E4%BF%9D%E7%AE%A1%E5%BA%AB%E3%81%8B%E3%82%89%E7%89%B9%E5%AE%9A%E3%81%AE%E5%90%8D%E5%89%8D%E3%81%8C%E3%81%A4%E3%81%84%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E6%8E%A2%E3%81%99)

これです。これをもっと発展させていきましょう。

#基本の計算、四則演算。

コンピュータで計算するのか…などと身構えなくても構いません。実際に例を見てみましょう。

```:Pythonインプリンター(黒い画面に直接文字を打って実行するもの)を用いています。
...
>>> 5 + 2
7
>>> 5 - 3
2
>>> 3 * 4
12
>>> 5 / 5
1.0
```

例を見るとわかると思いますが、加算減算に関しては驚くほどそのまんま、`+`と`-`が使われます。
式の書き方もそのまんまですね。

#####乗徐算

さて、では`*`(アスタリスク)と`/`(スラッシュ)は何でしょう。
これはそれぞれ、乗算と除算を示しています。

*は×に、/は÷に置き換えて考えてあげれば何も難しいことはありませんね。

#余剰、切り捨て、べき乗(累乗)、ついでにべき根(ルート)

割り算は割り算でも、その余り(余剰)が欲しかったり、小数点は切り捨てた数値が欲しかったりします。そんな時は`%`、`//`を使います。

#####余剰

```
>>> 10 % 3
1
```

余りってなんだか懐かしいですね。
上でやっていることは

10÷3=3...1

の余り、`1`を出力しています。

#####切り捨て除算

```
>>> 10 // 3
3
```

これは一見「は？」ってなりますが、

10÷3=3.3333333...

になりますね。時折、この.33333...が邪魔な時があります。
そんな時、そこを切り捨ててくれるのがこの演算子です。

#####累乗、ついでに平方根。

```
>>> 3 ** 2
9
```

多少PCに触れている人なら、`3^2`と書きたいでしょうが、ここは`**`と記述します。
よって、`3**2`は$3^2$ですから9ですね。

わからない人はここまででいいのですが、

これ、累乗ができるということは平方根もとれます。
ほれ、この通り

```
>>> 2 ** (1/2)
1.4142135623730951
```

いやなんでだよ、ってなる人もいると思いますが、詳しく説明すると数学の記事になるのでかる～く。
$x^\frac{1}{2}$ということはそれを二乗してやれば、$x^\frac{2}{2}=x^1=x$ですよね？
というわけで、2乗するとxになる数なわけですから、$x^\frac{1}{2}$は$x$の平方根ってわけです。

#呼称

`+`だとか`-`だとか。はたまた`%`など、計算の内容を決定するものを__演算子__と呼びます。
その前後にある数字や変数、はたまた文字なんかは__被演算子__と呼ばれます。
ちょっと覚えておきましょう。

#小数を含む計算

Pythonでは、小数を含む計算も不自由なくそのまま行うことができます。

```
>>> 10 * 0.5
5.0
>>> 7.2 + 16.6
23.8
```

#10/3が`3.33...`ではなく`3.3333333333333335`の理由。

これはコンピュータ特有の問題。"丸め誤差"というものです。

コンピュータは実際に計算しているわけですから、どこかで計算をやめてしまわなければなりません。その計算をやめる操作を`丸める`と表現します。

このとき、四捨五入されるか、切り捨てられるかはわかりませんが、__とても小さい誤差__が発生します。これが丸め誤差です。
積み重なると目に見える誤差になってくるわけですね。

#おわりに

次々回には演算子のまとめ(表)と便利な機能を紹介します。

#参考

http://www.tohoho-web.com/python/operators.html
ラジオボタンと不活性処理の連携

ラジオボタンでの選択に応じて

特定ボタンを不活性、活性にする処理。

ラジオボタンの値の取得はfor文を利用するものもあるが

自身はこっちのほうがスッキリで好きなので記録用に。。。

```html:index.html

<form id="testForm" method="get">
  <input type="radio" name="a" value="1" onclick="goDisabled();">不活性
  <input type="radio" name="a" value="2" onclick="goDisabled();">活性
  <input type="radio" name="a" value="3" onclick="goDisabled();">活性
</form>　
<input type="button" id="goBtn" value="GO!!" />
```
 

```js:script.js
function goDisabled(){
  var r = $('input[name="a"]:checked').val();
  if(r == 1){
    // 1のボタンを押したとき不活性化
    $("#goBtn").attr("disabled","disabled");
  }else{
    // 1以外のボタンの時活性化
    $("#goBtn").removeAttr("disabled");
  }
}
```
Swift MediaPlayer ミュージック検索 MPMediaPropertyPredicate

# 概要
Swift MediaPlayer ミュージック検索 MPMediaPropertyPredicate
# init
- init(value: Any?, forProperty: String)
- init(value: Any?, forProperty: String, comparisonType: MPMediaPredicateComparison)

MPMediaPredicateComparison指定の差異がある。
equalTo
contains
の2つが指定出来ます。
一致か、含むかです。
valueに正規表現が使えればいいのですが、使えない様ですね。
##example

```swift
let filter1 = MPMediaPropertyPredicate(value: "中嶋ユキノ", forProperty: MPMediaItemPropertyArtist, comparisonType: MPMediaPredicateComparison.equalTo)
```
Goでメールを送信する

メールについて色々と学んでる最中なので、勉強中のGoでメールの送信方法をまとめてみました。
そのうち受信についても記事にしてまとめていきたいと思っています。

## SMTPSでメールを送信する
```golang
package main

import (
	"crypto/tls"
	"fmt"
	"log"
	"net/mail"
	"net/smtp"
)

const (
	user     = "hoge@example.com"
	password = "hogehoge"
	rcpt     = "hoge_rcpt@rcpt.example.com"
	host     = "example.com"
)

func main() {
	server := host + ":" + "465"
	body := "This mail is TLS test."
	// TLS config
	tlsconfig := &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         host,
	}

	// ログイン情報を用意する
	auth := smtp.PlainAuth("", user, password, host)

	// TLSで通信するためのコネクションを用意する
	con, err := tls.Dial("tcp", server, tlsconfig)
	if err != nil {
		log.Fatal(err)
	}
	// TLSのコネクションでSMTP接続する
	c, err := smtp.NewClient(con, host)
	if err != nil {
		log.Fatal(err)
	}
	if err = c.Auth(auth); err != nil {
		log.Fatal(err)
	}
	if err = c.Mail(user); err != nil {
		log.Fatal(err)
	}
	if err = c.Rcpt(rcpt); err != nil {
		log.Fatal(err)
	}
	w, err := c.Data()
	if err != nil {
		log.Fatal(err)
	}

	message := "From: " + user + "\r\n"
	message += "To: " + rcpt + "\r\n"
	message += "\n" + body

	_, err = w.Write([]byte(message))
	if err != nil {
		log.Fatal(err)
	}
	defer w.Close()

	c.Quit()
}

```

## STARTTLSでメールを送信する
今回サーバのポートを25番でやっていますが、環境によってはOB25によって587番ポートでサービスを提供している場合があると思うので、ポート番号は適宜変更してください。

```go
package main

import (
    "crypto/tls"
    "log"
    "net/smtp"
)

const (
	user     = "hoge@example.com"
	password = "hogehoge"
	rcpt     = "hoge_rcpt@rcpt.example.com"
	host     = "example.com"
)

func main() {
    server := host + ":" + "25"
    tlsconfig := &tls.Config{
        ServerName:         server,
        InsecureSkipVerify: true,
    }

    c, err := smtp.Dial(server)
    if err != nil {
        log.Fatal(err)
    }
    if err = c.StartTLS(tlsconfig); err != nil {
        log.Fatal(err)
    }
    auth := smtp.PlainAuth("", user, password, host)
    if err = c.Auth(auth); err != nil {
        log.Fatal(err)
    }
    if err = c.Mail(user); err != nil {
        log.Fatal(err)
    }
    if err = c.Rcpt(rcpt); err != nil {
        log.Fatal(err)
    }
    w, err := c.Data()
    if err != nil {
        log.Fatal(err)
    }
    defer w.Close()

    message := ""
    message += "From: " + user + "\r\n"
    message += "To: " + rcpt + "\r\n"
    message += "Subject: " + "Test Mail" + "\r\n"
    message += "\n" + "This is StartTLS test"

    w.Write([]byte(message))
    c.Quit()
} 
```
カップヌードル BIGは本当にBIGなのか

# !って何個つけてもええんやで
一流プログラマならカップヌードルをすすりながら一度は気になったことないだろうか、カップヌードル BIGは本当にBIGなのか。

![IMG_20190311_224037.jpg](https://qiita-image-store.s3.amazonaws.com/0/223372/8363b429-457c-b07e-b243-b5da05142632.jpeg)

![IMG_20190311_224047.jpg](https://qiita-image-store.s3.amazonaws.com/0/223372/c09d43e8-190e-c191-042a-d58e57300d95.jpeg)

```!!!!!!!!!!!!!!!!!!!!!!!!BIG```

:::note info
!が24個あったので、Trueとなった。BIGの名に偽りはないことが分かった
:::


書いていて思ったこと。日清のデザイン担当者はここまで考えてデザインしたんだろうか。

# 注意事項
:::note alert
よい子は部屋を片付けてから写真を撮りましょう。できれば食べる前に。
:::
PRML演習問題1.1

![1章 序論-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/221435/c29b3bab-7c77-d6e0-7477-a75e7ac3f2cb.jpeg)
![1章 序論-3.jpg](https://qiita-image-store.s3.amazonaws.com/0/221435/a5fd6a49-b16d-f62d-ddb4-4554a7f44de2.jpeg)
Mac(Mojave)でRails5.2系/Ruby2.6系で cannot load such file -- google/protobuf_c (LoadError) エラー

# 背景
ローカルMac(Mojave)でRails5.2系/Ruby2.6系。 `rails generate migration` しようとしたら以下のエラー

```
bin/rails: Bootsnap::LoadPathCache::FallbackScan
.
.
/Users/xxx/vendor/bundle/ruby/2.6.0/gems/bootsnap-1.4.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require': cannot load such file -- google/protobuf_c (LoadError)
```

# やったこと
Gemfileに以下を `gem "google-protobuf", "3.7.0.rc.2"` を追加。3.6系はrubyの2.6系に対応してないらしい。

参考: https://github.com/protocolbuffers/protobuf/issues/3509#issuecomment-462537872
BeagleBoneGreenでGPSを受信する03

前回
[BeagleBoneGreenでGPSを受信する02](https://qiita.com/pata128/items/77516d81db2aa9bf835e)

GPSの位置情報を記録するのにgpxloggerを使います。gpsd-clientsに含まれています。
コマンドオプション等は以下で確認できます。
https://manpages.debian.org/jessie/gpsd-clients/gpxlogger.1.en.html

電源を入れたら自動的に記録を開始するようにしたいのでサービスとして起動するようにします。
参考:[Raspberry PiでGPS位置情報を記録](http://denor.daa.jp/raspberry-pi%E3%81%A7gps%E4%BD%8D%E7%BD%AE%E6%83%85%E5%A0%B1%E3%82%92%E8%A8%98%E9%8C%B2)

1.ログの出力先ディレクトリの作成

```
$ mkdir gpslog
```

2.サービス起動スクリプトの作成
[BeagleBoneGreenのGPIO端子の設定](https://qiita.com/pata128/items/308e027dc8fb187fe479)で作成したスクリプトと同じディレクトリにしています。参考元とディレクトリが異なります。

```
$ sudo nano /lib/systemd/system/gpxlogger.service
```

```gpxlogger.service
[Unit]
Description=gpxlogger service
After=gpsd.socket
 
[Service]
ExecStart=/bin/bash -c '/usr/bin/gpxlogger -f /home/debian/gpslog/gps_$$(date +%%Y%%m%%d%%H%%M%%S).gpx'
ExecStop=/bin/kill ${MAINPID}
Restart=always
Type=simple
User=debian
Group=debian
 
[Install]
WantedBy=multi-user.target
```
出力を全て記録したいため-mオプションは無しです。

3.サービスの登録

```
sudo systemctl daemon-reload
sudo systemctl enable gpxlogger.service
```

4.再起動後サービス起動の確認

```
sudo systemctl status gpxlogger.service
```
サービスの起動とファイルの作成を確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/366164/e8e5286d-5643-066b-12fd-a5f38086f99d.png)

gpxファイルで記録されるのでGoogle Earthで読み込むことができる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/366164/7f01688b-b3a6-6f30-989f-7bbb0783da00.png)
CS193p class note - 6 Multitouch

######Memo:
. set contentMode to 'redraw' will call the drawRect in custom view 
. call `setNeedsDisplay` and drawRect will be called
. call `setNeedLayout` if you want to layout the subviews 
. `label.frame.size = CGSize.zero` before calling `label.sizeToFit()` if you want the system to adjust the size for you. If there is width for the label, calling `sizeToFit` only adjusts the height.
. `CGAffineTransform` has three methods: scale, translate and rotate
. `traitCollectionDidChange` is called when dynamic type is changed
. add `@IBDesignable` and storyboard will show the design
. add `@IBInspectable` and you can change the property in the storyboard
. `UIGestureRecognizer` has a variable `state`

```swift
override func draw(_ rect: CGRect) {
// create rounded corners
    let roundedRect = UIBezierPath(roundedRect: bounds, cornerRadius: 16.0)
    roundedRect.addClip()
    UIColor.white.setFill()
    roundedRect.fill()
}
```

```swift
private func centeredAttributedString(_ string: String, fontSize: CGFloat) -> NSAttributedString {
// create attributedString
    var font = UIFont.preferredFont(forTextStyle: .body).withSize(fontSize)
    font = UIFontMetrics(forTextStyle: .body).scaledFont(for: font)
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.alignment = .center
    return NSAttributedString(string: string,
                              attributes: [.paragraphStyle: paragraphStyle,
                                           .font: font])
}
```

```swift
// how to deal with const in Swift
extension PlayingCardView {
    private struct SizeRatio {
        static let cornerFontSizeToBoundsHeight: CGFloat = 0.005
        static let cornerRadiusToBoundsHeight: CGFloat = 0.06
        static let cornerOffsetToCornerRadius: CGFloat = 0.33
        static let faceCardImageSizeToBoundsSize: CGFloat = 0.75
    }
}
```

```swift
// adding a gesture recognizer to a UIView
@IBOutlet weak var pannableView: UIView {
    didSet {
        let panGestureRecognizer = UIPanGestureRecognizer {
            target: self, action: #selector(someFunction)
        }
        pannableView.addGestureRecognizer(panGestureRecognizer)
    }
}
```
データベース 同時実行制御 学習メモ

###ロックの粒度
ロックの粒度とは、ロックの対象となるデータの単位の事。具体的には、（行、ページ、テーブル、データベース ）などの大きさで指定が可能。
例えば、ロックの粒度が行ならばトランザクションは同時に同じテーブルにアクセス可能可能である。その為、トランザクション間の待ち時間が短くなる為スループットは向上する。それとは別にロックの粒度がテーブルの場合、同じテーブルにアクセスするしようとする別のトランザクションは、テーブルに対するロックが解除されるまで待ち時間が発生することになる為スループットが低下する。
**ロックの粒度が大きくなるにつれて、ロックの制御は容易になるが、ロックの待ち時間が長くなる。
一方ロックの粒度が小さくなるにつれて、ロックの待ち時間は短縮できるがロックの制御処理が複雑になる。**
###ロックの種類

|ロックの名称|説明|
|:------------------:|:------------------:|
|共有ロック|トランザクションが行を読み出す（参照する）時に、このロックをかける。SQLではSELECT文が動いた時。このロックがかかった場合、他のトランザクションは、共有ロックはかけられるが専有ロックはかけられない。|
|専有ロック|トランザクションが行を更新、SQLではINSERT,UPDATE,DELETEが動いた時にこのロックがかけられる。このロックがかけられた場合、他のトランザクションはロック（共有、専有ともに）かけることができない。|

###２相ロッキングプロトコル(2PL(Two Phase Locking))
排他制御方式の１つ（もう一つは木規約）の事。トランザクションの実行前段階で読み込み・書き込みを行う共有資源に対してロックをかけておいて（第１相）、処理終了後にロックを解除する（第２相）と言うもの。
**２PLの実装がなされているのは、ISOLATION LEVELがREPEATABLE READとSERIALIZABLEに設定されている時。**
**ISOLATION LEVELがREAD COMMITTEDの場合は2PLに準拠していない為、ロックをかける順番を人工的に指定してあげないとデッドロックが起こる可能性が高まる（2PLに準拠指定てもデッドロックは発生する）。**

以下具体例↓
共有資源（a,b）が存在していると仮定した場合。
（２相ロック準拠Ver）
TR1
 LOCK a
 READ a
 a = a + 3
 
 WRITE a
 LOCK b
 READ b
 b = b + 3
 
 WRITE b 
 UNLOCK b
 UNLOCK a

TR2
 LOCK a
 READ a
 LOCK b
 READ b
 UNLOCK b
 UNLOCK a

↑上記の場合、TR1→TR2かTR2→TR1の順序でしかスケジューリングすることができない。この為、直列実行可能性を保証することが可能。

（２相ロック非準拠Ver）
TR1
 LOCK a
 READ a
 a = a + 3
 
 WRITE a
 UNLOCK a
 LOCK b
 READ b
 b = b + 3
 
 WRITE b 
 UNLOCK b

TR2
 LOCK a
 READ a
 LOCK b
 READ b
 UNLOCK b
 UNLOCK a

↑上記の手順で各トランザクションを実行した場合、処理の途中でアンロックをする為T1→T2→T1のスケジューリングが可能であり、直列可能性を保証できない。

**※2PLに準拠した場合、TR1→TR2もしくはTR2→TR1の実行スケジューリングとなる。※**
インターネット回線の速度計測（上り/下り)

# インターネット回線の速度計測
インターネット回線の上りと下りの速度計測を行う必要があり、王道であるiperfを調べていました。
https://iperf.fr/

iperfの場合、いくつかpublicなサーバーが存在するため、そちらを使って上りと下りを計測しようと考えたのですが、publicなサーバーの場合下りがうまく計測できませんでした。(クライアントからサーバーへの上り方向は測れるのですが）

public iperf server
https://iperf.fr/iperf-servers.php#public-servers

自分でAWSのEC2などにiperfをインストールするのも面倒なので、別の手段を探していたところ、speedtestというpythonのツールがありました。こちらがとても便利でしたので紹介させて頂きます。

https://github.com/sivel/speedtest-cli

# Speed Testでやっている事
ざっとコードを見たところ、Speed Testに利用可能なサーバーリストから一番近いサーバーを探してきて、そのサーバーに対してHTTPのダウンロードとアップロードを行なっています。--secureのオプションでHTTPSのダウンロードとアップロードの計測も可能な模様です。

インストールは上記のGithubに書かれていますが、Macの場合Pipでインストール可能です。

```bash
$ pip install speedtest-cli
```

計測は以下のコマンドで可能です。

```bash
$ $ speedtest
Retrieving speedtest.net configuration...
Testing from XXXXX ...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by GIAM PING VIETPN.COM (Tokyo) [23.22 km]: 17.611 ms
Testing download speed................................................................................
Download: 67.19 Mbit/s
Testing upload speed................................................................................................
Upload: 92.91 Mbit/s

```

# Pythonスクリプトから呼んでみる

Pythonスクリプトからはspeedtestをimportすれば以下のような形でテストできます。まずは、サーバーリストを取得して、一番近いサーバーを選択します。後はdownload()とupload()を実施すれば回線速度を計測する事ができます。計測結果は、それぞれbpsで出力されます。

```python
import sys
import speedtest

def get_speed_test():
    servers = []
    stest = speedtest.Speedtest()
    stest.get_servers(servers)
    stest.get_best_server()
    return stest

def command_line_runner():
    stest = get_speed_test()
    down_result = stest.download()
    up_result = stest.upload()
    print str(down_result) + ',' + str(up_result)

if __name__ == '__main__':
    command_line_runner()
```

# 1分に一度速度を計測させてみる
上記のスクリプトを修正して、1分に1度計測するように修正する。

```python
import speedtest
import datetime
import time

INTERVAL_SEC = 60

def get_speed_tester():
    servers = []
    stester = speedtest.Speedtest()
    stester.get_servers(servers)
    stester.get_best_server()
    return stester

def get_timestamp():
    date = datetime.datetime.now()
    timestamp = str(date.strftime('%Y-%m-%d %H:%M:%S'))
    return timestamp

def test_speed(stester):
    down_result = str(int(stester.download()))
    up_result = str(int(stester.upload()))
    return down_result, up_result

def command_line_runner():
    stester = get_speed_tester()
    print 'time,down(bps),up(bps)'
    while True:
        t1 = time.time()
        timestamp = get_timestamp()
        down_result, up_result = test_speed(stester)
        print timestamp + ',' + down_result + ',' + up_result
        t2 = time.time()
        next_sleep_time = int(INTERVAL_SEC - (t2 - t1))
        time.sleep(next_sleep_time)

if __name__ == '__main__':
    command_line_runner()
```
ReactiveX

```
Observable.just("800x600")
//    .observeOn(ConcurrentDispatchQueueScheduler(qos: .default))
    .map { $0.replacingOccurrences(of: "x", with: "/") }
    .map { "https://picsum.photos/\($0)/?random" }
    .map { URL(string: $0) }
    .filter { $0 != nil }
    .map { $0! }
    .map { try Data(contentsOf: $0 }
    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .default))
    .map { UIImage(data: $0) }
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { image in 
        self.imageView.image = image
    }).disposed(by: disposeBag)

```
【WPF】C#でjpgのExif情報を書き込む

# 概要
C#(WPF)で、jpg画像の中のEXIF情報を取り出し/書き込みする。
読み書きには、BitmapMetadataクラスのGetQuery/SetQueryを使用する。

# 書き込み
流れは、下記のようにする。

- new BitmapMetadata("jpg");でjpg用のBitmapMetadataを作成。
- 作成したMetadataに、SetQueryでデータを書き込む。
- データを入れたMetadataを、BitmapFrame、FileStreamを使ってファイルに書き込む。

具体的には、下記のようにする。

``` .cs
// ファイル読みこみ
MemoryStream data = new MemoryStream(File.ReadAllBytes(tb_FileName2.Text));
WriteableBitmap image = new WriteableBitmap(BitmapFrame.Create(data));
data.Close();

// metaデータを準備
var metadata = new BitmapMetadata("jpg");
metadata.SetQuery("/app1/ifd/gps/subifd:{ushort=1}", GPSLatitudeRef);
metadata.SetQuery("/app1/ifd/gps/subifd:{ushort=2}", GPSLatitude);
metadata.SetQuery("/app1/ifd/gps/subifd:{ushort=3}", GPSLongitudeRef);
metadata.SetQuery("/app1/ifd/gps/subifd:{ushort=4}", GPSLongitude);
metadata.SetQuery("/app1/ifd/{ushort=271}", "入れたメーカー名");
metadata.SetQuery("/app1/ifd/{ushort=272}", "いれたモデル名");

// ファイルに書き込み
using (FileStream stream = new FileStream(tb_FileName2.Text, FileMode.Open))
{
    var enc = new JpegBitmapEncoder();

    var frame = BitmapFrame.Create(image, null, metadata, null);
    enc.Frames.Add(frame);
    enc.Save(stream);
}

```

※あるファイルから読み込んだEXIF情報を別のファイルに書き込む想定で作っている。
　ので、SetQueryのところで使っている「GPSLatitudeRef」などは、読み込みの回で読み込んだデータを使っている想定。
参照：https://qiita.com/tera1707/items/936041605cfa08aec355

# コード
https://github.com/tera1707/WPF-/tree/master/017_SetGetExif

# 参考

EXIF規格
http://www.cipa.jp/std/documents/j/DC-008-2012_J.pdf

わかりやすいEXIFの規格のイメージ(図がわかりやすい)
http://dsas.blog.klab.org/archives/52123322.html

書き込みのサンプル
http://puni-o.hatenablog.com/entry/2017/12/15/113053

読み込みのサンプル
http://funct.hatenablog.com/entry/20151007/1444231916
Colaboratory で Progress bar を表示

#Google Colaboratory でプログレスバー を表示したい.

[参考元: How do I use updatable displays on colab?](https://stackoverflow.com/questions/46939393/how-do-i-use-updatable-displays-on-colab)
[参考元: Demo Program](https://colab.research.google.com/drive/1I2o3Ie34vJ3G4M6eE54-OyrmzJNBwhOp)

# 使いやすく書き換えたもの

```python:ProgressBar.ipyrb
class progressbar:
    def __init__(self, data):
        if type(data) is not int:
            self._datas = data
        else:
            self._datas = range(data)
        self._length = len(self._datas)
        self._count = 0
        self._image = display(self.__bar(), display_id=True)
        
    def show(self):
        from IPython.display import display
        self._image.update(self.__bar())
        return self._count / self._length
    
    def step(self, count=1):
        self._count += count
        self.show()
        
    def __next__(self):
        if self._count < self._length:
            r = self._datas[self._count]
        else:
            raise StopIteration
        self.step(1)
        return r
        
    def __iter__(self):
        return self
        
    def __bar(self):
        from IPython.display import HTML
        return HTML("""
            <progress
                value='{value}'
                max='{length}',
                style='width: 100%'
            >
                {value}
            </progress>
        """.format(value=self._count, length=self._length))
```

# 使い方 その1
```python:sample01.ipyrb
import time

loop_size = 1000
pgb = progressbar(loop_size)
for i in range(loop_size):
    print(i, end=' ')
    time.sleep(0.01)
    pgb.step()
```

# 使い方 その2
```python:sample02.ipyrb
import time

loop_size = 1000
for i in progressbar(range(loop_size)):
    print(i, end=' ')
    time.sleep(0.01)
```
読書めも : 何でもわかりやすくする技術、伝える技術

2. 何でもわかりやすくする技術、伝える技術
=====
 - http://amzn.asia/7wi3hIE


概要
-----
下記のような課題を解決するため、具体的なコツ34個を「話す・書く・聞く・読む」に分類し、紹介している

- 何が言いたいのかわからない、と言われる
- うまく人に伝えることができない

内容
-----
1. 誰にでも必ず伝わる「話し方」の技術
    - わかりやすい話し方の本質を理解する
        * 話す内容だけでなく、話し方や雰囲気間のとり方が重要
    - **話す内容の設計図を頭でつくる**
    - 話す内容を一言でまとめ、はじめに予告する
    - **相手の興味のあるテーマを想像し、話すようにする**
    - 質問に対してはドンピシャで返答する、など
2. 誰にでも必ず伝わる「書き方」の技術
    - **文章のフロー(設計図)を意識する**
    - 情報を整理し、簡潔に内容を伝える
        * はじめの1文は以降の文章を統括する内容を簡潔に伝える
        * フォーマットに従って書く
            1. テーマ/結論
            2. 状況の詳細
            3. 締めくくり
    - **相手にとってのわかりやすさを考え** 、独りよがりな文章にしない、など
3. どんな話もわかりやすくする「聞き方」の技術
    - **相手の話を聞く姿勢を身につける**
    - **質問を駆使して話の流れをコントールする**など
4. どんな情報をわかりやすくなる「読み方」の技術
    - 検索基準を明確にして効率よく読む
    - インプットに対してアウトプットを行う、など


新たに得た知見→いままでできていなかった点
-----
1. 話のはじめに予告する。相手に合わせてその内容を変える
    - 意識していたが、内容を変えることはできていなかった
2. 文章のはじめの一文は一つの事柄だけ
    - 意識していたが、その一文のチョイスがいままで不適切であった
3. 話の全体から今聞いている箇所はどこかを意識してきく
    - できていなかった。これができていないと効果的な質問や自身が相手に求められる回答をかえすことができないと感じた


所感
-----
多くのコツは自身で現状できているのではないかと感じることが多かったため、  
大きく学ぶことはなかったと感じる。(メモを取る・箇条書きを適切に使う、など)
が、頭でわかっていてもいざ自分がそのコツ通りに適切にアウトプットできているかというとできていないため、各コツにかかれている例文を読むことで自分が今できている/できていないの確認を行うことができた。

大事な部分は下記2点であったと思う
 1. 相手を尊重する
 2. 話の内容を整理整頓する

本レポート自体わかりやすいよう書いたつもりであるが、そこまで自信がないので
引き続きアウトプット時に気をつけていたい。
WindowsにPHPの環境を作る（XAMPPのインストール）

# はじめに
WEBアプリケーションの開発にも挑戦したいと思い、PHPの勉強を始めました。
その実行環境を作った際の、備忘録として書きます。
（ほとんど参考サイトの通りです。）

# XAMPPのインストール
PHPの環境を作る際に、XAMPPというものをインストールしました。

まず、以下のサイトから、XAMPPのインストーラをダウンロードして実行します。
[XAMPP Installers and Downloads for Apache Friends](https://www.apachefriends.org/jp/index.html)
![1.png](https://qiita-image-store.s3.amazonaws.com/0/311225/4c99848e-7b31-0187-2e84-1b19e4221312.png)
「Next>」を押します。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/311225/78a7f659-099d-2ad9-3512-60c9d0b9aff3.png)
インストールしたいものにチェックをつけます。私はひとまずすべてインストールしました。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/311225/3aa2e3a7-c0f9-f5df-26f6-3740fcc42113.png)
インストールする場所を選びます。基本的に変えなくて大丈夫です。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/311225/d49f512a-f9f8-ac79-aeac-26cf1bea41a5.png)
これはチェックを外します。

後は、「Next>」を押していくだけでインストールできます。

以下のサイトを参考にしました。
[XAMPPをインストールする方法【超初心者向け】 | TechAcademyマガジン](https://techacademy.jp/magazine/1722)

# 実行確認
![x.png](https://qiita-image-store.s3.amazonaws.com/0/311225/585cf6a4-d70c-3d8e-244b-651a1cbc4f4e.png)
「XAMPP Controll Panel」を起動します。
![x3.png](https://qiita-image-store.s3.amazonaws.com/0/311225/4d618c31-e326-ad05-8434-352a74488acc.png)
「Apache」と「MySQL」のStartボタンを押します。以下のようになります。
![x4.png](https://qiita-image-store.s3.amazonaws.com/0/311225/9ad41a2e-a862-7da1-cd1d-7432e92d0357.png)

![x5.png](https://qiita-image-store.s3.amazonaws.com/0/311225/bfad9151-a982-01a4-687d-d55c65200874.png)
上記のアドレスにアクセスすると、以下のような画面が開きます。
![x6.png](https://qiita-image-store.s3.amazonaws.com/0/311225/d5188d29-0a15-4a98-7ec5-fd0fafcea20c.png)
これで成功です。

また、xampp内の「htdocs」というフォルダにファイルを置くと開くことができます。
デフォルトでは、「C:\xampp\htdocs」です。
以下のファイルを作成して置きます。

```php:test.php
<?php
	echo "HELLO WORLD";
```
![x7.png](https://qiita-image-store.s3.amazonaws.com/0/311225/d35b6e9c-fd0c-2a21-a3f0-a6f298ed0b49.png)
上記のアドレスにアクセスします。

![x8.png](https://qiita-image-store.s3.amazonaws.com/0/311225/f2de5d53-2397-4628-13f6-7bebee61a620.png)
無事、表示されました。

# おわりに
ひとまず、PHPの環境を作成しました。
次は、フレームワークの環境を作りたいと思います。
今更ながらWindows8.1端末(Surface3)をWindows10にアップデートする

ひょんなことからWindows8.1Pro端末（Surface3）を手に入れたので、2019年2月時点でWindows10にアップデートできるんだっけという視点での確認がてら手順を残してみる。
ぶっちゃけると同じ端末を手に入れた職場の同僚向けのメモ。

#事前準備
【重要】これをやっておかないと、Windows10にしようとしたときにアップデートが46％で止まってしまう。

歯車アイコン＞保守と管理＞WomdpwsUpdate＞更新プログラムのインストール方法を選択する。
![スクリーンショット (2).png](https://qiita-image-store.s3.amazonaws.com/0/35808/15520374-1e6b-b6b0-bfb5-123a943aee51.png)

「重要な更新プログラム」のドロップダウンリストを「更新プログラムをチェックしない（推奨されません）」にしておく。下2つのチェックも外した状態にしておく。
![スクリーンショット (3).png](https://qiita-image-store.s3.amazonaws.com/0/35808/ad98c23c-65f9-9938-a2ac-b8136660a718.png)


#ダウンロード
https://www.microsoft.com/ja-jp/software-download/windows10
にアクセスする。
![スクリーンショット (4).png](https://qiita-image-store.s3.amazonaws.com/0/35808/be1c9c82-43fb-58e5-3f28-f5578ad01a04.png)


「ツールを今すぐダウンロード」をクリック。

「MediaCreationTool1809.exeを実行または保存しますか？」と聞かれるので「保存」を押下。

# インストール作業
ダウンロード完了後、「実行」を押下。
「Windows10 セットアップ」の画面が表示される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/3c81283c-397f-3ca3-6e58-3ac8661e2aea.png)

しばし待つ。

「適用される通知とライセンス条項」が表示されるので「同意する」を押下。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/26885ec1-22aa-a8aa-a6d9-0f3f03364338.png)

「このPCを今すぐアップグレードする」＞「次へ」と進む。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/782e33ac-bcaa-b4e5-c943-312d42f6b859.png)

ダウンロードが始まる。

およそ20分後、ダウンロード終了。このあたりはWi-Fi環境に依存するけどまぁだいたいこんなもんのはず。

開始からおよそ30分後。再度ライセンス条項のウィンドウが開くので「同意する」、
更新プログラムのダウンロードが始まる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/e1e4f671-3e25-4e15-c559-72bb3a111d03.png)

「次の作業が必要です」
このデバイスはWindows10で互換性がありません。
という画面が出る。アイコンの隣りにある「確認」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/294f4334-24cb-6753-2611-a8a16a69762d.png)


「インストールする準備ができました」の画面になるので「インストール」を押下。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/de539abf-892b-8ad1-6ae8-093f7ee92e60.png)

このあと、再起動したり更新プログラムの構成が走ったりで暫く待つ。
これすごく長い。めっちゃ時間かかる。
でも基本的にここまでくればあとは放置で大丈夫なのでここまで仕込んで寝ちゃうと翌朝には出来てる感じ。


#インストール後の設定
自分のSurface3だけかもしれないけど、TypeCoverが英語キーボードとして認識されてしまって日本語キーボードにならなかった。具体的に言うと、**Shift+2で@に**なったりする。この問題を修正する。

Windowsメニューから設定を開き、「時刻と言語」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/c7d64325-7cde-ea3b-53cc-79687c3c727f.png)

「言語」を選択し、「日本語」部分をクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/e3f55e3b-6c9a-864a-50a8-cfe36fd78e49.png)

表示された「オプション」を選択。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/36cf30a1-1f77-76e3-c973-8b69ee39f5f5.png)

「ハードウェアキーボードレイアウト」が英語キーボードになっていたら「レイアウントを変更する」を押下。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/82657ba5-182e-d83e-36b3-2ee8cd14a8e7.png)


ドロップダウンリストから「日本語キーボード（106/109キー）」を選択して「今すぐ再起動する」を押下。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35808/e291f950-0b78-987e-6e9d-cfafe63ce7be.png)

ここまでで一通り使えるようにはなるはず。
なっとく！アルゴリズム(p64)再帰

## p64の練習問題(4.1)
4.1 sum関数のコードを書いてみる

答えを見ずに書いたらこんな感じ

```Swift
func sum(array: [Int]) -> Int {
    var arr = array
    
    if arr.count < 2 {
        return arr[0]
    }
    return arr[ arr.count - 1 ] + sum(array: Array(arr.dropLast(1)))
    
}

print(sum(array: [1,2,3,4]))
```

解答を参考にするともう少しスマートにかけたかな？

```python
def sum(list):
   if list == []:
      return 0
   return list[0] + sum(list[1:])
```

```Swift
func sum(array: [Int]) -> Int {
    var arr = array
    guard arr.isEmpty else {
        return arr[0] + sum(array: Array(arr.dropFirst(1)))
    }
    
    return 0
}

print(sum(array: [1,2,3,4]))
```

## 詰まったころ
下記のように書くと

```Swift
func sum(array: [Int]) -> Int {
    var arr = array
    
    if arr.count < 2 {
        return arr[0]
    }
    return arr[ arr.count - 1 ] + sum(array: arr.dropLast(1))
    
}

print(sum(array: [1,2,3,4]))

```

エラーメッセージが出た

```
main.swift:7:50: error: cannot convert value of type 'ArraySlice<Int>' to expected argument type '[Int]'
    return arr[ arr.count - 1 ] + sum(array: arr.dropLast(1))
```

公式ドキュメントを参照すると`dropLast`は`Substring`をかえすらしい。arrayを返すのだと思ってた。

```
func dropLast(_ k: Int) -> Substring
```

### 対策
`Array(arr.dropLast(1))`とかいて型を変換した

## 4.2 リスト内の要素の個数を数える再帰関数を書いてみる
```
func count(array: [Int]) -> Int {
    var arr = array
    
    guard arr.isEmpty else {
        return 1 + count(array: Array(arr.dropFirst(1)))
    }
    return 0
}

print(count(array:  [1,2,3,4,7]))
```

## 4.3 リストに含まれている数字のうち、最も大きな数字を見つけ出す

これも答えを見ずに考えたらこんな感じ　ちょっと汚い

```Swift
func largeNumber(array: [Int]) -> Int {
    var arr = array
    
    if arr.count < 2 {
        return arr[0]
    }
    
    if arr[ arr.count - 1 ] == largeNumber(array: Array(arr.dropLast(1))) {
        return arr[ arr.count - 1 ]
    } else if arr[ arr.count - 1 ] < largeNumber(array: Array(arr.dropLast(1))) {
        return largeNumber(array: Array(arr.dropLast(1)))
    } else {
        return arr[ arr.count - 1 ]
    }
}

print("largeNumber(array: [1,2])",largeNumber(array: [1,9,6]))
```

教本の答えはこんな感じ

```python
def max(list):
   if len(list) == 2:
      return list[0] if list[0] > list[1] else list[1]
   sub_max = max(list[1:])
   return list[0] if list[0] > sub_max else sub_max

```

Swiftで書いてみるとこんな感じ
唐突に`arr.count == 2`って書いてあったらちょっとわかりにくいかも・・・・

```Swift
func largeNumber(array: [Int]) -> Int {
    var arr = array
    
    if arr.count == 2 {
        return arr[0] > arr[1] ? arr[0] : arr[1]
    }
    var subMax = largeNumber(array:Array(arr.dropLast(1)))
    return arr[0] > subMax ? arr[0] : subMax
}

print("largeNumber(array: [1,2])",largeNumber(array: [1,9,6]))

```

## 参考文献
[Swift の Array やら ArraySlice やらポインタの変換まとめ](https://qiita.com/Satachito/items/4c39c9b06304e4d86660)

[Apple docment popLast()](https://developer.apple.com/documentation/swift/string/2997140-poplast)

[Apple docment dropLast(_:)](https://developer.apple.com/documentation/swift/string/2893517-droplast)
SlackでQiitaのfeedがbroken linkを含んでいるのを調べた

## 壊れている部分

```xml
   <content type="html">
&lt;h2&gt;
&lt;span id="minitest" class="fragment"&gt;&lt;/span&gt;&lt;a href="#minitest"&gt;&lt;i class="fa fa-link"&gt;&lt;/i&gt;&lt;/a&gt;Minitest&lt;/h2&gt;
```

のように `href` 属性が相対リンクになっていて、 Slack は `https://qiita.com/#minitest` として扱うため、リンク切れになっている。
(アンカーが存在しないだけなので、ページ自体は開ける)

## 仕様を確認

atom で検索すると atom editor が検索ノイズになるので、 atom feed で検索すると良い。
仕様を軽く確認したところ、 content の type が html や xhtml のときに相対リンクがどう扱われるべきかの記述は見つけられなかった。
HTML の base 要素に相当するようなものもなさそうだった。

## Feed validator でチェック

https://validator.w3.org/feed/check.cgi?url=https%3A%2F%2Fqiita.com%2Ftags%2Fruby%2Ffeed でチェックしたところ、以下のようなエラーなどだけで、相対リンクは問題なさそうだった。

```
This feed does not validate.

line 7, column 2: Undefined feed element: description [help]

  <description>QiitaでRubyタグが付けられた新着記事</description>
  ^
line 9, column 35: link must have an href attribute [help]

  <link>https://qiita.com/tags/ruby</link>
                                   ^
line 15, column 4: Undefined entry element: url (20 occurrences) [help]

    <url>https://qiita.com/.../items/...</url>
    ^
In addition, interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

line 9, column 8: link should not have text (all data is in attributes) [help]

  <link>https://qiita.com/tags/ruby</link>
        ^
line 28, column 0: content should not contain data-lang attribute (99 occurrences) [help]

&lt;div class="code-frame" data-lang="vim"&gt;&lt;div class="highlight"&gt;& ...
line 1184, column 0: content should not contain data-canonical-src attribute (6 occurrences) [help]

    <content type="html">&lt;p&gt;&lt;a href="https://camo.qiitausercontent. ...
line 2150, column 0: content should not contain script tag [help]

&lt;script async src="https://platform.twitter.com/widgets.js"&gt;&lt;/scrip ...
line 2333, column 0: content should not contain data-hovercard-target-type attribute (8 occurrences) [help]

「&lt;a href="/profile" class="user-mention js-hovercard" title="profile" dat ...
line 2333, column 0: content should not contain data-hovercard-target-name attribute (8 occurrences) [help]

「&lt;a href="/profile" class="user-mention js-hovercard" title="profile" dat ...
```

## 別の validator でチェック

https://rssatom.com/feedvalidator.php でチェックしたところ、エラーなしだった。

## 要望

見出しに対応する部分に qiita.com へのリンクがあると Slack で記事の概要 + qiita.com の概要×最初の方の見出しの数 が展開されて邪魔なので、 feed では見出しの部分のリンクは削って欲しいです。

script タグなどの validator によっては怒られる部分も出来るだけ直した方が良いのではないかと思いました。
最新最強の物体検出技術M2Detを動かしてみた

# はじめに
先日以下の記事を書きました。

[最新最強の物体検出技術M2Det](https://qiita.com/kzykmyzw/items/1831f70dcade04db2210)

で、著者らによる実装が[GitHub](https://github.com/qijiezhao/M2Det)で公開されたので動かしてみると共にSSDとざっくり比較しました。結論を言ってしまうと、今回試した範囲ではM2DetはSSDよりも遅かったですが、特に小さな物体に対する検出精度がかなり高いです。

# 実験環境
今回はASUSのゲーム向けラップトップ[ROG ZEPHYRUSGX 501GI](https://www.asus.com/jp/Laptops/ROG-ZEPHYRUS-GX501/)を使いました。GTX 1080を積んでるにも関わらずまぁ持ち歩けなくはないというレベルのサイズを実現している優秀なマシンです。スペックはざっとこんな感じです。

- CPU: Intel Core i7-8750H @ 2.2GHz
- MEM: 24GB
- GPU: NVIDIA GeForce GTX 1080 Max-Q
- OS: Ubuntu 16.04 LTS

# 実装
## M2Det
冒頭にも書いたように著者らの実装をそのまま使っています。PyTorchで実装されており、推奨ヴァージョンは0.4.1ですが最新の1.0でも問題なく動きました。

[qijiezhao/M2Det](https://github.com/qijiezhao/M2Det)

基本的にはREADME通りにやれば動くと思います。今のところ公開されている[学習済みのWeight](https://drive.google.com/file/d/1NM1UDdZnwHwiNDxhcP-nndaWj24m-90L/view)は画像サイズが512×512、BackboneがVGG-16のものです。

## SSD
比較用のSSDには一番有名な以下の実装を使いました。

[balancap/SSD-Tensorflow](https://github.com/balancap/SSD-Tensorflow)

こちらもREADME通りで問題ありません。M2Detと揃えるため、同じく画像サイズが512×512、BackboneがVGG-16の[学習済みWeight](https://drive.google.com/file/d/0B0qPCUZ-3YwWT1RCLVZNN3RTVEU/view)を使いました。

# 結果
近所で適当に撮影した映像（640×480）で検出性能を比較しました。まず、SSDです。右下にフレームレートを出してます（サムネールクリックでYouTubeに飛びます）。
[![SSD_RESULT_01](http://img.youtube.com/vi/AdFKIA4Azi4/0.jpg)](http://www.youtube.com/watch?v=AdFKIA4Azi4)
次に、M2Detです。
[![M2DET_RESULT_01](http://img.youtube.com/vi/1hugYRnLTHM/0.jpg)](http://www.youtube.com/watch?v=1hugYRnLTHM)
オリジナルのソースコードそのままなので、両手法でボックスの色が全然違っており、かつ大変見づらくてすいません。まずフレームレートですが、SSDが50fps近く出ているのに対し、M2Detは約10fpsとだいぶ遅いです。M2Detの[論文](https://arxiv.org/abs/1811.04533)で著者らが実際に自分達で評価しているもので今回の条件に近いのは以下の結果です（論文のFigure 5参照）。

- GPU: NVIDIA Titan X PASCAL
- M2Det512-vgg: mAP 37.6% @ 55.5ms (18 fps)
- SSD513-ResNet101: mAP 31.0% @ 37ms (27 fps)

Titan XとGTX 1080の性能差を考えると、M2Detについてはまぁこんなもんかという感じですね。しかしSSDは今回のやつは妙に早いな… 今回のはVGG-16なのでResNet-101よりもさらに遅いはずなんだが…　まぁ、速度については、PyTorchとTensorflowの違いとか、とにかくベースが全然違うのであまり正確な比較ではないですね。参考程度。

次に、検出精度ですが、見た目の印象ではM2Detの圧勝という感じ。特に信号なんかはかなり小さく写ってますが、そこそこ検出できてます。あと、歩行者の検出精度がすごい。オクルージョンでほとんど頭しか見えないような場合でも検出できてる。これは驚きました。他にも途中にバスが通りますが、窓越しに上半身だけ見えてるドライバーも検出できてます。

続いてもうちょっとエクストリームな状況で試してみました。まずSSD。
[![SSD_RESULT_02](http://img.youtube.com/vi/qCMgJnC8NGc/0.jpg)](http://www.youtube.com/watch?v=qCMgJnC8NGc)
続いてM2Det。
[![M2DET_RESULT_02](http://img.youtube.com/vi/sYkqcTImK9w/0.jpg)](http://www.youtube.com/watch?v=sYkqcTImK9w)
特にSSDの方、歩行者のボックスの枠が大変見づらくて恐縮ですが、こちらも精度はM2Detの方が圧勝しているのがわかるかと思います。交差点の向こう側にいる人すら検出できてますね。あと、歩行者が持ってるバッグやスーツケースも検出できてる。やはり小さな物体にかなり強いみたいです。

# まとめ
M2Detのオリジナル実装が公開されたので、SSDと比較してみました。どちらも実装のベースが異なっているので厳密な比較ではないのですが、速度ならばSSD、精度ならばM2Detという結果になりました。特に小さい物体に対するM2Detの検出精度は驚異的です。

# おまけ
公開されたM2Detのデモは静止画入力オンリーでしたが、ウェブカメラからの入力に対してリアルタイムに検出結果を見れるように機能を追加しました。以下が機能追加済みのコードですので、ご興味ある方はREADMEを参考に試してみてください。

[kzykmyzw/M2Det at add_webcam_mode](https://github.com/kzykmyzw/M2Det/tree/add_webcam_mode)
MySQLの再インストール方法についての備忘録

ハマったので備忘録。

MySQLをインストールすると、
設定ファイルなどが分散しているようで
単純にプログラムのアンインストールからでは
ちゃんとアンインストールできていません。

そのため以下の手順が再インストールのために必要でした。

**環境**
Windows 7
MySQL 5.7

**手順**
1. 管理ツール>サービスからMySQL削除
2. C:¥Project Files配下のMySQLフォルダ削除
3. C:¥Program Datas(隠しフォルダ)配下のMySQLフォルダ削除
4. 環境変数を設定していたら削除
5. プログラムのアンインストールからMy SQL Serverアンインストール
6. OS再起動
7. 最新版のmsiを再度ダウンロードして、インストール
【vimめも】bundle exec ruby を使用してquickrunでのruby実行

## はじめに

tempファイルにてrubyを試せるようにしており、簡単に動作確認などをできるようにしていましたが
bundleのおかげでgemのrequireがうまくいかない！！ってなったので
`bundle exec ruby`を使ってquickrunを実行できるようにコマンドを作りました

#### これが元の設定

```vim
let g:quickrun_config= {
  \   '_': {
  \     'runner': 'vimproc',
  \     'runner/vimproc/updatetime' : 60,
  \     'outputter/error/success' : 'buffer',
  \     'outputter/error/error'   : 'quickfix',
  \     'outputter/buffer/split': ':botright 8sp',
  \     'hook/time/enable': '1'
  \    },
  \   'bundle_ruby': {
  \     "vimproc/sleep"    : 0,
  \     "outputter/buffer/into" : 1
  \   }
  \ }
```

### bundle_rubyを実行する専用コマンドを定義

必ず1回は`QuickRunBundleRuby` に引数を渡す必要がある
=> なければエラー

1回渡せば次回からは前回の値をそのまま使用する

再度渡せば、設定値を変更して実行

```vim
function! s:bundle_ruby(...)
  if !exists("g:my_quickrun_config")
    let g:my_quickrun_config = {}
  endif

  if exists("a:1")
    let g:my_quickrun_config["bundle_gem_path"] = a:1
  elseif !has_key(g:my_quickrun_config, "bundle_gem_path")
    echom "require temporary bundle_gemfile_dir path"
    return
  endif

  echom "env BUNDLE_GEMFILE=". g:my_quickrun_config["bundle_gem_path"]. "/Gemfile bundle exec ruby %o %s:p "
  let g:quickrun_config["bundle_ruby"]["exec"] = "env BUNDLE_GEMFILE=". g:my_quickrun_config["bundle_gem_path"]. "/Gemfile bundle exec ruby %o %s:p "
  exe "QuickRun bundle_ruby"
endfunction
command! -nargs=? QuickRunBundleRuby call s:bundle_ruby(<f-args>)
```

めでたしめでたし
iframe内のリンクを使いたくない時

2020/08/17
instawidgetがサービス終了した上に、代替サービスでよく使われてる（であろう）instawindowではiframeを採用してないのでこの記事自体要らなくなってしまった。。
https://insta-window-tool.web.app/

ただ、iframe内のリンクで困ったときのために残します。

instawidgetをサイトに埋め込み時、リンク先を自由に設定することができない
（instawidgetの記事URLに飛んでしまう）

自由なURLを設定したかったのでiframeのクリックイベントをjsで制御しようとしたけどレイヤーの関係なのかうまく制御できず、、

CSSでiframe内のクリックを無効にできるのでそっちでできた。

```html
<script src="https://instawidget.net/js/instawidget.js?u=ce6e9e4a15482922f195a1fe83cda9ecb592598bf296f3cd907e3d67fc24b0ee&width=300px"></script>
```

↓

```html
<a href="http://google.com" target="blank" id="hoge">
<script src="https://instawidget.net/js/instawidget.js?u=ce6e9e4a15482922f195a1fe83cda9ecb592598bf296f3cd907e3d67fc24b0ee&width=300px"></script>
</a>
<style>
#hoge {
	display:block;
}
#hoge iframe{
	pointer-events: none;
}
</style>
```

これでできる。
ls -l での時刻表示をエポックに


gnu coreutils の ls の `--time-style` オプション


```
$ ls -l --time-style='+%s.%N' 
```


わざわざ、ls --full-time から  => epoch してたよ。

- `%N` 付ければ、nanosecondまで表示出来る。
- long-iso とか full-iso とかを与えれば、ISO 8601 にしてくれる
Google Colaboratory での Terminal 操作 (メモ)

# Google Colaboratory で コマンド実行
Google Colaboratory で Linux コマンドを対話型 Terminal で実行したい.

2022/8/1 更新
# colab-xterm を使う

これでいけるらしい、簡単。
```bash
!pip install colab-xterm
%load_ext colabxterm
%xterm
```
https://github.com/InfuseAI/colab-xterm

お試し程度にして、pro版をちゃんと使ったほう良いです。

## 過去の方法

Python製 Shell を入れる.

```terminal:インストール
!pip install xonsh==0.9.2
```

それを実行する.

```terminal:実行
!xonsh
```

これで Linux コマンドを打ち込める.
ABC092 C - Traveling Plan (300点)

[問題のリンク](https://atcoder.jp/contests/abc092/tasks/arc093_a)

#問題概要
要素数$N$の配列$A$が与えられる。
数直線上に配列$A$の各要素が並んでいる。原点からスタートして$A(i)$への移動を繰り返し、再び原点に戻ってくる。この時、点$a$から点$b$への移動は$|a-b|$円かかる。
$i = 1, 2, ..., N$について点$i$への移動をとりやめた時にかかる金額の総和をそれぞれ求めよ。

#制約

- $2 \leqq N \leqq 10^5$
- $−5000 \leqq A(i) \leqq 5000(1 \leqq i \leqq N)$
- 入力値はすべて整数である。


#考えたこと
まず配列$A$から要素$A(i)$を抜いた配列を作り総和を取っていくのを$N$回繰り返すというやり方が思いつくが、制約条件で$N$が最大$10^5$なので$O(N^2)$だと計算量が$10^{10}$となり、かなり厳しい。

なので$for$文一つにして計算量を$O(N)$に収めたい。

ここでまず配列Aの要素間の差分の総和をとってうまく引き算したらよさそうと考えて、入力例で実験した。

>入力例1
3
3 5 -1

すると以下のように点の移動と点から点への移動コストが整理される。
![20190311_ABC092c.001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/326440/0235f349-edb8-1a9c-2e86-c22504675ad9.jpeg)




この図から配列Aの両端に0を追加し、 $B[i]=|A[i]-A[i+1]|$ となる配列Bを作り、配列$B$の総和から、 $B[i]+B[i+1]$ を引き、 $|A[i]-A[i+2]|$ を足せば求める値が出せることがわかる。

例えば、上記の入力例で言うと、移動のとりやめを考慮しない時の総和は12。
点$i=0$の時、$B[0]=3$と$B[1]=2$を$B$の総和から引いて、$|A[0]-A[2]|=5$を$B$の総和に足す。

あとは出力すればおーけーです。これをN回繰り返すだけ。

ロジックを簡潔に示すと以下のようになる。

```
a.sum()
- (abs(a[i] - a[i - 1]) + abs(a[i + 1] - a[i])) //=b[i] + b[i+1]
+ abs(a[i + 1] - a[i - 1])
```


#解答
```c.cs
using System;
using System.Linq;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args) {
        int n = int.Parse(Console.ReadLine());
        List<int> a = new List<int>();
        a.Add(0);
        a.AddRange(Console.ReadLine().Split().Select(int.Parse).ToArray());
        a.Add(0);
        List<int> b = new List<int>();
        for (int i = 0; i < n+1; i ++) b.Add(Math.Abs(a[i]-a[i+1]));
        int sum = b.Sum();
        for (int i = 0; i < n; i ++) {
            int result = sum;
            result -= b[i]+b[i+1];
            result += Math.Abs(a[i]-a[i+2]);
            Console.WriteLine(result);
        }
    }
}
```

#犯したミス
ACするまでの過程で犯したミスを書いておきます。

1. 上記の解法を実際のコードに落としていく時にループごとに `result` を初期化するのを失念していた。
2. 1.の解消のためにbの総和を取るのをfor文中に入れたらTLEした。以下の記事を参照すると、計算時間は for < foreach < Sumとなっている。よって今回の問題ではfor文中にsumを入れると$O(N^2)$となるので避けるべき。

[forとforeachとSumにおける実行速度の違い](http://barikata.hateblo.jp/entry/20131010/1381388886)

これぐらいですかね。他はインデックスに気をつけるとかです。
あと僕はC#で書いてるので、配列をListにして扱うほうが動的な処理が可能なのでよいかと思います。
npm -g install に失敗した時の解決方法

なぜか`npm -g install`に失敗する
解決法が記載されていたので、自分的にも備忘録として記録

参考URL
[【備忘録】npm -g install に失敗する - Qiita](https://qiita.com/NaokiIshimura/items/cc07441939b226e779c6)


```console
$ mkdir ~/.npm-global
$ npm config set prefix '~/.npm-global'
$ echo ' export PATH=~/.npm-global/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile
```

上記を入力する事で解決

`npm -g install xxx`に成功！！
ブレッドボードに5.0V供給する その1

#はじめに

本記事を試す場合は必ず自己責任でお願いします。
まずは準備として、ブレッドボードに電力の供給を試みました。

#使用したもの
 - ブレッドボード
 - ジャンパーワイヤー
 - 半固定抵抗102 (抵抗買うの忘れた)
 - LED
 - ワニ口クリップ付きUSBケーブル (今回のメイン)

ワニ口クリップ付きUSBケーブルにジャンパーワイヤーをつないでコンセントにさしました。
家庭用コンセントなので5Vになるはずです。きっと。
![IMG_20190311_194337.jpg](https://qiita-image-store.s3.amazonaws.com/0/246294/ed00dd87-e88b-fdd6-b42f-4ff9a3ebccbc.jpeg)
これにUSB充電器の下のアレを接続し、ジャンパーワイヤーを噛ませます。
![IMG_20190311_202744.jpg](https://qiita-image-store.s3.amazonaws.com/0/246294/bab7f010-6886-1d20-acde-b07cf067b8c6.jpeg)

#ブレッドボードで回路を組む
ブレッドボードで回路を組みます。
抵抗を買い忘れてしまったのですが、幸い半固定抵抗がありました。
![IMG_20190311_202845.jpg](https://qiita-image-store.s3.amazonaws.com/0/246294/566a4570-3182-e4eb-3f88-d35649c299c6.jpeg)

コンセントをさすとLEDが光ります。
![IMG_20190311_202913.jpg](https://qiita-image-store.s3.amazonaws.com/0/246294/08eb577d-9db7-7ab9-585b-ae0186ea7f6f.jpeg)

#おわりに
友人が、ワニ口クリップはショートする恐れがあるから気を付けてね。と言っていました。
露出してる部分ですね。
次はロジックICを使用してAND回路かOR回路をやりたいと思います。

#日記一覧へ
[ロジックIC日記 一覧](https://qiita.com/C_Assembly/items/fa1e78643e7a52fe9e4b)
Androidアプリが落ちてしまいます。ボタンをクリックするだけで落ちます。

このようなエラーが出ます。
どこがおかしいのでしょうか。

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference

以下がコードとなっています。

package com.example.tokoroshingo.myapplication;

import android.content.Intent;
import android.content.res.Resources;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Context;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;


public class FileActivity1 extends AppCompatActivity {

    private TextView textView;
    private EditText editText;
    private String fileName[] = new String[15] ;
    private int i;
    private Button buttonRead[] = new Button[15];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_file1);

        textView = findViewById(R.id.text_view);


        for(i=0; i<15; i++){
            fileName[i] = "CH1_"+i+1+".txt";
            int viewId;
            String resViewName;
            resViewName = "button_ch" + i+1;
            viewId = getResources().getIdentifier(resViewName, "id", getPackageName());
            buttonRead[i] = findViewById(viewId);
            buttonRead[i].setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String str = readFile(fileName[i]);
                    if (str != null) {
                        textView.setText(str);
                    } else {
                        textView.setText(R.string.read_error);
                    }
                    TextView textReceive1 = (TextView) findViewById(R.id.text_view1);
                    textReceive1.setText("CH"+ i);
                }
            });

        }


        //  editText = findViewById(R.id.edit_text);



        Button return_file_Button1 = findViewById(R.id.return_file_button1);
        return_file_Button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplication(), SubActivity5.class);
                startActivity(intent);
            }
        });


    }


    // ファイルを読み出し
    public String readFile(String file) {
        String text = null;

        try {
            FileInputStream in = openFileInput(file);
            BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            String str = "";
            String tmp;
            while ((tmp = reader.readLine()) != null) {
                str = str + tmp + "\n";
            }
            text = str;
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return text;
    }
}
BashスクリプトをJavaで実行してみよう

#はじめに
JavaにおいてProcessbuilderだとかRuntimeでプロセスを作ってあげると、Linux上の挙動とは必ずしも同一でない振る舞いをすることがあります。
一時的に「bashスクリプト(シェルスクリプト)」をつくってあげて、それを実行してあげると、望み通りの挙動になるかもしれません。

#コード

```java

public void executeCommands() throws IOException {

//一時ファイル作成
    File tempScript = createTempScript();

    try {
        //スクリプト実行
        ProcessBuilder pb = new ProcessBuilder("bash", tempScript.toString());

       //エラー出力
       try (BufferedReader buffer = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
               System.out.println(buffer.lines().collect(Collectors.joining("\n")));
       }

      //標準出力
      try (BufferedReader buffer = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
               System.out.println(buffer.lines().collect(Collectors.joining("\n")));
       }
        Process process = pb.start();
        process.waitFor();
    } finally {
        //一時ファイル削除
        tempScript.delete();
    }
}

public File createTempScript() throws IOException {
    //一時ファイル作成
    File tempScript = File.createTempFile("script", null);

    Writer streamWriter = new OutputStreamWriter(new FileOutputStream(
            tempScript));
    PrintWriter printWriter = new PrintWriter(streamWriter);

    //スクリプトを書いていく。
    printWriter.println("#!/bin/bash");
    printWriter.println("cd bin");
    printWriter.println("ls");

　　//書き込み終了
    printWriter.close();

    return tempScript;
}
```





#参考（これのパクリ）
https://stackoverflow.com/questions/26830617/running-bash-commands-in-java