OmniAICreator/Qiita-1.07M huggingface dataset:
Seleniumの実行時間をJUnitのClassRuleアノテーションで高速化する

# はじめに
Seleniumでテストしている時、テストメソッド単位でブラウザの起動/終了が行われるのが一般的（だと思っている）。
ただ、毎回ブラウザの再起動をすると実行時間がかなり伸びるので短縮したかった。

方法は色々あると思うが、今回はJUnit4のClassRuleアノテーションでやってみた。
ClassRuleで宣言すればWebDriverのnew/quitがテストクラス単位にできるので、それなりに短縮になる。

↓Rule/ClassRuleについては、こちらの方が分かりやすく纏めてくださっていました。
http://qiita.com/Chayata/items/dd31e22bca6df6c91793

# 実装
Ruleアノテーションを利用するには専用のクラスを実装し、テストメソッドのフィールドにする必要がある。
詳細は[こちらのリポジトリ参照](https://github.com/knakamatsu/SeleniumJUnitRuleSample)
### Rule側
ExternalResouceを継承してクラスを実装し、クラスのフィールドとしてWebDriverを生成しておく。
Overrideしたafterメソッドがjunitの後処理になるので、WebDriverのquitをafterに実装する。

```WebDriverRule.java
public class WebDriverRule extends ExternalResource {

	private WebDriver driver;
	public WebDriver getDriver() {
		return getInstance();
	}

	@Override
	protected void after() {
		this.driver.quit();
	}

	private WebDriver getInstance(){
		if(this.driver == null){
			this.driver = new ChromeDriver();
		}
		return this.driver;
	}
}
```

### テスト実行側
実装したRuleクラスは @Rule と @ClassRule の両方で使うことができそれぞれ以下のようになる。
@ClassRuleで宣言すると before/afterがクラス単位の前後処理に相当し（@BeforeClass と @AfterClass）
@Ruleで宣言すると before/afterがメソッド単位の前後処理に相当する（@setUp と @tearDown）

```Test.java
public class classSample {
	@ClassRule
	public static WebDriverRule dr = new WebDriverRule();

	@Test
	public void test(){
		WebDriver d = dr.getDriver();
		d.get("https://www.google.co.jp/");
		WebElement el = d.findElement(By.cssSelector("input[aria-label='検索']"));
		el.sendKeys("chrome test.");
	}
}
```


# 比較
![QS_20170513-195323.png](https://qiita-image-store.s3.amazonaws.com/0/153339/ea208531-f2ba-3f2e-f530-65165cf5523a.png)
上側が@ClassRule、下側が@Ruleでの実装。 実行するテストは両方同じ。
サンプルで作ったテストクラスでは、10秒くらい差がある。
ClassRuleの場合はブラウザの起動が初回のテストメソッドのみなので、テストメソッドが多いほど効果がある。
テスト環境ではブラウザ起動に5秒程度かかっていた。

# まとめ
テスト対象にもよるが、テストメソッド毎にブラウザ再起動するのは過剰な場合が多いので、こうしておくほうが好み。
ただ、テストメソッド間に依存関係が出来ても気づきずらいので（cookieに情報が残って偶然動くとか）注意は必要。
ElectronでフレームレスなYouTubeプレイヤーを作ってみた

# はじめに
MacのQuick Playerみたいな感じのYouTubeプレイヤーが欲しかったので作りました。
名前は、「Shuvi」です。

ダウンロードは下記のアドレスから。
[https://github.com/yuki540net/Shuvi/releases/tag/v0.0.1](https://github.com/yuki540net/Shuvi/releases/tag/v0.0.1)

Mac/Windows/Linux向けにパッケージしていますが。Mac以外は動作確認していないので動作の保証はできません。

![shuvi.png](https://qiita-image-store.s3.amazonaws.com/0/77608/32a1b2a9-40b0-5ee8-2c71-72e39def5bbd.png)

### 動作確認

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ElectronでフレームレスなYouTubeプレイヤーを作りました。<br>自由にリサイズできるのが特徴です。<br>名前は、「Shuvi」です。<br><br>GitHub: <a href="https://t.co/Bksmy2HZFw">https://t.co/Bksmy2HZFw</a><br>Download: <a href="https://t.co/HNHLcSMifc">https://t.co/HNHLcSMifc</a> <a href="https://t.co/ZAibALDOme">pic.twitter.com/ZAibALDOme</a></p>&mdash; yuki540 (@eriri_jp) <a href="https://twitter.com/eriri_jp/status/863369467618668544">2017年5月13日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

# 内容
動画の再生部分は、YouTubeのiframe APIを使いました。

提供されているJavaScriptファイルを読み込んで、

```javascript
<script src="https://s.ytimg.com/yts/jsbin/www-widgetapi-vflHJ3SDg/www-widgetapi.js"></script> 
```

``` YT.Player ```を使えば、iframeが埋め込まれます。
あとは、``` player ```を使って、再生・停止などを各コンポーネントから制御すれば簡単にプレイヤーを作ることができます。

```coffeescript
player = new YT.Player 'player', {
  width   : width
  height  : height
  videoId : '動画ID'
  events  : {
    onReady: (e) =>
      console.log '読み込み終了'
  }
}
```

YouTube iframe APIのリファレンスは下記のアドレスです。
[https://developers.google.com/youtube/iframe_api_reference?hl=ja](https://developers.google.com/youtube/iframe_api_reference?hl=ja)

YouTube iframeのパラメータ類は下記のアドレスです。
[https://developers.google.com/youtube/player_parameters?hl=ja](https://developers.google.com/youtube/player_parameters?hl=ja)

# Shuvi - シュヴィ
ということで、完成したものがこちらです。
よくある動画再生プレイヤーのUIですね。

<img width="555" alt="top.png" src="https://qiita-image-store.s3.amazonaws.com/0/77608/49a6b855-7b7d-507c-6def-cb8172a0d56b.png">

動画の再生は、上のテキストボックスにYouTubeの動画URLを入力し、検索アイコンのボタンをクリックするだけです。

<img width="555" alt="search.png" src="https://qiita-image-store.s3.amazonaws.com/0/77608/c6601a7d-011e-ea58-9284-39ea429d8252.png">

タイトルバーの右のメニューアイコンのボタンをクリックすると、過去に再生した動画の履歴を見ることができ、再度URLを入力することなく、動画を再生することができます。

<img width="555" alt="list.png" src="https://qiita-image-store.s3.amazonaws.com/0/77608/a995e195-2f03-ab98-7dd6-85e1549e63d0.png">

また、Shuviの特徴は、大きさや形にとらわれることなく、ウィンドウをリサイズすることができることです。
作業スペースにあった動画サイズで視聴することができます。

<img width="1029" alt="transform.png" src="https://qiita-image-store.s3.amazonaws.com/0/77608/cd660de1-4439-057a-9371-d493da4dc527.png">

<img width="1440" alt="scale.png" src="https://qiita-image-store.s3.amazonaws.com/0/77608/cdc27ee6-8cb4-690a-8171-78456a4f022c.png">

# おわりに
技術内容がほとんどない記事で申し訳ないのですが、YouTube　iframe APIを使ったソフトウェアを作ってみてすごく楽しかったので、これから別のものも作ってみようと思います。

Shuviも、もうちょっと便利にプレイリストなんかを追加できるよう開発していきたいと思います。

Shuviのソースコードは、GitHubで公開してますので、よければStarください。
GitHub: [https://github.com/yuki540net/Shuvi](https://github.com/yuki540net/Shuvi)
Twitter: [@eriri_jp](https://twitter.com/eriri_jp)
Bootstrapでレイアウトを調整する方法

![グリッドレイアウト.png](https://qiita-image-store.s3.amazonaws.com/0/160563/850bf9b5-80a9-a9e8-968c-d31089b349db.png)

#利用シチュエーション

* Bootstrapを用いてカラムレイアウトを自由自在に活用したい時


#記述方法
##.container
containerはコンテンツの全体を覆うクラス。
大枠を「.container」で囲むと覚えておけばOK!

```html:qiita.rb
<section class="container">
</section>
```
containerはブラウザの幅に応じて横幅のサイズが異なる。

|名称|ブラウザ幅|.container幅|
|:---|:---|:---|
|Extra Small|544px未満|画面幅いっぱい|
|Small|544px以上768px未満|576px|
|Medium|768px以上992px未満|720px|
|Large|992px以上1200px未満|940ox|
|Extra large|1200px以上|1140px|
※ .container-fluidを使うと上記の表に関係なく画面幅いっぱいに広がる

##.row
横一列の大枠に付与するクラス。

```html:qiita.rb
<section class="container">
  <div class="row">
  </div>
</section>
```

##.col
左から右にcolのクラスを指定したコンテンツを並べる。

> .col-画面幅-グリッド数

```html:qiita.rb
<section class="container">
  <div class="row">
    <div class="col-md-3"></div>
    <div class="col-md-3"></div>
    <div class="col-md-3"></div>
    <div class="col-md-3"></div>
  </div>
</section>
```

* 画面幅は.containerの画面幅のときにサイズを指定

|Extra small|Small|Medium|Large|Extra large|
|:---|:---|:---|:---|:---|
|.col-xs-|.col-sm-|.col-md-|.col-lg-|.col-xl-|

* グリッド幅は足して12になるまでを一列に配置

> .colの指定は複数も可能
> (例)Mediumの時は横幅の「1/4」 Extra smallの時は「1/2」

```html:qiita.rb
<div class="col-md-3 col-xs-6"></div>
```
Oracle Preinstall RPMとRed Hat Best Practiceの違い

# Oracle Database向けのOSチューニング
  Oracle DatabaseをLinux環境にインストールし、高速に稼働させるためにいくつかのチューニング・ポイントがあります。特にカーネル・パラメーターについてはインストール要件に加えていくつか推奨項目があります。Best Practiceと言えるカーネル・パラメーターの値には以下の２種類の根拠があります。

- Oracle Preinstall RPMパッケージ
- Red Hat Best Practices

Oracle Preinstall RPMはOracle Linux向けのRPMパッケージで、カーネル・パラメーターの設定からブート設定等多くの設定項目を自動的に実施するRPMです。一方、Red Hat Best PracricesはRed Hatが提供するBest Practiceです。この両者の設定がどのように異なるかを検証してみました。

# Red Hat Best Practicesのインストール
[2016 - Deploying Oracle RAC Database 12c on RHEL 7 - Best Practices] (https://access.redhat.com/articles/1357883)からdeploying-oracle-rac-12c-on-rhel7-v1.2-updated-july-27-2016.tar.gzファイルをダウンロードし、任意のフォルダに展開します。

以下のファイルが作成されます。

|ファイル名|内容|
|:---|:---|
|req-rpm.txt|Oracle Databaseのインストールに必要なパッケージのリスト|
|huge_page_settings.sh|最適なHuge Pageのページ数を計算するスクリプト|
|multipath.conf|Device Mapper Multipath設定ファイル|
|sysctl.conf|推奨カーネル・パラメーターのリスト|
|99-grid-oracle-limits.conf|ユーザー制限（limits.conf）|
|99-oracle-asmdevices.rules|ASM用udev設定ファイル|
|public.xml| firewalld用XML
|oracle-grid.sh|ユーザー制限(ulimitコマンド)を実行するシェル・スクリプト|
|sample-ks.cfg| Kickstart Fileのサンプル
|CHANGELOG|変更ログ|


# カーネル・パラメーターの変更
Oracle Preinstall RPMとRed Hat Best Practiceのカーネル・パラメーター推奨には以下のような差があります。

|パラメーター|Oracle|Red Hat|
|:---|---:|---:|
|vm.swappiness|なし|1|
|vm.dirty_background_ratio|なし|3|
|vm.dirty_ratio|なし|80|
|vm.dirty_expire_centisecs|なし|500|
|vm.dirty_writeback_centisecs|なし|100|
|fs.file-max|6815744|6815744|
|kernel.sem|250 32000 100 128|250 32000 100 128|
|kernel.shmmni|4096|4096|
|kernel.shmall|1073741824| 1073741824|
|kernel.shmmax|4398046511104|4398046511104|
|kernel.panic_on_oops|1|1|
|net.core.rmem_default|262144|262144|
|net.core.rmem_max|4194304|4194304|
|net.core.wmem_default|262144|262144| 
|net.core.wmem_max|1048576|1048576|
|net.ipv4.conf.all.rp_filter|2|なし|
|net.ipv4.conf.default.rp_filter|2|なし|
|fs.aio-max-nr|1048576|1048576| 
|net.ipv4.ip_local_port_range|9000 65500|9000 65500| 

# /etc/security/limits.confの差
Oracle Preinstall RPMではdomainが*になっていますが、Red Hatの設定ではoracleユーザーとgridユーザーがそれぞれ設定が書かれています。
Red Hat Best Practiceのmemlock値はhuge_pages_settings.shスクリプトで計算するように指示されています。

|type|item|value (Oracle)|value (Red Hat)|
|:---|:---|---:|---:|
|soft|nofile|1024|1024|
|hard|nofile|1024|65536|
|soft|nproc|16384|2047|
|hard|nproc|16384|16384|
|soft|stack|10240|10240|
|hard|stack|32768|32768|
|soft|memlock|134217728|計算|
|hard|memlock|134217728|計算|

# 終わりに
カーネル・パラメーターについては、Oracle Preinstall RPMがインストールに必要な最小限の設定を行っているのに対し、Red Hat Best Practiceではより積極的な値の変更を行っている印象です（Oracle Linuxではデフォルト値が変更されている可能性がありますが）。
Nukkit+DockerによるMinecraft PE/Win10 マルチサーバー構築メモ

# NukkitをDockerを用いて構築するメモ
## 1, Dockerをインストールする。
```
apt-get install docker
```
とか。

## 2, NukkitのDockfileを取得する
いろいろ試した結果、[ixilon/nukkit](https://hub.docker.com/r/ixilon/nukkit/)のものが良い模様

```
docker run -it -p 19132:19132/udp -v [データを置きたい場所へのフルパス]:/srv/nukkit ixilon/nukkit
```
※サーバーのポートは任意で開く

```
iptables -I INPUT 6 -p tcp -m state --state NEW -m udp --dport 19132-j ACCEPT
```
とか。

## 3, Nukkitの設定を行う
このとき、言語設定が文字化けするため、languageはengを指定する。あとは通常通り。
設定と動作確認が完了したら、stopと打ち込みターミナルを終了する。

## 4, サービスとして走らせる
```
docker run -p 19132:19132/udp -v [データを置きたい場所へのフルパス]:/srv/nukkit ixilon/nukkit
```

## 5, Nukkitを更新する
最新のスナップショットからNukkitを取得する。

```
docker pull nukkit:latest
```

## 6, 動作中のNukkitにアクセスする
このコマンドで、動作中のNukkitのコマンドプロンプトにアクセスできる。

```
docker attach [Nukkitのコンテナ名]
```

# Appendix
## AsustorのNASにこの環境を設置する
1. App Centralから、ベータ版アプリボタンを押す。
2. Dockerがあるのでこれをインストールする
3. root権限でsshでNASにアクセスし、上記コマンドを実行する。データを起きたい場所へのフルパスは`/volume1/home/admin/nukkit`がいいと思う。
4. あとは同じ。
gitでmergeされてないbranchを調べたい


よく忘れてしまうのでメモします。


### まだmergeされていないbranchを調べる

```
$ git branch --no-merged
```

### すでにmergeしたbranchを調べる

```
$ git branch --merged
```

### 全てのbranchを確認したい

```
$ git branch
```

自分は　git fetch する前の確認などでよく使ってます。
JavaScriptで時間を曖昧に表す

# 概要
時間を曖昧に変換する

## 例
- 3分45秒 => 4分
- 28分45秒 => 25分
- 2時間25分45秒 => 2時間
- 3日2時間25分45秒 => 3日

# ソース
```js
function count(ms) {
	let unit = ["日","時間","分","分","秒"],
			vari = [86400000,3600000,60000,60000],
			inte = 1,
			leve = 4;
	if(ms>1000*60      ) {inte=1000*60;leve=3}
	if(ms>1000*60*10   ) {inte=1000*60*5;leve=2}
	if(ms>1000*60*60   ) {inte=1000*60*60;leve=1}
	if(ms>1000*60*60*24) {inte=1000*60*60*24;leve=0}
	return (Math.round(ms/inte)*inte)/vari[leve]+unit[leve]
}
```
## 使い方
引数にミリ秒を入れるだけ
Riotで同人イベントの告知ページを作ったよという話

## まえがき
Riot良さそうなんだけど触る機会なかなか無いしなあと思ってたところで、
制作を依頼された同人イベントの告知サイトを制作した事例メモです。

## なぜRiotなのか
* React / Vuejsなどのフレームワークは触ったことはないけれど、なにか触ってみたい
* 触りやすそうなフレームワークって何だろう→Riotだと学習コスト低そう
* （Reactも良さそうなんだけど、JSXのコードがエグいなあって思ってしまい敬遠…）
* HTMLそのままで書けるんだ、なんならpugでも書けるの良いね  
（とはいえemmet使ってHTML書いた方が速いかなあと思いました。tag使い回せば良いし。）
* CSSもsassで書けるじゃん、JSも当然のようにES6で書けるのね
* でも要件としては特に必要無いんじゃない？  
→「技術触ってみたい」は魔法の合言葉

## 制作の流れ
* HTML/CSSコーディング  
普段と同じ感覚ですね。共通部分は子タグで共通化できるのでちょっと楽できる感じ。
* コンテンツの中身はJSONで書いておいて読み込み（さすがにAPIとか用意するほどではなかった）
* 適当にロジック書いていく
* アニメーションなど追加したり

### observableの利用
疎結合を維持できるので便利だなあという感想。

具体的に言うと、アニメーション連携あたり。

1. アクセス時にはローダー画面を表示させておく(z-indexで最前面に設定した状態)
2. 画像ロード完了時のハンドラーをobserverに登録しておく
3. ロード完了したら（ローダー周りの処理で）observerを叩く
4. observerは登録されているハンドラーを叩く
5. tag内のアニメーションイベントが走る

という流れです。

## ハマりどころ
というか正直公式のドキュメントが読みづらく感じるのは僕だけでしょうか……

### JSONからHTML要素を書き出そうとしてもテキストとして出力されてしまう
XSS対策とかセキュリティ的には正しい選択なのだけれど、何も考えないで組むと躓きますね…

答えは[公式ドキュメント](http://riotjs.com/ja/guide/#エスケープしないでhtmlを表示する)にあった。
子タグを呼び、そこを通してinnerHTMLを書き換えてもらう感じ。

```html:raw.tag
<html-raw>
<script>
//※データの都合上、文字列 or 文字列を適宜分割した配列を想定
opts.content = (typeof opts.content == 'string') ? opts.content : opts.content.join('');
this.root.innerHTML = opts.content;
</script>
</html-raw>
```


## 感想
### Riotを使用したメリット
さすがにSPAライクなページじゃないと真価を発揮していない感はある。
けれど、ペライチのWebページでもセクションごとにtag分割したり使い回して書けるので、
比較的コードの見通しがよくなりやすいなあという感じ。

特に、見た目にこだわりたい案件ではエフェクトも複雑になりがちで、
アニメーション周りのコードがクッチャクチャになりやすい……。
ので、関係するtag内でコードが完結できるのは大きなメリットかも。
今回はやらなかったけど、スタイルも1つのtagにまとめて書けるしね。
うまくやれば、ローダーみたいな部品はtagひとつコピーするだけでコードに手を入れず使い回しできるので後々楽そう。
このへん他のフレームワークだとやりづらそうなので、Riotならではなのかな？

後々のページ追加のタイミングではあまり時間が無かったため、
別案件の使い回しHTMLを用意してしまった、ので、Riotでやったメリットが薄れてしまった結果に。
次回以降はrouterなんかを使って上手いことやりたいです。

### Observableの利用で、イベントのハンドリングが楽
複数タグまたぎでもイベントのハンドリングが容易。なので上述のようなイベント連携が書きやすい！
……とはいえ、これは僕がObserverパターンを知らなかっただけなので、べつにRiotのメリットではないですね。

### ノウハウの集積
React / Vue あたりと比べるとユーザーが少ないので、あまりノウハウが転がってないなあというのが一番苦労したポイントかなあとは思います。
学習コストは低いのかもしれないけど、流石に全くフレームワークを触ったことがない状態だと、サンプルとかあまり見ないで触ろうとするとツラいですねー……。
あと公式のドキュメントがイマイチ読み辛いのがしんどかった。。

とはいえ触ってて楽しいは楽しいので、別の案件でも使ってみようかなとは。
Python3 で Twitter をサーチ

次のプログラムは、"python" というキーワードのサーチの例です。

```py:search_twitter.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	search_twitter.py
#
#						 Apr/26/2019
# --------------------------------------------------------------------
import sys
import json
from requests_oauthlib import OAuth1Session
from config_twitter import config_twitter_proc
# --------------------------------------------------------------------
def tweet_search(search_word):
	url = "https://api.twitter.com/1.1/search/tweets.json?"
	params = {
	"q": search_word,
	"lang": "ja",
	"result_type": "recent",
	"count": "5"
	}

	twitter = config_twitter_proc()
	responce = twitter.get(url, params = params)
	if responce.status_code != 200:
		print("Error code: %d" %(responce.status_code))
		return None
	tweets = json.loads(responce.text)
	return tweets
#
# --------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
key_word = "#python"
tweets = tweet_search(key_word)
#
for tweet in tweets["statuses"]:
	tweet_id = tweet[u'id_str']
	text = tweet[u'text']
	created_at = tweet[u'created_at']
	user_id = tweet[u'user'][u'id_str']
	user_description = tweet[u'user'][u'description']
	screen_name = tweet[u'user'][u'screen_name']
	user_name = tweet[u'user'][u'name']
	print("tweet_id:", tweet_id)
	print("text:", text)
	print("created_at:", created_at)
	print("user_id:", user_id)
	print("user_desc:", user_description)
	print("screen_name:", screen_name)
	print("user_name:", user_name)
#
sys.stderr.write("*** 終了 ***\n")
# --------------------------------------------------------------------
```

```py:config_twitter.py
# --------------------------------------------------------------------
#	config_twitter.py
#
#					Apr/25/2019
# --------------------------------------------------------------------
import os
from dotenv import load_dotenv
from requests_oauthlib import OAuth1Session

# --------------------------------------------------------------------
def config_twitter_proc():
	dotenv_path = '.env'
	load_dotenv(dotenv_path)
	CONSUMER_KEY = os.environ.get("CONSUMER_KEY")
	CONSUMER_SECRET = os.environ.get("CONSUMER_SECRET")
	ACCESS_TOKEN = os.environ.get("ACCESS_TOKEN")
	ACCESS_TOKEN_SECRET = os.environ.get("ACCESS_TOKEN_SECRET")
#
	twitter = OAuth1Session \
		(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_TOKEN,ACCESS_TOKEN_SECRET)
#
	return twitter
# --------------------------------------------------------------------
```

```text:.env
CONSUMER_KEY = '******'
CONSUMER_SECRET = '******'
ACCESS_TOKEN = '******'
ACCESS_TOKEN_SECRET = '******'
```

Arch Linux でライブラリのインストール

```bash
sudo pacman -S python-requests-oauthlib
```

次の環境で動作を確認しました。

```text
$ uname -a
Linux iwata 5.6.13-arch1-1 #1 SMP PREEMPT Thu, 14 May 2020 06:52:53 +0000 x86_64 GNU/Linux

$ python --version
Python 3.8.3

```
画面サイズに応じて適用するスタイルを変更する方法

![サイズ振り分け.png](https://qiita-image-store.s3.amazonaws.com/0/160563/c83764de-b923-e148-f569-9daf72102cc8.png)


#利用シチュエーション

* デバイスサイズに応じて適用するスタイルを変更したい時


#記述方法
## デバイスの幅で適用するCSSをCSSファイルに直接記載

```css:qiita.rb
@media screen and (min-width:横幅サイズ) {
  ."クラス名"{
  }
}

/* 記述例 */
@media screen and (min-width:480px) and (max-width:768px) {
  .sample{
  /* ここに適用したいCSSを記載 */
  }
}
```

## デバイスの幅で読み込ませるCSSを変更

```html:qiita.rb
<link rel="stylesheet" href="style.css" media="screen and (max-width:横幅サイズ)">

<!-- 記述例 -->
<link rel="stylesheet" href="style.css" media="screen and (max-width:1040px)">
```

###Tips
* スマートフォンの縦表示・横表示で適用するCSSを変更する方法

```css:qiita.rb
/*縦向き*/
@media screen and (orientation:portrait){
  .sample{
  }  
}

/*横向き*/
@media screen and (orientation:landscape){
  .sample{
  }  
}
```


#デバイスサイズの目安

|デバイス|サイズ|
|:---|:---|
|スマートフォン|480px|
|タブレット|768px|
|PC|1040px|
【しずおかアプリ部】活動ログ　第39回

![しずおかアプリ部2.jpg](https://qiita-image-store.s3.amazonaws.com/0/88105/ee800648-fa25-1829-20c3-bad9c2055d35.jpeg)

##■公式サイト##
[http://monolizm.com/shizuoka-app](http://monolizm.com/shizuoka-app)
「Slack」も利用しています。 shizuapp で検索し、ご参加ください。

##■タイトル##
第３９回


##■開催日##
２０１７年５月１３日（土）　１６：００～１８：００


##■参加者##
１１名


##■活動内容（概要）##
・最近の話題の技術ニュース、告知
・菅原プレゼン「Unityはじめるよ　～光と影～」
・部員さんプレゼン「Fusion360　実践・解説」
・部員さん自作のVRコンテンツが進化しました！
・TEA BREAK　＆　VR体験



##■活動内容（詳細）##

【実演・プレゼン】

**・最近の話題の技術ニュース、告知**
　　・[Unity１週間ゲームJAM](https://unityroom.com/unity1weeks/1)
　　・[SVGからパスアニメを作成　Lazy Line Painter](http://lazylinepainter.info/)
　　・[部員さんがWiiリモコンを使ってのインタラクティブなホワイトボード作成にチャレンジ](http://qiita.com/yaju/items/814a556704dfacdce58b)
　　・[Windows VRの本命か](http://panora.tokyo/27537/)
　　・[ゲームAIが遂げた驚異の進化史](http://news.denfaminicogamer.jp/interview/gameai_miyake)
　　・[Windowsで作ったiOSアプリが動く仕組み](http://ticktack.hatenablog.jp/entry/2017/05/13/022611)
　　・[U-22プログラミング・コンテスト2017](http://www.u22procon.com)
　　・スマホで簡単ホログラム
　　![IMG_7813.JPG](https://qiita-image-store.s3.amazonaws.com/0/88105/1b6c3e2f-1373-050c-2a9c-cf655539c7e2.jpeg)

<hr>


**・菅原プレゼン「Unityはじめるよ　～光と影①～」**
　　　モバイル向け（低スペック機種含む）ゲームでグラフィックのクオリティを上げたい。
　　　その手法について調査中である。
　　　今回はその途中結果を発表。

　　　■ライトマップ
　　　高負荷である光と影の計算を事前に行い、
　　　その情報をテクスチャに書き込んでおき、実行時の負荷を軽くする方法。

　　　メリット
　　　・実行時の負荷が少ない
　　　・高品質

　　　デメリット
　　　・スタティックなオブジェクトにしか使えない
　　　・ライトマップ用テクスチャ分のメモリとストレージを消費
　　　　　※広大なステージの場合など、
　　　　　テクスチャのサイズを大きくしてクオリティを保つか、
　　　　　テクスチャのサイズを抑えてクオリティを下げるかの検討が必要。

　　　ハマりポイント
　　　・自作モデルやアセットストアのモデルモデルデータを使うと、
　　　　　影が出なかったり、おかしな影になる場合がある。
　　　　　そんな時は、モデル読み込み設定の
　　　　　Model > Generate Lightmap Uvs
　　　　　にチェックを入れ読み込み直すと直る場合がある。

　　　　　それでも治らない場合はモデリングソフト上で、
　　　　　テクスチャのUV設定を行うと直るかも。

　　　・ハードによって使える機能が異なる。
　　　　　モバイル端末の大部分では、
　　　　　Lightmapping SettingsのDirectionalModeをNon-Directionalでないと動かなかったり。

　　<img width="1202" alt="スクリーンショット 2017-05-13 20.06.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/88105/eafe774e-96c3-150b-037c-0122eb0bbd89.png">


　　　　[第39回_プレゼン資料(～光と影～).pdf](http://monolizm.com/sab/pdf/第39回_プレゼン資料(～光と影～).pdf)



<hr>



**・部員さんプレゼン「Fusion360　実践・解説」**

　　　■Fusion360の実践・解説
　　　　フリーCADソフト「Fusion360」の使い方を日本語チュートリアルを見ながら進めた。
　　　　Fusion 360入門者向け日本語チュートリアル P４０～４３ 

　　　スケッチで文字を作成・切り取り操作・コピー（矩形状パターン・円計上パターン） を行いました。

　　　スケッチのテキストで文字を描き、押し出しを使って、コースターの表面を削る。
　　　カップがコースターに張り付かないよう、
　　　同様の手法で、スケッチで長方形を描き、押し出しを使って溝を掘る。
　　　その溝をコピーで増やし完成。

![IMG_7814.JPG](https://qiita-image-store.s3.amazonaws.com/0/88105/8b38f772-ea14-d191-5750-5131d1d8f7ad.jpeg)




　　[Fusio360の日本語チュートリアルはこちらから](http://www.myautodesk.jp/jeff/material.html)

<hr>



**・TEA BREAK**
　　　・部員さん自作のVRコンテンツが進化しました！
　　　　自作のVRコンテンツがほぼ完成となりました。
　　　　回転する椅子を利用した方向転換が直感的でした。
　　　　また、手に持つコントローラが増えていたり、確実にバージョンアップしていました。
　　　　当コンテンツの活かし方、蓄積されたノウハウを利用できる場を探し中です。
　　　　　![IMG_7817.JPG](https://qiita-image-store.s3.amazonaws.com/0/88105/17ee7d57-8029-8207-00c9-2b47bb8f478f.jpeg)
　


　　　・VR体験会
　　　　　　GoogleEarthが面白い！
WPFでCefSharp（Chromiumの.NET向け実装）を使う - 4

# 概要

今回はSchemeHandlerについて書きます。

webアプリを組み込んだネイティブアプリでwebからネイティブに何かを通知する方法は複数ありますが、最も一般的だと思われるのがカスタムURLスキームを利用する方法です。

CefにもカスタムURLスキームを利用してブラウザから通知を受ける仕組みが提供されています。

# カスタムURLスキームについて

```
hoge://fugafuga
```

みたいなやつです。

スマホのブラウザからgoogle map開いたりアプリストア開いたりできるのはこれのおかげです。

OSにデフォルトで定義されている挙動もありますが、Cefではその前の段階で挙動をハンドリングすることができます。

# ISchemeHandlerFactoryについて

カスタムURLスキームのハンドリングにはISchemeHandlerではなくIResourceHandlerを利用します。

URLは`<scheme>://<host>/<path&query>`となっていて、スキームごとにCefにハンドラを登録することができるのですが、直接ハンドラを登録するのではなくて、スキームのハンドラのファクトリをプロパティに持つカスタムスキームクラスをCefSettingsに登録する必要があって、手順が少し複雑です。

カスタムスキームとして"sample"を利用する場合には↓のようなコードになります。(sample://hogeみたいなurlに遷移しようとするとハンドラが呼び出される)

```Csharp
var CefSettings = new CefSettings();
var customScheme = new CefCustomScheme();
customScheme.SchemeName = "sample";
customScheme.SchemeHandlerFactory = new SchemeHandlerFactory();
cefSettings.RegisterScheme(customScheme);
Cef.Initialize(cefSettings);
```

## ISchemeHandlerFactoryの実装

ISchemeHandlerFactoryは、リクエストがあったときにそれに対応するハンドラを生成するCreateメソッドのみを実装すればOKです。

urlのホスト部で大きく処理を変えることが多いはずなので、ホスト部の処理ごとにハンドラを用意しておくのがいいと思います。

```Csharp
class SchemeHandlerFactory : ISchemeHandlerFactory
{
    public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
    {
        return new SchemeHandler();
    }
}
```

# SchemeHandlerについて

カスタムスキームのハンドリングするためのSchemeHandlerやそのインターフェースであるISchemeHandlerといったものは存在せず、IRequestHandlerを実装したクラスをカスタムスキームのハンドラとして利用します。

ありがたいことにIResourceHandlerにはデフォルトの実装をもったResourceHandlerクラスが存在するので、それを拡張してハンドラを実装しましょう。

実装する必要がある個所はProcessRequestAsyncのみです。

```Csharp
class SchemeHandler : ResourceHandler
{
    public override bool ProcessRequestAsync(IRequest request, ICallback callback)
    {
        // 何かrequest.Urlを見たりして処理する
        return false;
    }
}
```

~~falseを返しておけばリクエストがキャンセルされるので基本的にfalseを返しておけばいいと思います。~~

7/26追記

内部でasyncな処理とかをしてる時はfalseを返すと即座に処理が中断されちゃうので、trueを返したうえでasyncな処理が終わったタイミングでcallback.Cancel()を呼ぶのが正しいようです（リクエストをキャンセルする場合）。

[元記事](http://ghken.hatenablog.com/entry/2017/05/13/194820)
gulpでTwigレンダリングをなんとかしてみた話

## 追記・更新情報
2019/09/10： gulp4.x系で動くよう修正

## まとめ

テンプレートエンジンとしてTwig（をサーバサイドレンダリングする）案件が発生したけれど、
gulpで何とかできないの……？ということで、やってみた手順です。

それらしい情報がなかなか見当たらなかったのですが、
まあbrowser-sync使うにしてもローカルにXMAPP環境作ってproxyした方が早いよねって話ですかね……。
普段PHP触らないコーダーさんに環境をバラ撒く想定だったので、
フロントエンドな人の導入障壁の低そうなgulpで何とかしてみましたよー、というお話。

もろもろ構築済みのものがこちらです。
[twig-template](https://github.com/niltea/twig-template)

## いるもの
packages.json貼った方が早いすね。

```json:packages.json
{
  "dependencies": {
    "browser-sync": "^2.18.8",
    "gulp": "^3.9.1",
    "gulp-twig": "^0.7.0"
  }
}
```

## gulpまわりの動作など

ざっくり言うと

* gulp-twigでHTMLを生成
* それをbrowser-syncでリアルタイムプレビューする

という感じです。
下記は説明のためにザックリ抜き出しな感じですが、
必要に応じてsassなりbabelなんなりを追加すればよろしいかと。

```js:gulpfile.js
'use strict';
// settings
const $dist = './dist/';
const $twigSrc = ['./src/twig/**/*.twig'];
const $twigSrc_exclude = ['!./src/twig/**/_*.twig'];
// プレビュー表示用HTMLの生成先
const $htmlRoot = '__html/';

// import common packages
const gulp = require('gulp');
const plumber = require('gulp-plumber');

// twigをコンパイルする
gulp.task('twig', () => {
	const twig = require('gulp-twig');
	const _twigSrc = $twigSrc.concat($twigSrc_exclude);
	const _htmlRoot = $htmlRoot.replace(/\/$/, '');
	const _htmlDist = $dist + _htmlRoot;
	gulp.src(_twigSrc)
	.pipe(plumber())
	.pipe(twig({
		data: $twig_output_data,
		base: $twigBase
	}))
	.pipe(gulp.dest(_htmlDist));

	// twigテンプレートをdistへコピー
	// gulp 4.xではreturn valueが必要なのでひとまずreturnしておく
	return gulp.src($twigSrc).pipe(gulp.dest($dist));
});

gulp.task('server', () => {
	const browserSync = require('browser-sync');
	const _htmlRoot = '/' + $htmlRoot;
	browserSync({
		server: {
			baseDir: $dist,
			directory: false
		},
		middleware: (req, res, next) => {
			if (req.url.match(/\/$/)) {
				req.url = _htmlRoot + req.url.match(/(.*)\/$/)[1] + '/';
			} else if (req.url.match(/html?$/)) {
				req.url = _htmlRoot + req.url;
			}
			return next();
		}
	});

	gulp.watch(`${$dist}**/*.html`).on('change', browserSync.reload);
});

gulp.task('watch', () => {
	gulp.watch($twigSrc, gulp.series(['twig']));
});
gulp.task('default', gulp.parallel('server', 'watch'));
```

## 使ってみて
客先の環境のパスが想定と違っていたりで、案件ではちょいとトラブったりしたのですが、
基本的にはこれで問題なしでした。
macにvagrantでcentos7の仮想環境を構築したときの初期設定

macにvagrantとvirtualboxで仮想環境を構築してboxとしてcentos7を導入したあとの初期設定です。
簡単にboxを構築できたのですが、実際にsshでログオンしてみるといくつか初期設定が必要でした。

##言語設定
初期構築したばかりだと言語がドイツ語になっています。これを日本語に直します。

```
[vagrant@localhost ~]$ jkfdkj
-bash: jkfdkj: Kommando nicht gefunden.
```
多分コマンドが見つからないって言っています。
環境変数の値を確認すると

```
[vagrant@localhost ~]$ set |grep LANG
LANG=de_DE.UTF-8
```

ドイツ語です。これを日本語に変更します。

```
[vagrant@localhost ~]$ localectl set-locale LANG=ja_JP.UTF-8
==== AUTHENTICATING FOR org.freedesktop.locale1.set-locale ===
Authentication is required to set the system locale.
Authenticating as: root
Password: 
==== AUTHENTICATION COMPLETE ===
[vagrant@localhost ~]$ source /etc/locale.conf
```

rootのパスワードを聞かれて戸惑いましたが、ディフォルトでは
vagrant　がパスワードです

```
[vagrant@localhost ~]$ kjkfdkf
-bash: kjkfdkf: コマンドが見つかりません
```

日本語になりました。

##タイムゾーン設定
これもディフォルトではヨーロッパのタイムゾーンになっています。（CEST:Central European Summer Time）

```
[vagrant@localhost ~]$ date
2017年  5月 10日 水曜日 07:16:21 CEST
```


これも日本のタイムゾーンに変更します。

```
[vagrant@localhost ~]$ sudo cp /usr/share/zoneinfo/Japan /etc/localtime
```

```
[vagrant@localhost ~]$ date
2017年  5月 10日 水曜日 14:28:35 JST
```
日本のタイムゾーンになりました。

## キーマップ変更
ここまでの設定を確認しようと思い、localectlコマンドで状況を確認してみたところ、Keymap, Layoutはドイツっぽいままになっていました。

```
[vagrant@localhost ~]$ localectl status
   System Locale: LANG=ja_JP.UTF-8
       VC Keymap: de
      X11 Layout: de
```
これを変更します。

```
[vagrant@localhost ~]$ localectl set-keymap jp106
==== AUTHENTICATING FOR org.freedesktop.locale1.set-keyboard ===
Authentication is required to set the system keyboard settings.
Authenticating as: root
Password: 
==== AUTHENTICATION COMPLETE ===
```
またrootのパスワードが必要です。vagrant

```
[vagrant@localhost ~]$ localectl status
   System Locale: LANG=ja_JP.UTF-8
       VC Keymap: jp106
      X11 Layout: jp
       X11 Model: jp106
     X11 Options: terminate:ctrl_alt_bksp
```
日本語キーボードになりました。
とりあえずここまで

## 参考
macOS Sierra バージョン10.12.4
Vagrant 1.9.4
VirtualBox 5.1.22
CentOS 7.0 64bit

***
## シリーズ一覧 (vagrant centos LAMP環境構築）
1.[macにvagrantでcentos7の仮想環境を構築したときの初期設定](http://qiita.com/saboten10/items/40a1331b69536534b7dc)
2.[mac上の仮想環境に構築したcentos7にPHPを導入する](http://qiita.com/saboten10/items/7026539e47093a62673c)
3.[mac上の仮想環境に構築したcentos7でPHPのビルトインサーバーを利用する](http://qiita.com/saboten10/items/e916bd2cd33c059f266b)
4.[mac上の仮想環境に構築したcentos7にapahceを導入する](http://qiita.com/saboten10/items/4bf506c81b5eed3aae78)
5.[mac上の仮想環境に構築したcentos7にmysqlを導入する](http://qiita.com/saboten10/items/298e884c953255708a61)
6.[centos7に導入したMySQL5.6の初期設定と動作確認](http://qiita.com/saboten10/items/4d2c79d507d1eae00d1b)
tagbarでjavascriptを便利にしようと思ったら上手くいかなかったので改善したメモ

# TL;DR
https://github.com/hushicai/tagbar-javascript.vim

# tagbar は入れたけど
デフォルトだとjavascriptを上手く解析してくれなかったりする。
ググっても意外と日本語の情報がなく、またあっても古かったりした。
というわけで辿り着いたものが https://github.com/hushicai/tagbar-javascript.vim 。


ES6文法もちゃんとタグ化してくれてますね（リンク先のスクショ参照）。
node.jsでファイル出力

#node.jsでファイル出力
node.jsでファイル出力するには、
標準ライブラリであるfsを読み込みます。

```node.js
var fs = require("fs");

var text = "テスト出力";

// 非同期で行う場合
fs.writeFile('out.txt', text, (err, data) => {
  if(err) console.log(err);
  else console.log('write end');
});

// 同期で行う場合
try {
  fs.writeFileSync("テストoutput2.txt", text);
  console.log('write end');
}catch(e){
  console.log(e);
}

```
[Monaca] JavaScriptからの外部サーバー通信について

Monacaで開発するアプリからJavaScript（Ajax）経由で外部サーバーと通信を行う際、通信エラーになる場合があります。
今回は、外部サーバーとの通信がエラーになった際に確認する項目について書いてみたいと思います。


#はじめに
Monacaデバッガーと実機では、コンテンツのセキュリティーが異なるため、最終的には実機アプリをインストールして確認する必要があります。
対象は、Cordova6.2プロジェクトになります。


#許可する外部URL
通常、Monacaで開発するアプリでの外部サーバーと通信する際の設定は、各アプリ設定画面の `許可する外部URL` に設定します。
デフォルトでは、「*」が、設定されています。

この設定は、JavaScriptからネイティブ側へWebView経由で送信されるコンテンツ（ネットワーク）のリクエストに対しての設定になります。

各アプリ設定画面の `許可する外部URL` のデフォルト値は、 `すべて許可` の状態になっているため、通常は、JavaScript経由で外部サーバーと通信を行うことが可能なのですが、iOSの場合、「*」を `すべて許可` として認識しない場合があるため、iOSで外部サーバーとの通信ができない場合は、対象の外部サーバーを明示的に記述する必要があります。


#iOS
iOSでは、ATS（App Transport Security）によって外部サーバーとの通信が制限されている場合があります。
ATSによって外部サーバーとの通信がエラーになっている場合は、ATS設定を行う必要があります。

ATS設定については、[Whitelistプラグインについて](http://qiita.com/keeey/items/44d0453b39c0529328f3)を参照してください。


#リクエストヘッダー
アプリ側の設定に問題がないのに外部サーバーとの通信がエラーになる場合は、アプリから送信されるリクエストヘッダーを外部サーバー側が拒否している場合があります。

この場合は、外部サーバー側で対応する必要があるため、外部サーバーの管理者に一度確認してもらってください。


#さいごに
Monacaで開発するアプリからJavaScript経由で外部サーバーと通信する際のエラーに関しては、さまざまな原因があります。
まずは、問題の切り分けが大切になりますので、参考にしていただけたら幸いです。
日本の北端・東端・西端・南端のWebメルカトル(3857)座標

仕事で必要になったときにすぐ出てこなかったので。
変換にはPostGISを使用

- 北端（JGD2000（GRS80楕円体）経度緯度:4612 → Webメルカトル:3857）
-- 択捉島・カモイワッカ岬（北海道蘂取郡蘂取村 北緯45度33分28秒 東経148度45分14秒）

```
SELECT ST_AsText(
  ST_Transform(ST_GeomFromText('POINT(148.75388889 45.55777778)', 4612), 3857)
);
---> "POINT(16559207.164754 5709763.80144174)"
```

- 東端（JGD2000（GRS80楕円体）経度緯度:4612 → Webメルカトル:3857）
-- 南鳥島・坂本崎（東京都小笠原村 北緯24度17分12秒 東経153度58分50秒）

```
SELECT ST_AsText(
  ST_Transform(ST_GeomFromText('POINT(153.98055556 24.28666667)', 4612), 3857)
);
---> "POINT(17141037.0370046 2788378.80177753)"
```

- 西端（JGD2000（GRS80楕円体）経度緯度:4612 → Webメルカトル:3857）
-- 与那国島・西崎（沖縄県八重山郡与那国町 北緯24度26分58秒 東経122度56分01秒）

```
SELECT ST_AsText(
  ST_Transform(ST_GeomFromText('POINT(122.93361111 24.44944444)', 4612), 3857)
);
---> "POINT(13684906.9901435 2808271.29464826)"
```

- 南端（JGD2000（GRS80楕円体）経度緯度:4612 → Webメルカトル:3857）
-- 沖ノ鳥島・北小島（東京都小笠原村 北緯20度25分30.6585秒 東経136度4分11.1766秒 ）

```
SELECT ST_AsText(
  ST_Transform(ST_GeomFromText('POINT(136.06972222 20.425)', 4612), 3857)
);
---> "POINT(15147212.1899126 2323446.56066348)"
```

参照 : [日本の端の一覧](https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC%E3%81%AE%E7%AB%AF%E3%81%AE%E4%B8%80%E8%A6%A7)
PowerShellでtail -f

いつも忘れるので備忘録

```
Get-Content -Wait -Tail "読み取り行数" -Path "ファイルパス" 
```

もし文字化けするようなら、エンコード指定をUTF8にしてみる

```
Get-Content -Wait -Tail 10 -Encoding UTF8 -Path example.log 
```
QNAP NAS に内向き DNS サーバーを構築する


自分用メモ

いつの間にか QNAP NAS で Optware IPKG が使えなくなっていたため、再構築した

## 環境

* QNAP NAS: TS-469 Pro
* ローカル IP: 192.168.1.2
* ドメイン: EXAMPLE.myqnapcloud.com (myQNAPcloud DDNS サービスを使用中)
* ルータ: ひかり電話ルータ PR-400KI (フレッツ光)

## QNAP にパッケージマネージャを入れる

App Center から Optware IPKG がインストールできなくなったため、代わりに Entware-ng をインストールする

### 参考サイト

1. [QNAP にパッケージマネージャを入れる - Qiita](http://qiita.com/qurage/items/7d97ad870db2b7b661f1)
2. [QNAPのパッケージマネージャ - Qiita](http://qiita.com/nak1114/items/b534cd3bd79db3e3f256)

## DNS サーバ

dnsmasq を使用する


```
opkg update
opkg upgrade
opkg install dnsmasq-full
```

残り作業は、下記の参考サイトと同じ

ex) 名前解決したいエントリを追加

```
address=/EXAMPLE.myqnapcloud.com/192.168.1.2
```

### 参考サイト

1. [QNAPにdnsmasqを入れて内向きDNSサーバーを構築 | 高エネルギー技術研究室](https://htlab.net/blog/2013/05/14/qnap-dnsmasq/)

## ひかり電話ルータの設定


トップページ ＞ 詳細設定 ＞ DNS設定
ローカルドメイン問合せテーブル

プライマリDNSサーバアドレスには QNAP のアドレスを指定

DNSサーバアドレスは IPv6 表記
ex) 192.168.1.2 -> ::FFFF:C0A8:102


| ドメイン名 | プライマリDNSサーバアドレス | セカンダリDNSサーバアドレス |
|:----------:|:-----------:|:------------:|
| EXAMPLE.myqnapcloud.com | ::FFFF:C0A8:102 | (任意) |

### 参考サイト

1. [PR-400系のローカルドメイン問い合わせテーブル | blog.r622.net](https://blog.r622.net/archives/1554)
Visual Studio For Macをインストールしてみた

先日、Visual Studio For Macがリリースされたので、使ってみました。
ちなみに、アプリ開発は、趣味でのUnity開発以外やったことないのですが、ネイティブアプリのロジック部分ををCSHARPによる統一コードで作れるので、簡単なアプリケーションを実装するまでやってみた。

##インストール
以下のアドレスよりインストールできます。
https://www.visualstudio.com/ja/vs/visual-studio-mac/

基本的に画面の指示通りにインストールできました。

##プロジェクトの作成
![スクリーンショット 2017-05-13 16.53.57.png](https://qiita-image-store.s3.amazonaws.com/0/82366/69e11566-ee36-aed9-1073-f8a8c627be5f.png)

マルチプラットフォーム→ブランクフォームアプリを選択
指示に従って、プロジェクトの作成を完了します。


##ビューをXAMLで書く
ビューを変更するときは、xamlファイルを変更します。


今回は、helloworldsPage.xamlを編集します

```xml:helloworldsPage.xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:helloworlds" x:Class="helloworlds.helloworldsPage">
    <StackLayout HorizontalOptions="Center" VerticalOptions = "Center">
        <Label Text="text" x:Name="label"></Label>
        <Slider x:Name="slider"></Slider>
    </StackLayout>
</ContentPage>

```
ここで、x:Nameがコード上での名前になります。
実際には、このxamlからコードが作られ、そのコード上で宣言されています。
##コード部分を書く

上記で、テキストの部分にスライダーの値を表示するようにします。
Sliderの項目に、valueChanged="handle_ValueChanged"
を追加すると、自動的にコードが生成されます。
そこを、このように編集します

```csharp:helloworldsPage.xaml.cs
using Xamarin.Forms;

namespace helloworlds
{
    public partial class helloworldsPage : ContentPage
    {
        void Handle_ValueChanged(object sender, Xamarin.Forms.ValueChangedEventArgs e)
        {
            label.Text = string.Format("Hello {0:F2]", e.NewValue);
        }
        public helloworldsPage()
        {
                InitializeComponent();
                label.Text = string.Format("Hello {0:F2}", slider.Value);
        }
    }
}
```

##コンパイルと実行

ツールバーの以下の部分で、対象とするデバイスを選んで起動できます。
helloworlds.Droidを、iOSに切り替えると、iOSのデバッグもできます。
![スクリーンショット 2017-05-13 17.42.04.png](https://qiita-image-store.s3.amazonaws.com/0/82366/ae723d76-533b-7e81-7337-94f5e78efee1.png)

再生ボタンを押すとコンパイルが始まり、シミュレーターが起動します。

iOS,Android双方で同じアプリケーションが動くことを確認できるでしょう！
![スクリーンショット 2017-05-13 17.46.16.png](https://qiita-image-store.s3.amazonaws.com/0/82366/b6bc12fb-dc46-73a6-ebb1-ad5452c2348c.png)




##おまけ　クロスプラットフォームアーキテクチャ

どうやってCSharpで、両方のネイティブ環境で動くプログラムを作っているのか気になったので調べてみた。

AndroidとiOSでは違うアプローチで変更していた。

###Android

CSharpコード
↓
IL(中間コード)+Mono Runtime
↓ JIT(Just In Time)コンパイル
ネイティブコード

###iOS
一方で、iOSではJITが許可されていないので
CSharpコード
↓
IL(中間コード)
↓AOT(Ahead of time)
ネイティブコード

となっているようだ。間違っているかもしれない
Docker用のスクリプト覚書

使わなくなったので備忘録として記録

# ビルド用

```bash:build.sh
#!/bin/bash

set -eux

if [ $# -le 1 ]; then
	echo "invalid arguments. ${#}"
	echo "# Usage"
	echo "- $ bash build.sh <image-name> [options]"
	echo "# Descriptions"
	echo "- --all: build tab push"
	echo "- -b: build"
	echo "- -t: tag"
	echo "- -p: push"
	echo "# Examples"
	echo "- $ bash build.sh editor-app --all"
	exit 1
fi

image=$1
shift
targets=

while [ $# -gt 0 ]
do
	case $1 in
		"--all" )
			targets="build tag push"
		break ;;
		"-b" )
			targets="${targets} build"
		;;
		"-t" )
			targets="${targets} tag"
		;;
		"-p" )
			targets="${targets} push"
		;;
	esac
	shift
done

curr=$(cd $(dirname $0); pwd)

for C in ${targets}
do
	case $C in
		"build" )
			docker build --rm -t ${image} ${curr}
		;;
		"tag" )
			docker tag ${image} localhost:49000/${image}
		;;
		"push" )
			docker push localhost:49000/${image}
		;;
	esac
done
```

# Registory用

```bash:registory.sh
#!/bin/bash

set -eux

curr=$(cd $(dirname $0); pwd)

if [ $# -ne 1 ]; then
	echo '# Usage'
	echo '- $ bash registry.sh export'
	echo '- $ bash registry.sh import'
	echo '- $ bash registry.sh upload'
	echo '- $ bash registry.sh run'
	exit
fi

if [ "$1" == "export" ]; then
	docker export docker-registry | gzip - > ${curr}/docker-registry.tgz
elif [ "$1" == "import" ]; then
	cat ${curr}/docker-registry.tgz | docker import - docker-registry:latest
elif [ "$1" == "upload" ]; then
	scp ${curr}/docker-registry.tgz aws:~/
elif [ "$1" == "run" ]; then
	docker run -d \
		--name docker-registry \
		-p 49000:5000 \
		docker-registry:latest \
		registry serve /etc/docker/registry/config.yml
fi
```
[作成中][備忘録]isoイメージからをmp4を作成


忘れるのと、PC引っ越ししたらソース無くしそうなんでQiitaにメモ。

[前準備]
・brewからをffmpegインストール

```
brew install ffmpeg

```

・gemでsystemuを入れておく



[手順]
・ISOファイルをマウントする
・マウントしたイメージの「VIDEO_TS」フォルダ内の「.VOB」ファイルを結合して１ファイルにする
・結合したファイルをffmpegにてmp4に変換する
・変換後、結合したファイルを削除する
・ISOファイルをアンマウントする

上記を、Rubyのバッチで行う。
（シェルで書くのがメンドイ。。。）


[ソース]

```
require 'systemu'
require 'find'

raise "no arg(iso file path...)" if ARGV.size < 1

mountNm = nil
outVOBPath = nil

begin

  isoFile = ARGV[0]
  ext = File.extname(isoFile)
  raise "wrong extension " unless ext.upcase == ".ISO"
  raise "not found argment file" unless File.exists? isoFile

  mountNm = "/Volumes/#{File.basename(isoFile, ext)}"

  puts "[[[#{mountNm}]]]"

  status, stdout, stderr = systemu( "hdiutil mount #{isoFile}" )

  unless File.exists?(mountNm)
    msg = "unexpected mount name...#{mountNm}"
    mountNm = nl
    raise  msg
  end
  puts "* iso file mounted:#{mountNm}"
  video_dir = "#{mountNm}/VIDEO_TS"
  unless  File.exists?(video_dir)
    raise "wrong format iso file(VIDEO_TS FOLDER not exists...)"
  end

  # VOBファイルの列挙（[_0.VOB] は、メニューらしいので除外する）+ path接続                                           
  vob_list = Dir.entries(video_dir).select {|item| item =~ /\.VOB$/i && !(item =~ /\_0\.VOB$/)}.map {|item| "#{video_dir}/#{it\
em}"}
  raise "VOB File not exists..." if vob_list.empty?
  puts "* VOB files found."

  outDir =  File.dirname(isoFile)
  outVOB = "#{Time.now.strftime("%Y%m%d%H%M%S")}.VOB"
  outVOBPath = "#{outDir}/#{outVOB}"
  concat_cmd = "cat #{vob_list.join(" ")} > #{outVOBPath}"
  status, stdout, stderr = systemu(concat_cmd)
  puts "@@@[\n#{[ status, stdout, stderr ]}\n]@@@"

# TODO error check                                                                                                             

# TODO Start Time store...                                                                                                     

# TODO execute convert mp4 command                                                                                             

# TODO result check and show result                                                                                            

# TODO show proccess time                                                                                                      

rescue => e
  raise e
  
ensure
# TODO Remove concat VOB file                                                                                                  
#  if outVOBPath && File.exists?(outVOBPath)                                                                                   
#    File.delete outVOBPath                                                                                                    
#  end                                                                                                                         

  if mountNm
    system( "hdiutil unmount #{mountNm}" )
    puts "exists:#{mountNm}:#{File.exists?(mountNm)}"
  end
  
end


```


・・・作成中・・・
Ruby on Railsアプリ用にSequel Proでデータベースを作成する時の手順

Ruby on Railsアプリ用にデータベースを作成する時の手順をメモしておきます。
データベース管理にはSequel Proを使用。
Sequel Pro公式サイト　https://www.sequelpro.com/

#新しくデータベースを作成する
ターミナルで以下のように入力。

```:ターミナル
$ rake db:create
```

するとSequel Proに「○○_development」「○○_test」という二つのデータベースができている。

#モデルを作成する
モデル…コントローラとデータベースの橋渡し的存在。コントローラでモデルを利用してテーブルからデータを引き渡し、ビューに渡す。

ターミナルで以下を実行。

```:ターミナル
$ rails g model モデルクラス名(全て小文字、単数形)
```
これを実行すると、モデルファイル作成と同時にマイグレーションファイルも作成されている。

#マイグレーションファイルにカラムを記述(テーブルを作成)
作成されたマイグレーションファイルにカラムを記述する。
「t.型　:ファイル名」の形式で。

```db/migrate/2017XXXXXXXXXXXX_create_tweets.rb
  class CreateTweets < ActiveRecord::Migration
    def change
      create_table :tweets do |t|
        t.string      :name
        t.text        :text
        t.text        :image
        t.timestamps
      end
    end
  end

```
記述後、ターミナルで以下を実行

```:ターミナル
$ rake db:migrate
```

これでSequel Proを確認するとテーブルができてます。


###戻す時は以下を実行

```:ターミナル
$ rake db:rollback
```
素人の覚書[VBA]

[行・列を取得](http://qiita.com/yasuhikoc/items/bf636b3d7f1f9929f68d)したら
その範囲のデータを2次元配列に入れてしまうとそのあとの処理速度が速くなる気がする

行、列はそれぞれ`Ro`,`Co`にて取得済みとする

```
dim reg()'配列の宣言
dim i as long , j as long

redim reg(Ro,Co)
for i =1 to Ro
   for j = 1 to Co
      reg(i,j) = ws.cells(i,j)
   next j
next i
```
4000行くらいまでの表ならこれでも十分行ける感じ
機械学習⑤ アダブースト (AdaBoost) まとめ

# アダブースト (AdaBoost)  のまとめ

## What is アダブースト (AdaBoost) ?

アダブーストは、ランダムよりも少し精度がいいような弱い識別機を組みわせて、強い識別機を作成しようとする機械学習モデルです。
作り方の流れは、
まず、弱い識別機の適用させ、誤分類してしまったものの重みを増やす。
そして、次にその重みがついたものを優先的にみて、分類する。ということを繰り返します。

下記の図を参考にするとわかりやすいです。Youtube のリンクも貼っておいたので、詳しく知りたい方は見てみてください、

![Screen Shot 2017-05-13 at 12.44.42.png](https://qiita-image-store.s3.amazonaws.com/0/161691/59ea52a9-36ef-185e-0697-f4238f413578.png)
Extracted from [Alexander Ihler's youtube video](https://www.youtube.com/watch?v=ix6IvwbVpw0)

上記の図では、最初にD1で弱い識別機を使って、分類し、D2で誤分類した '+'1個と'-'2個の重みを増やしています。次にその誤分類された３つを優先的に考えて、また分類しています。ここで、重みを増やすのと同時に、正確に分類された他のものの重みは減っています。さらに、D3では、D２で誤分類された'-'３個の重みを増やすと同時に他のものの、重みは減っています。ちなみに、AdaBoost の default code では、この弱い識別機での分類は、DecisionTree (決定木)が使われています。


その繰り返し行った分類の重みを元に、強い識別機というものを作ります。


![Screen Shot 2017-05-13 at 13.00.11.png](https://qiita-image-store.s3.amazonaws.com/0/161691/d0485595-1e1e-c0a7-dad7-d4b16e7f6c6f.png)
Extracted from [Alexander Ihler's youtube video](https://www.youtube.com/watch?v=ix6IvwbVpw0)




## default のコード

```python:

from sklearn.ensemble import AdaBoostClassifier

AdaBoostClassifier(base_estimator=None, n_estimators=50, learning_rate=1.0, algorithm='SAMME.R', random_state=None)

```

## アダブースト (AdaBoost) 内の Parameter の説明


- base_estimator

弱い識別機として使われる機械学習モデルのこと。default は、DecisionTreeClassifier (決定木)が使われているが、指定することで他の機械学習モデルを適応することもできる。
 
- n_estimators 

弱い識別機を使った分類を何回繰り返すかの指定。しかし、その前に強い識別機が100%の精度になったら、そこで終了。





## アダブースト (AdaBoost)  の 良い点悪い点。

- 良い点

弱い識別機を幾つか組み合わせるので、正確に分類されやすい。

- 悪い点


K nearest neighbors と同じで、ノイズ（違うラベルが同じ場所に混在する）や、Outliers (異常値)にも、弱い。過学習になりやすい。

## まとめ

以上が現在筆者のわかる範囲での アダブースト (AdaBoost)  の概要です。
日々更新していきますので、追加すべきところ、直すべきところありましたら、コメントいただけると幸いです。
オープンソース支援団体NumFOCUSについて

NumFOCUS (https://www.numfocus.org/) は、オープンソースのサイエンス・コンピューティングに関するプロジェクトを支援する非営利団体。マイクロソフトやIBMといった会社が、パートナーとして参加しています。

非常に有名なオープンソースのプロジェクトであっても、非営利のボランティアだけでコミュニティを支えていくのは資金面で困難であることが多く、NumFOCUSは、そいういったプロジェクトが活動を継続するための、資金面での支援を行う受け皿となることをミッションとして掲げています。

支援プロジェクトになるにはその目的が、**scientific computing or data science**　に特化していることが必要で、汎用的なツールの開発 (IDE、ユーティリティ、汎用プログラミング言語やツール開発)は向かないそうです。scientific computing や data science が目的であれば教育活動もgood fitです。その他の具体的な要件は[こちら](https://www.numfocus.org/open-source-projects/information-on-fiscal-sponsorship/)のページに記載されています。

### NumFOCUS 支援プロジェクト (2017年5月13日時点)

NumFOCUSが資金面で支援しているプロジェクトのリストです。もともとPythonの主要プロジェクトを支援するための母体として始まったため、Python関連のプロジェクトが多いようです。ライブラリ開発だけでなく、教育目的の活動プロジェクトも含まれています。

| プロジェクト      |      活動内容          |    
|:-----------------|------------------:|
| AstroPy          | 天文学のPythonパッケージ開発|    
| Data Carpentry   | データサイエンスの教育活動 |       
| FEniCS Project   | 偏微分方程式のツール開発|        
| IPython          | Pythonの高機能なインタラクティブシェル|       
|Julia             | 科学技術計算のための動的プログラミング言語|      
|Matplotlib        | Pythonの2Dグラフ描画ライブラリ|     
|nteract           | 実行可能なコードを含む文書作成プログラム|     
|NumPy             | 科学技術計算のための基礎的なPythonライブラリ|    
|Project Jupyter   | インタラクコンピューティングのためのツール|    
|pandas            | データ分析のためのPythonライブラリ|      
|PyMC3             | ベイズ統計モデルのPythonライブラリ|      
|PyTables          | 階層構造をもつデータセットのためのPythonライブラリ|      
|QuantEcon         | 経済モデルのためコンピューティングスキル支援|      
|rOpenSci          | 科学者のワークフローを支援するRソフトウェア群|      
|Software Carpentry|科学者のためのコンピューティング教育 |   
|SunPy             | 太陽物理学のためのPythonライブラリ|  
|SymPy             | PythonによるCAS(数式処理システム)ライブラリ|  
|Stan              | 多くの統計モデルによる自動推定が可能なデータ分析のための言語|    
|yt                | Pythonによる容積測定データのための分析と視覚化ツール|
素人の覚書[VBA]：最終行・最終列の取得


```
dim Ro as long,Co as long 'Ro=row(行),Co=column(列)
dim ws as worksheet
set ws = thisworkbook.sheets(1)

Ro = ws.Cells(Rows.Count, 1).End(xlUp).Row
Co = ws.cells(1,Columns.count).End(xltoleft).Column
```
シート上の表の行列の最終行・列を求める方法
この後配列に放り込むなりなんなりできる
MacでのJava開発環境構築を通して「PATHを通す」意味を学ぶ

# PATHを通すということ

プログラム実行時に自動的に検索させるディレクトリを指定することです。

たとえばJDKを配置する時、

>windowsだと **C:\Java\jdk1.8.0\Home**\bin（以下略） 
>Macだと **~/Library/Java/JavaVirtualachine/jdk1.8.0/Home**/bin（以下略）

みたいに同じJDKでもディレクトリに行き着くまでの階層が異なったりします。 
そこでこの差異を吸収するために、実行マシン（コンパイラ？）上では上記の太字の部分を**＄JAVA_HOME＄**と定義することでどんな環境にも対応できるようにしています。

もちろん何もしていない状態のパソコンでは＄JAVA_HOME＄なんてものは定義されていないので、環境ごとに設定をしなければなりません。これを**PATHを通す**と表現します。 
PATHの呼び方はパソコン本体（OS単位）ではPATH、JavaではJAVA_HOME、tomcatならCATALINA_HOME、apacheならHTTPD_HOMEなどミドルウェアによって様々です。 
ミドルウェアによってはインストール時に自動的にPATHを通してくれますが、Javaはやってくれないので自分でやる必要があります。あるいは特定のフォルダにPATHを通すことで自作ショートカットを配置できたりします。→
[Windows使いのプログラマは絶対に仕込んでおくべき最強のランチャー1選](http://qiita.com/s_hino/items/22f0a9c0a167d222dc54)

# 流れ
1. [.bash_profileを開く](http://qiita.com/s_hino/items/a185deb4f9fc31c0f5e2#1-bash_profile%E3%82%92%E9%96%8B%E3%81%8F)
2. [PATHとJAVA_HOMEを追記](http://qiita.com/s_hino/items/a185deb4f9fc31c0f5e2#2-path%E3%81%A8java_home%E3%82%92%E8%BF%BD%E8%A8%98%E3%81%99%E3%82%8B)
3. [適用と確認](http://qiita.com/s_hino/items/a185deb4f9fc31c0f5e2#3-%E7%A2%BA%E5%AE%9A%E3%81%A8%E7%A2%BA%E8%AA%8D)

ターミナルを使って作業します。
## 1. .bash_profileを開く
Macでは**.bash_profile**というファイルにWindowsで言うところの環境変数が記述されています。これを開きます。おそらくテキストエディタで開かれるかと思います。

```sh
$ open ~/.bash_profile
```

新品のMacでファイルが存在しない場合は作ってください。

```sh
$ touch .bash_profile
```

.bash_profileと双璧となる存在に.bashrcというファイルがあります。両者の違いは

> .bash_profile→ログイン時に自動的に読み込まれる
> .bashrc→bash（ターミナル）起動時に読み込まれる

です。.bash_profileのほうが優先度が高いようです。基本的には.bash_profileを編集しましょう。

## 2. PATHとJAVA_HOMEを追記する
以下の文法で追記します。

```sh
$ export 変数名=ディレクトリ
```
すでに存在する変数に追加したい場合は、以下の文法で追記します。

```sh
$ export $元変数名:変数名=ディレクトリパス
```
元の変数名を後ろにつけることで優先順位を上げることができます。

```sh
$ export 変数名:$元変数名=ディレクトリパス
```
Javaの実行環境をPATHに、JAVA_HOMEを新規で追加したい場合にはこんな感じで追記します。

```sh
export PATH=$PATH:/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home
```
※ディレクトリパスは異なるかもしれないので適宜読み替えて下さい。 

追記したら上書き保存をしてください。

## 3. 適用と確認
.bash_profileを適用します。

```sh
$ source ~/.bash_profile
```
これで通りました。 
ターミナルを再起動して本当に通っているか確認をします。

```sh
$ echo $PATH
$ echo $JAVA_HOME
```
追記したディレクトリが表示されれば成功です。

## 参考
[PATHを通す方法](http://motw.mods.jp/Mac/PATH.html)
[open ~/.bash_profile で .bash_profile が編集できる！Mac OS X 便利すぎ](http://blog.livedoor.jp/noanoa07/archives/1898106.html)
[MacでPATHを通す](http://qiita.com/nbkn/items/01a11392921119fa0153) 
[PATHを通すために環境変数の設定を理解する (Mac OS X)](http://qiita.com/soarflat/items/d5015bec37f8a8254380)
[MacでPATHを通す .bash_profileの作成と編集](http://motomichi-works.hatenablog.com/entry/2016/03/02/103207)
Orange Pi Plus 2E のOS選択(2017年春)


# 序段

おもちゃ替わりに買ったOrange Pi Plus 2E。ケースと電源セットで[6000円弱](https://ja.aliexpress.com/store/product/Orange-Pi-Plus-2E-SET5-Pi-Plus-2E-Power-Suppy-Transparent-Acylic-Case-Support-Ubuntu-Debian/1553371_32674695091.html)。
家ではすっかりRaspberry Pi 3にお株を奪われていたのですが、CPUもRAMの性能も悪くないのにお蔵入りはもったいない。
いろいろ試すにも、まずはOS・ディストリビューションの(私情の入った)検証をしてみます。

以下、「Orange Pi Plus 2E」は「Plus 2E」と略しますね。

# 使える、使えそうな、使えないディストロ達
評価基準：
　◎ おすすめできる、安全、安定
　○ まず成功する。問題なし
　△ 難儀、困難、どうにかなるかもしれない。
　× やめとけ。泣きをみる。

* [armbian](https://www.armbian.com/)
    * ◎ 本命。「Plus 2E」も正式サポートされています。他のOrange Piシリーズもほぼサポートされています。eMMC搭載機種のための書き込みコマンド(nand-sata-install)が同梱されているのも地味にありがたい。
    * ◎ 「Debian 8(Jessie) サーバ版」と「Ubuntu 16.04 LTS(xenian) デスクトップ版とサーバ版」があり、「Plus 2E」をLinuxデスクトップにするには必要十分。
* [DietPi](http://dietpi.com)
   * △ 「Plus 2E」は正式サポートされてないが、ハード構成のほぼ一緒な「OrangePi Plus / Plus 2」がサポートされているため、おそらく動く。<未検証>
   * ○ minimal(極小)を名乗っており、「Plus 2E」より「Orange Pi Zero」や「NanoPi」といった組み込み(IoT)デバイス向き。デスクトップやサーバ向けではないでしょうね。<Raspberry Pi 1 Model Bでの評価による感想>
* [公式 orangepi.org](http://www.orangepi.org/downloadresources/)
    * × Orange Pi の公式であり、AndroidやRaspbian, Ubuntu, DebianをOrange Piに対応させたものを置いてあるはずなのだが、ダウンロードできない、表記(日付)が正しくないなど怪しさ爆発。
    * ×見て、ダウンロードしようとして、そして諦める。そんなHP。
* [Arch Linux ARM](https://archlinuxarm.org/)
    * △ Arch LinuxのARMデバイス用ディストロ。Orange PiもAllwinnerプロセッサもサポートされてはいないが、[公式のWikiに書かれている方法](https://wiki.archlinuxjp.org/index.php/Orange_Pi)でARMv7用のパッケージで起動させることはできました。<検証済>
    * × 起動用のSDカードを作るためには、Linux上でパーテーションを作るなどの作業が必要でとてもめんどくさい。他のディストロはSDカードにimgファイルを書き込むだけなのにね。

# フォーラムで公開されていたあれはいま…

個人が作成したOrange Pi用のイメージもいくつかありますが、1年以上古いものばかりになっていました。ですのでここで紹介は止めておきます。
もし新しいもの(更新日が2017年以降)のものがありましたら教えていただけますと幸いです。

# 情報収集元
[公式フォーラム](http://www.orangepi.org/orangepibbsen/forum.php)にて「[Plus 2E](http://www.orangepi.org/orangepibbsen/search.php?mod=forum&searchid=57&orderby=lastpost&searchsubmit=yes&kw=Plus+2E)」で調べる。
matrixStatsで行ごと・列ごと演算の穴を埋める

Rの話です。

行列の行ごと・列ごとに何らかの演算をしたいとき、baseに含まれている`colMeans`や`rowSums`を使うと速い。裏でコンパイル済のコードが呼ばれているためだ。

平均や合計以外の演算については、baseには含まれていない。最小、最大、中央値などを行ごと・列ごとに行うには、通常は`apply`関数を用いて同様の計算をすることができるが、速度で劣る。

そんな穴を埋めるのが、[`matrixStats`](https://cran.rstudio.com/web/packages/matrixStats/index.html)パッケージだ。baseを補完する`colMins`, `rowMedians`などの関数を取り揃えている。

下のコードでは、大きめの行列に対して、`matrixStats`を使う場合と使わない場合で、同じ結果が得られることを確認している。

```{r}
x <- rnorm(12*1e+4)
dim(x) <- c(300, 400)

library(matrixStats)
all(colMins(x) == apply(x, MARGIN=2, FUN=min)) ## TRUE
all(rowMaxs(x) == apply(x, MARGIN=1, FUN=max)) ## TRUE
```

さらに、速度を比較してみよう。

```{r}
library(microbenchmark)
microbenchmark(colMins(x), apply(x, 2, min),
               rowMaxs(x), apply(x, 1, max))
```

私の結果では、下のように約5倍速い結果になった。

```
Unit: microseconds
             expr      min        lq      mean    median        uq       max neval
       colMins(x)  543.971  549.2495  578.2656  570.8660  581.7235   781.020   100
 apply(x, 2, min) 2611.425 2671.2140 2812.8639 2692.3325 2723.6600 11133.883   100
       rowMaxs(x)  622.411  627.9780  656.0709  650.2715  662.9000   988.466   100
 apply(x, 1, max) 2457.899 2537.1715 2900.6546 2714.8585 2850.1375 11321.663   100
```