OmniAICreator/Qiita-1.07M huggingface dataset:
スマブラSP&スプラトゥーン2向けゲーミングモニタ

　どうも、ひれおくんです。
![ひれおくん.jpg](https://qiita-image-store.s3.amazonaws.com/0/309447/470e04ac-b801-0e9d-c541-62fb290fb2a1.jpeg)
　こんなキャラクターでスプラトゥーン2をやっていますが、これは[ZOZOテクノロジーズその2 Advent Calendar 2018]("https://qiita.com/advent-calendar/2018/zozo_tech2") 22日目の真面目な記事です。スプラトゥーン2に適したモニタを応答性能や画質などの観点から紹介したいと思ってましたが、スマブラSPにも全く同じ話が出来ると気付きました。スマブラSP兼スプラトゥーン向けモニタのお話です。

#結論
　細けぇこたぁいいんだよ！って方に向けてまず結論から書くとこいつを買いました。

Amazon : https://www.amazon.co.jp/dp/B06XFQDM2V/
公式 : https://acerjapan.com/monitor/gaming/kg1/KG251Qbmiix

当記事の執筆時はAmazonで税込14,980円から更に10%OFFクーポンで値引きされてます。ちなみに私が購入した時は20,000円弱しましたが、今でも良い買い物をしたと思っています。

#きっかけ
 そもそも何故わざわざゲーミングモニタを買おうかと思ったかというと、一緒にチームを組む友人達が全員ウデマエがX帯（最上位ランク）の中、自分だけランクが低く足を引っ張っていたからです。何で自分は弱いんだろう？と考えたところ色々と改善点は思い付き、その中の1つが画面の大きさでした。当時はNintendo Switchの本体画面でスプラトゥーン2をやっていましたが、ディスプレイの横幅が20cm以下と指を広げた時の方が大きく、この画面の小ささだと打ち合い中に敵を見失うことが多々ありました。流石に限界を感じたので「もっと大きい画面でやろう！」と考えてモニタを探し始めました。

#要求スペック
　ではモニタに必要なスペックとは何か？と考えたところ、以下の点を考慮すべきだと考えました。

* リフレッシュレート
* 応答速度
* 解像度
* グレア・ノングレア

1個ずつ見てゆきます。なお有機EL(OLED)だと大型テレビのサイズとなってしまい私の机の上には乗らないので除外して、今回は全て液晶モニタのお話です。またスプラトゥーンでは音で敵の捕捉する事もあるので音質は重要ですが、その場合はNitendo Switchから直接音を取るべきなので、モニタの要求スペックからは除外しました。

##リフレッシュレート
　リフレッシュレートとは（厳密には異なりますが）フレームレートとも呼ばれるもので、1秒間に画像表示を何回切り替えられるかを表す指標です。入力周波数と表記されている場合もありますが、この値が大きいほど性能が高く、高速で描画が出来るという意味になります。今回の映像信号元はNintendo Switchで60Hzですので、モニタのリフレッシュレートは60Hz以上あればコマ落ちなどが発生せず問題なく描画出来ることになります。

文字だけでよく分からないよ、って方はこちらをどうぞ。
https://www.youtube.com/watch?v=9kHHcraaeLs

##応答速度
　応答速度とは、画素をある色から別の色へ変化させる時に必要な時間です。この値が小さいほど性能が高く、より早く描画が完了するので映像ボケなどが無くなりクッキリした映像になります。多少の映像ボケはスプラトゥーンやスマブラSPをやる上では問題なく、それよりも重要なのが入力遅延です。入力遅延とは、Nintendo Switchで押されたボタンが入力されてから画面に反映されるまでの時間です。この入力遅延が酷いと「射撃ボタンを押して暫く経ってから画面が反映した」ということになり、対人戦闘では致命的です。
(入力遅延) = (ゲーム内部処理の時間)+(HDMIなどケーブルの伝送時間)+(応答速度)
で表すことができ、Nintendo SwitchはHDMIケーブルしか使えないので、入力遅延を減らすにはモニタの応答速度を速めるしかありません。なので、なるべく応答速度が速いものということで1msのモニタを選びました。
ちなみにゲーミングモニタと呼ばれるものは、この応答速度とリフレッシュレートが高性能となっているものが非常に多い理由は、以上のお話から理解できると思います。

##解像度
　世間で4Kとか言われているアレです。正確には、画面内の画素数のことでテレビ業界でいう4Kとは、横3840画素×縦2160画素のことです。Nintendo Switchの出力解像度は1920×1080で、2KまたはFULL HDと呼ばれる解像度です。なのでモニタも1920×1080以上あれば問題ありません。

##グレア・ノングレア
　ノングレア（非光沢）にすべきです。ノートPCで高価格帯のものだと「ノングレア液晶」というワードを見かけることがありますが、これは液晶への映り込みを低減したものになります。どういう事かというと、画面が真っ暗になった時に自分の顔や、自分の後ろにある光などが画面に映り込むことがありませんか？　これが映り込みで、画面が真っ暗ならまだ良いのですが、暗い洞窟などを進んでいる時にこの映り込みが発生すると、映り込みが邪魔で洞窟内の敵が見えない！という事態に陥ります。戦闘中なら致命的です。これを避けるためにノングレアにすべきです。

#まとめ
　以下のスペックのモニタを買うべし。

* リフレッシュレートは60Hz以上
* 応答速度はなるべく良いもの
* 解像度は1920×1080以上
* ノングレア（非光沢）のやつ
Pleiades201809にTomcat Pluginを入れる

# 概要
最近のバージョンのPleiadesにはTomcat Pluginがデフォルトで入っていないため、自分で入れる必要がある。その手順を記す。

# 手順
[ヘルプ]→[Eclipseマーケットプレース]

![image.png](https://qiita-image-store.s3.amazonaws.com/0/30304/37e2aa44-8cad-7cba-0c0b-1460ff9854ac.png)

「Tomcat」で検索して[インストール]

![image.png](https://qiita-image-store.s3.amazonaws.com/0/30304/7eeaf99d-5aff-6924-762f-8cfb5c41a1e1.png)

ライセンスに同意して[完了]
![image.png](https://qiita-image-store.s3.amazonaws.com/0/30304/a715cc47-2215-2bf8-2af2-654e664f4516.png)

Eclipseを再起動すると追加される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/30304/5ff27bc6-248a-07bc-3b1b-f77c7dd1114f.png)


以上。
【Python】**kwargs っぽくコマンドライン引数を処理する

# はじめに

Pythonではコマンドライン引数のパースには標準ライブラリ `argparse` が使われます。
このライブラリはかなり高機能なので、しっかりしたアプリケーションを設計したい場面ならきっと便利に使えます。

しかし、毎回毎回そんなにしっかり設計できるものでもないです。
もともとコマンドライン引数を使わないスクリプトとして書き始めたのに、いつのまにか `sys.argv` があちこちに書かれているような人も多いのではないでしょうか。

# ありがちな状況

```python
# bad.py
import sys

foo = sys.argv[1]
bar = sys.argv[2]

print('foo ==', foo)
print('bar ==', bar)
```

```bash
$ python bad.py 12 34
foo == 12
bar == 34
```

これでは、引数で何を渡しているのか全くわかりません。
せめてPythonの関数でいうところの `**kwargs` みたいなものが欲しくなりますよね？

# 提案

```python
# better.py

def arg(*flags, args=None, **kwargs):
    import argparse
    p = argparse.ArgumentParser()
    p.add_argument(*flags, **kwargs)
    ns, _ = p.parse_known_args(args)
    return next(getattr(ns, d) for d in dir(ns) if not d.startswith('_'))


foo = arg('--foo')
bar = arg('--bar')

print('foo ==', foo)
print('bar ==', bar)
```

```bash
$ python better.py --foo=12 --bar=34
foo == 12
bar == 34
```

いかがでしょう、ちょっとはマシになったんじゃないでしょうか。
Chart.jsで線グラフで縦棒をマウスホイールで動かす方法

Chart.js 2.7.xにはバグがあってchart.update()でアノテーションが再描画されません。
Chart.js 2.6.xに落とすと、正常に動作します。
（2018年12月21日現在）
https://github.com/chartjs/chartjs-plugin-annotation/issues/88

```JavaScript:index.html
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>chartjs-plugin-annotation sandbox</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/0.5.7/chartjs-plugin-annotation.min.js'></script>
<script src='https://cdn.rawgit.com/chartjs/Chart.js/master/samples/utils.js'></script>  
</head>

<body>


  <div style="width: 75%">
    <canvas id="canvas"></canvas>
  </div>


  

<script>
var g_value_index = 5;
var g_chart = null;
var chartData = {
  labels: ["11月30日 12:00", "11月30日 15:00", "12月1日 00:00", "12月1日 03:00", "12月1日 06:00", "12月1日 09:00", "12月1日 12:00", "12月1日 15:00", "12月1日 18:00", "12月1日 21:00", "12月2日 00:00", "12月2日 03:00"],
  datasets: [
    {
      data: [1008, 1008, 1004, 1006, 1004, 1002, 996, 992, 990, 975, 970, 955]
    }
  ]
};

var my_annotation = {
            type: "line",
            mode: "vertical",
            scaleID: "x-axis-0",
            value: chartData.labels[g_value_index],
            borderColor: "blue",
            label: {
              content: "1008",
              enabled: true,
              position: "top"
            }
          };
var options = {
	  animation: false,
      annotation: {
        annotations: [
          my_annotation,
        ]
      }
    };

function main()
{
  var ctx = document.getElementById("canvas").getContext("2d");
  g_chart = new Chart(ctx, {
    type: "line",
    data: chartData,
    options: options,
  });
}
main();



function handler(e){
	if (e.originalEvent.deltaY < 0) {
		console.log("wheel up");
		g_value_index --;
		if ( g_value_index < 0 ) {
			g_value_index = 0;
		}
	} else {
		console.log("wheel down");
		g_value_index ++;
		if ( g_value_index > chartData.length - 1 ) {
			g_value_index = chartData.labels.length - 1;
		}
	}
	console.log("g_value_index="+g_value_index);
	my_annotation.value = chartData.labels[g_value_index];
	console.log("my_annotation.value="+my_annotation.value);
	options.annotation.annotations.shift();
	options.annotation.annotations.push(my_annotation);

	g_chart.update();
	e.preventDefault();
}
$("#canvas").off('wheel');
$("#canvas").on('wheel', handler);

</script>



</body>

</html>

```
SQLでサブクエリを使って平均値以上を抽出する


#環境
- BigQuery

#データセット
![image.png](https://qiita-image-store.s3.amazonaws.com/0/326771/6b211110-179d-dbc9-631d-b8ba03533194.png)

#平均値以上を抽出
```sql

select 
  team, hit
from 
  テーブル名
where
  hit >= 「平均値」;
```

と書きたいところですが、問題はどうやったら平均値を出せるのか、というところだと思います。
解決方法として今回はサブクエリを使って、つまり、もう一つクエリを書いて安打数の平均値を抽出します。
単純に平均値を抽出するクエリは以下の通りです。

```sql
select
  avg(hit) 
from
  テーブル名;
```

これを実行すると「1366.4333333333332」という数値が返ってきます。なので、このクエリを一番初めのクエリの「平均値」のところに記述します。


```sql

select 
  team, hit
from 
  テーブル名
where 
  hit >= (select avg(hit) from テーブル名)
;
```


#結果
![image.png](https://qiita-image-store.s3.amazonaws.com/0/326771/76e80757-9da6-b1fc-1909-3820f53049c2.png)
WP Rest APIとvue.jsでお知らせを一覧を作ってみる

#WP Rest APIとvue.jsでお知らせを一覧を作る

最近vue.jsを勉強し始めたのでWordpressとの連携を試してみたかったので
実装頻度が高そうなお知らせ一覧で作ってみようと思います。

## 実装環境
・[WP REST API](https://ja.wp-api.org/)（WPプラグインで投稿内容のjsonを返してくれる）
・投稿はカスタム投稿を使用します。（カスタム投稿名はnewsで設定）
・vue.jsとaxionはCDNで読み込み。


##WP側の設定
***ドメイン名/news/*** でアクセスされたらjsonを返すよう、functions.phpに下記の内容を記述。

```php:functions.php
	 function get_news_feed(){
	   register_rest_route(
	     'wp/v1/', 'news', //jsonを取得するためのurlを設定
	     array(
	       'method' => 'GET',
	       'args' => array(
	         'paged' => array(
	           'default' => 1,
	           'sanitize_callback' => 'absint'
	         )
	       ),
	       'callback' => 'news_add'
	    ));
	 }

	 function news_add() {
		$result = array();

		$query = new WP_Query(array(
			'post_type' => 'news', //設定済みのカスタム投稿名
			'posts_per_page' => 3 // 表示数
		));

		$items = array();//投稿情報を格納するための配列を作成
		while($query->have_posts()) {
			$query->the_post();
			$item = array();
            // 表示させたい内容をを配列に入れていく
			$item['title'] = get_the_title();//タイトル名
			$item['date'] = get_the_time("Y.m.d");//日付
			$item['permalink'] = get_the_permalink();//個別記事のリンク
			$item['content'] = mb_substr(strip_tags(get_the_content()), 0, 120, 'UTF-8');//記事本文
			$item['thumbnail'] = get_the_post_thumbnail_url(
				get_the_ID(), 'news_list'); //サムネイル画像
			$items[] = $item;
			}
			$result['items'] = $items;
			return $result;
	}
```

wp側の設定は以上。

## JS側の設定
適当なファイル名で作成（今回はnewsfeed.js）

```javascript:newsfeed.js
new Vue({
  el: '#newsFeed',
  data: {
    items: []//カスタム投稿の内容を入れる変数を用意
  },
  created: function created() {
    axios.get('https://example/news/').then(function (response) {
      // 取得完了したらlistリストに代入
      this.items = response.data;
    }.bind(this)).catch(function (e) {
      console.error(e);
    }.bind(this));
  }
})
```

## html側の設定
作成したJSファイルの読み込み

```html
<script src="newsfeed.js"></script>
```

vue.jsの読み込み

```html
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
```

axioxの読み込み

```html
<script src="https://cdn.jsdelivr.net/npm/axios@0.17.1/dist/axios.min.js"></script>
```


後は表示させたい箇所でJSで受け取った値をリストで表示するための記述をして実装完了。

```html:index.html
<div id="newsFeed">
	<div v-for="item in items" class="news_list_item">
		<a v-bind:href="item.permalink">
			<div class="news_list_img"><img v-bind:src="item.thumbnail" alt=""></div>
			<h3 class="news_list_title">{{ item.title }}</h3>
			<time class="news_list_time">{{ item.date }}</time>
			<div class="news_list_txt newsBar">{{ item.content }}</div>
			<span class="news_list_link din_bold">READ MORE...</span>
		</a>
	</div>
</div>
```

## 終わり
今回一覧のみのシンプルな実装ですが、さらに使えるようになり要件に沿った実装ができたらと
いいなーと思いました。
Rambulanceを拡張して無理やりURL毎にエラーページを切り替える

この記事は
===

* Rambulanceでやりたいことやろうとしたら若干拡張機構使う必要が出たのでメモです

やりたかったこと
===

* Railsの例外機構をシンプルかつ堅牢にすることができる[Rambulance](https://github.com/yuki24/rambulance)というgemがあります
* 便利なのですが、同一のRailsアプリの中では単一のデザイン（=layoutsファイル）しか定義することができません
* 今回URLによってデザインが諸々異なり、別のlayoutsを指定したかったです

ダメだった方法
===

Rambulanceが複数layoutに対応してないか？
---

* そもそもRambulanceは複数のlayout指定に対応していません
* [ソース](https://github.com/yuki24/rambulance/blob/master/lib/rambulance/exceptions_app.rb#L13)も見ましたが、思いっきり単一の```@layout_name```に持っちゃってます

Rambulanceを無視してrescue_fromを書く
---

* 特定のコントローラに```rescue_from```を書いてしまって、処理の中で強制的にデザインの異なるエラー画面にredirectしてはどうかと考えました
* が、Ramulance様はRack middlewareの根っこを抑えている神なので、rescue_fromなんていう瑣末な雑魚メソッドは完全に無視されてしまいダメでした

正解
===

RambulanceのCustom Exceptions Appを作成する
---

* READMEをよく読んでみると[Custom Exceptions App](https://github.com/yuki24/rambulance#custom-exceptions-app)というものの記載がありました
* ほとんど説明がないのでなんなのかは不明ながら、とりあえずそこに書いてある```$ rails g rambulance:exceptions_app```を実行してみました
* すると、```app/handlers/exceptions_app.rb```にRambulanceの動きをカスタマイズできるExceptionsAppのソースが生成されました！

対応コード
---

* どうもこのクラスはRambulanceの本体である```Rambulance::ExceptionsApp```を拡張するもののようで、Rambulanceのエラーページ表示の前に必ず通る場所のようです
* 最大のポイントは```ActionController::Base```を継承しているので、Railsの大半のメソッドが使い放題！ということです
* で、下記のようなコードを書いて、URLの頭が```/other```で始まっている場合のみ、Rambulanceのエラー表示を横取りして、強制的に別レイアウトのページにredirectするようにしました

```ruby:app/handlers/exceptions_app.rb
class ExceptionsApp < Rambulance::ExceptionsApp
  before_action :other_layout_filter

  private
  def other_layout_filter
    redirect_to '/other/error' if is_other_page?
  end

  def is_other_page?
    (params[:controller]&.split('/')&.first == 'other') rescue false
  end
end
```

* 注意点としては、このファイルの修正をしたらdevelopmentモードだとしてもRailsを再起動しなくてはなりません

終わりに
===

* 便利なライブラリは融通ききづらい時もあるけど、なんでもできる拡張の仕組みがあると、なんとか力技で対応できて助かりますね
gitでコミットに変更以外のファイルがまぎれこんでいないか調べる方法

```
git diff "HEAD^" --name-status | grep -E '^[^M]'
```

例えば100ファイルくらい置換とかで編集して全部コミットしてしまったとき、間違ってファイルを足してしまっていたり、削除してしまったりしてないか確認できる。
Railsで論理削除をもうしないためのrecords_rip gem

RailsのActiveRecordで論理削除をやめるための[records_rip gem](https://github.com/ts-3156/records_rip)を作った。

## このgemを使う利点

論理削除のためのカラム（例：`deleted_at`）を持たせると、すべてのSELECT文にこのカラムの値を指定する必要があり、コードの保守がしづらくなってしまう。

```ruby
# 論理削除のカラムがないなら、単に検索条件を書くだけでよい
User.where(name: 'Smith')

# 論理削除のカラムがある場合
# 他のメソッドや関連の取得などすべてに漏れなくavailableを指定する必要がでてくる
User.available.where(name: 'Smith')
```

作っているアプリケーションが小さい、開発者が少ないうちは問題ないが、規模が大きくなるにつれ論理削除は徐々に破綻していく。

こうした自体を避けるために、論理削除を隠蔽するようなActiveRecordのカスタマイズを行いたくなる。これをすると、今度はRailsの高速なバージョンアップに追随するのが非常に難しくなる。最終的には既存のアプリケーションを壊す可能性が出てきてしまう。

「論理削除されたレコードのデータをまったく使わない」ことも現実的には多々ある。これでは、何のために苦労して論理削除を実現したのか分からない。

records_rip gemを使うとこのような状況を回避することができる。

## records_rip gemの使い方

Gemfileに追加する。

```ruby:Gemfile
gem 'records_rip'
```

migrationファイルを生成し、データベースにテーブルを作る。

```sh
rails generate records_rip:install
rake db:migrate
```

レコードを削除する可能性があり、かつ、ログを残しておきたいモデルに`rest_in_peace`を追加する。

```ruby:app/models/user.rb
class User < ApplicationRecord
  rest_in_peace
end
```

こうしておくだけで、Userモデルのレコードが削除されたときは自動でそのログが残るようになる。

```ruby
user = User.create(name: 'Smith')
user.destroy
# => BEGIN
# =>   INSERT INTO "tombs" ...
# =>   DELETE FROM "users" ...
# => COMMIT
```

ログはデフォルトではJSON形式にシリアライズされてテーブルに保存される。検索するためには`Model.tomb( ... )`というメソッドを使えばよい。

```ruby
User.tomb(name: 'Smith').to_a
# => [#<RecordsRip::Tomb:0x0000xxxxxxxxxxxx id: 1, item_type: "User", item_id: 1, epitaph: "{\"id\"=>1, \"name\"=>\"Smith\"}"]
```

ActiveRecordに元々存在するメソッドのカスタマイズはまったくしていない。そのため、既存のRailsアプリケーションが壊れる心配はない。

また、ログを便利に検索するメソッドや、削除されたレコードを復活させる機能は作っていない。そもそも、「削除されたレコードの復活」は数ヶ月や数年に一回あるかないかの出来事であり、それくらいの頻度ならばデータベースのバックアップからリストアすべきと考えているため。

## 論理削除は悪いことなのか

論理削除を採用した方がよいケースもいくつかあります。ざっと思いつく代表的な例は下記の通りです。

- undoのために一定時間レコードを残しておきたい
- 「購読期限切れ」のように紐付けは残しつつ有効・無効の状態管理をしたい
- 「削除された or NOT」だけでなくさらに複数の状態を管理する必要がある
- 会社が大きくなったためシステム監査（のログ）が必要になった
- 外部キーで紐づく他のテーブルの対処が悩ましい

もしあなたの求める要件が上記のいずれかに該当するなら、論理削除をアプリケーション上で実現した方がよいです。

逆に、ただ漠然と、「過去のデータも残しておいた方が安心かも？」と考えているなら、（データベースのバックアップを取りつつ）単にレコードをDELETEするか、records_rip gemを使って簡易的なログを残すだけでよいと思います。

もし、create / update / destroyの徹底的なログを残したい、さらにレコードの復活を実現したい、のなら[paper_trail gem](https://github.com/paper-trail-gem/paper_trail)を使うとよいでしょう。
VSCode 用 SystemVerilogの拡張を作る（#7）

# LanguageServer
拡張機能エントリとは別に、サーバー用の.tsを作ります。

拡張機能が起動する際に、拡張機能からLanguageServerを起動してIPCで接続します。
これらはVSCodeのライブラリで簡単にできるようになっています。

LanguageServer：
https://github.com/Rockdoor/systemverilog/blob/master/src/server/server.ts

サンプルは[公式](https://code.visualstudio.com/docs/extensions/example-language-server)にありますが、これがまた余計なものが多くてつかみにくい。要点はとても少ないです。

## クライアント（拡張機能）との接続
サーバー側で以下のコードを記述。

```typescript
let connection = lserv.createConnection(
  new lserv.IPCMessageReader(process), 
  new lserv.IPCMessageWriter(process));
```

で完了します。基本これだけ。

## リクエストに対するレスポンス
```typescript
connection.onXXXXX() {
```
という形で、connectionのメンバとして 接頭on＋LSPリクエストの関数を実装すると対応するリクエストにレスポンスできるようになります。

何に対応するかと言うのは onInitialize という必ず起動時にやってくるメッセージに対して下記のような hogehogeProviderの内容を返してやると拡張機能側でそのLSPが有効化されます。

```typescript
  return {
    capabilities: {
      textDocumentSync: documents.syncKind,
      hoverProvider: true,
      completionProvider: {
        resolveProvider: true,
        triggerCharacters: ['.', ':']
      },
      signatureHelpProvider: {
        triggerCharacters: ['(', ',']
      },
      documentSymbolProvider: true,
      definitionProvider: true,
      referencesProvider: true,
      // codeLensProvider: {
      //   resolveProvider: true
      // },
      // codeActionProvider: true,
      executeCommandProvider: {
        commands: ["sv.server.instantiateModule"]
      },
    }
  };
```

## 実際の通信を垣間見る
公式でも紹介されていますが、
https://microsoft.github.io/language-server-protocol/inspector/
が便利です。

ログをダンプしておいて、それを上記ページにアップすると視覚化してくれます。


# クライアント（拡張機能）からのLanguageServerの起動と接続
拡張機能が起動されると呼ばれる activate 関数内で以下の流れを記述するとサーバーが起動されます。
注意として、serverModuleのパスは、.ts の生成コード（.js）となります。
パスを含めて出力コードがサーチされるようにserverModuleを指定します。

```typescript
    // The server is implemented in node
    let serverModule = ctx.asAbsolutePath(path.join('out', 'server', 'server.js'));
    // The debug options for the server
    let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] };
    // If the extension is launched in debug mode then the debug server options are used
    // Otherwise the run options are used
    let serverOptions: vsclient.ServerOptions = {
      run : { module: serverModule, transport: vsclient.TransportKind.ipc },
      debug: { module: serverModule, transport: vsclient.TransportKind.ipc, options: debugOptions }
    }
    // Options to control the language client
    let clientOptions: vsclient.LanguageClientOptions = {
      documentSelector: [{scheme: 'file', language: 'sv'}],
      synchronize: {
        configurationSection: 'svlog',
        fileEvents: vscode.workspace.createFileSystemWatcher('**/*.{v,sv,vh,svh}')
      }
    }
    // Create the language client and start the client.
    let disposable = new vsclient.LanguageClient('svlog', 'Language server for SystemVerilog', serverOptions, clientOptions).start();
```

あとは debugOption として、inspectを指定しておくと、そのプロセス番号を参照してVSCodeのデバッガがアタッチでき、サーバーの動きもトレースできるようになります。
Poetryとtoxを組み合わせてPythonのテストコードを動かす

この記事は[LIFULL Advent Calendar その3](https://qiita.com/advent-calendar/2018/lifull3)の遅れてきた16日目の記事です。

今までPythonの開発にPipenvを使っていたのですが、こちらの記事「[Poetryを使ったPythonパッケージ開発からPyPI公開まで](http://kk6.hateblo.jp/entry/2018/12/20/124151)」読んで、[Poetry](https://github.com/sdispater/poetry)というツールが気になっていました。

> Poetryの便利なところは、パッケージをビルドした際にこの設定がそのまま setup.py の console_scripts として記述される。ビルドする時にコマンドとして実行できるようにあらためてsetup.pyを書く必要がない。


そのテストも兼ねて、社内用のPythonライブラリをPipenvからPoetryに移行してみました。また、Rustを少し触っていて遊んでいた（コンパイルが通らずに泣いていた）ときに、開発ツールのcargoが洗練されていて羨ましかったのですが、それに使い勝手が近そうな印象を受けます。

## setup.pyが無い！

ところが、```poetry run tox```でtoxのテストコードを実行したところ、以下のようなエラーが出てしまいました。

```bash
ERROR: No setup.py file found. The expected location is:
  /Users/ninomiyt/Documents/xxxx/setup.py
```

toxを通常実行すると、その都度setup.pyを読み込んでインストールするのですが、poetryではbuild時に設定ファイルからsetup.pyを生成するため、開発時には存在しません。

ここですこしハマったのですが、[ISSUE](https://github.com/sdispater/poetry/issues/222)に解決方法が書いていました。以下のようにtoxの設定ファイルで「poetryはtox環境のものを利用する」ようにし、poetry経由でインストール&テストコード実行すれば大丈夫でした。

```ini:tox.ini
[tox]
skipsdist = True
envlist = flake8-py3, py36

[testenv]
whitelist_externals = poetry
skip_install = true
commands =
    poetry install -v
    poetry run pytest test/

[testenv:flake8-py3]
whitelist_externals = poetry
skip_install = true
commands =
    poetry install -v
    poetry run flake8 --version
    poetry run flake8 src test
```

## Poetry、なかなか良さそう

少し触っただけなのですが、今のところ、Pythonの、少なくともライブラリ開発ではなかなか良さそうだと感じています。

「Pipenvではpyenv自体もラップして必要なバージョンをインストールしてくれるのに対し、Poetryを使う際には、pyenvで利用したいPythonバージョンを指定した上で利用しなければならない」という点は少し不便なのですが、少しずつ試していって問題が無ければ、過去のPythonコード資産も少しずつPoetryに移行していってもいいように思います。
S3にあるELBのログをAmazon Athenaでクエリする

毎回調べているような気がするので備忘録として。
個人的にはログ系は1つのバケットに全部いれてしまうのが良いと思っているので、ログ専用のバケットを切ります。
同じような設定を色んな所にしなければならなかったりするので。特に権限周り。
ここでは
s3://<BUCKET_NAME>/<ELB_NAME>/AWSLogs/<ACCOUNT_ID>/elasticloadbalancing/ap-northeast-1/2018というディレクトリ構成にします
hive形式で作ればadd partitionする必要がないらしいのですが、ELBが作るデフォルトのディレクトリ構成に従います。

## DDLを用意する
```
CREATE EXTERNAL TABLE IF NOT EXISTS <dbname>.<elbname> (
  request_timestamp string,
  elb_name string,
  request_ip string,
  request_port int,
  backend_ip string,
  backend_port int,
  request_processing_time double,
  backend_processing_time double,
  client_response_time double,
  elb_response_code string,
  backend_response_code string,
  received_bytes bigint,
  sent_bytes bigint,
  request_verb string,
  url string,
  protocol string,
  user_agent string,
  ssl_cipher string,
  ssl_protocol string )
PARTITIONED BY (year STRING, month STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
         'serialization.format' = '1','input.regex' = '([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*):([0-9]*) ([.0-9]*) ([.0-9]*) ([.0-9]*) (-|[0-9]*) (-|[0-9]*) ([-0-9]*) ([-0-9]*) \\\"([^ ]*) ([^ ]*) (- |[^ ]*)\\\" (\"[^\"]*\") ([A-Z0-9-]+) ([A-Za-z0-9.-]*)$' )
LOCATION 's3://<BUCKET_NAME>/<ELB_NAME>/AWSLogs/<ACCOUNT_ID>/elasticloadbalancing/ap-northeast-1/';
```

パーティションは年、月で切れればいいので、year,monthを設定しました。

## パーティションを切る
```
ALTER TABLE <dbname>.<elbname> ADD PARTITION (year='2018',month='01') location 's3://<BUCKET_NAME>/<ELB_NAME>/AWSLogs/<ACCOUNT_ID>/elasticloadbalancing/ap-northeast-1/2018/01/';
ALTER TABLE <dbname>.<elbname> ADD PARTITION (year='2018',month='02') location 's3://<BUCKET_NAME>/<ELB_NAME>/AWSLogs/<ACCOUNT_ID>/elasticloadbalancing/ap-northeast-1/2018/02/';
...
略
```

## クエリしてみる
レスポンスタイムのパーセンタイルをクエリしてみます。
これはこれで別記事にするべきかもしれませんがめんどくさいので纏めます。

```
select 
    approx_percentile(client_response_time, 0.99) as percentile_99,
    approx_percentile(client_response_time, 0.95) as percentile_95,
    approx_percentile(client_response_time, 0.90) as percentile_90,
    approx_percentile(client_response_time, 0.5) as percentile_50,
    approx_percentile(client_response_time, 0.3) as percentile_30
from
    table_name
where
    year='2018' and month='12'
```

これでできるようになりました。S3にログのファイルがあるので好きなだけテーブルを作り変えれますね。
Re:dash、Docker,Nodeインストールから立ち上げまで。

環境 CentOS7

## Docker準備


### Docker install
[https://docs.docker.com/install/linux/docker-ce/centos/#install-docker-ce-1](参考(Get Docker CE for CentOS))


### docker-compose install
```
$ curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` > docker-compose
$ mv docker-compose /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
```

### 一般ユーザからdockerを使えるようにする

dockerグループに現行ユーザを追加すればよい

```
$ sudo groupadd docker
$ sudo gpasswd -a $USER docker
$ sudo systemctl restart docker
```
再接続すれば反映される。


### バージョン確認

```
$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01
```

## Node.js準備

2018/12/21現在最新のv10.14.2で試す。
＞Install Node.js (latest LTS or later is recommended, can be installed with Homebrew on OS/X)
Nvmを使ってInstallする。

### Nvm install

```
$ git clone git://github.com/creationix/nvm.git .nvm
$ source ~/.nvm/nvm.sh
$ nvm --version
0.33.11
```
「source ~/.nvm/nvm.sh」は.bash_profileへ追記しておく

### Node.js install

```
$ nvm install v10.14.2
$ nvm alias default v10.14.2
$ node -v
v10.14.2
```

# Redash の Docker install
[https://redash.io/help/open-source/dev-guide/docker](参考(Docker Based Developer Installation Guide))

###　redash ダウンロード

```
git clone https://github.com/getredash/redash.git
cd redash/
```

### データ永続化と作成
そのままだと、docker内のpostgresのデータは消えてしまう為、
永続化設定をする。

vi docker-compose.production.yml

``` 
postgres:
image: postgres:9.5.6-alpine
# volumes:
# - /opt/postgres-data:/var/lib/postgresql/data
```
上記のコメント部分を外せばOK

### DB作成

```
docker-compose -f docker-compose.production.yml run --rm server create_db
```

### 起動
```
$ docker-compose -f docker-compose.production.yml up -d
```
### 停止
```
$ docker-compose -f docker-compose.production.yml down
```

以上で完了。
docker nginxが80で立っているので、サーバのポートが空いていれば
接続すれば画面が確認できる。
Oracle → SQL Server DB LINK

http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05708-01/configodbc.htm

サンプルの初期化ファイルinitdg4odbc.oraが付属します。サンプル・ファイルは、$ORACLE_HOME/hs/adminディレクトリに格納されています。

ODBCゲートウェイ用の初期化ファイルを作成するには、サンプルの初期化ファイルをコピーしてその名前をinitsid.oraに変更します

# Express EditionにはGateway for SQL Serverがない
https://docs.oracle.com/cd/E36055_01/license.112/b66462/toc.htm#BABJIJCJ

# Gatewaysのありか
![oracle gatewaysのありか.PNG](https://qiita-image-store.s3.amazonaws.com/0/107052/d01b24a2-989d-bba7-3ad0-c1c44bd01d8b.png)
こんなとこにあった

# SQLServerのはまりポイント
TCP/IPが無効になっていたので有効にした。
するとやっとDBLINKがつながるようになった :sweat:
Cloud Functionsをcronっぽく実行

Cloud Functionsをcron実行したい...。
誰もが思うこの機能ですが、しかしCloud Functions自体にはCron機能はなく、何かしら別のサービスを組み合わせる必要があります。

私はCloud FunctionsのトリガーにCloud PubSubを設定し、Azure FunctionからメッセージをPublishすることで定期実行をやっていました。

HTTPをトリガーとしていないのは、セキュリティの問題です。Cloud FunctionsのURLはリージョン/プロジェクトID/名前で決まるので、特定されやすいとか、コードで認証つけたとしても認証されるまではちょっと実行される等々細かいところを突っ込まれるので、pubsubを使っています。

なぜAzure Functionだけでやっていなのはというと、Azure Functionでは動作しないが、Cloud Functionsでは動作する、というものがあったからです（詳細は省略）。

前置きが長くなりましたが、11月にリリースされたCloud Schedulerを使うことでより簡単に定期実行ができるようになりした。
上記のAzure Functionの部分をCloud Schedulerに置き換えた方法をご紹介致します。
https://cloud.google.com/scheduler/docs/quickstart
https://cloud.google.com/scheduler/docs/tut-pub-sub

- Create Cloud PubSub
- Create Cloud Functions
- Create Cloud Scheduler
- Run Job

## Cloud PubSub
Cloud PubSubを作ります。中継ポイントとなります。

```zsh

$ gcloud pubsub topics create test-topic
```
## Creater Cloud Functions
`--trigger-topic=test-topic`というふうに先程作成したトピックを指定していきます。

```zsh

$ gcloud functions deploy test --source='https://source.developers.google.com/projects/<project-id>/repos/tyarin/moveable-aliases/gcp' --runtime=nodejs8 --trigger-topic=test-topic
```

## Create Cloud Scheduler Job
ポータルのCloud Scheduler => ジョブを作成
ここでペイロードに動的な値（例えば時刻など）を入力する方法がわかりませんでした。ご存知の方教えていただけると幸いです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/119101/a9b8e002-de36-80ae-70f4-7e62b22e15b3.png)

## Run Job
ジョブ作成後、ジョブ一覧が見えるので「今すぐ実行」ボタンを押下。
下記のように結果が成功となればOKです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/119101/a01a6b07-20db-b9a1-15ae-f5546cfd81f7.png)

実行ログも確認することができます(Scheduler側)。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/119101/16393193-16ee-a9d3-1a8a-943210ec5ec3.png)



## まとめ
Cloud Schedulerをつかってcron形式でCloud Functionsを呼び出すことができました。
いままではAzure FunctionにGCPのクレデンシャルをもってきて...とやっていたのでそのへん楽になりました。
pythonとselceniumでIE11を動かす 準備編

画面単体テストとか言いながら画面ポチポチしてスクショして、、、の繰り返しに飽きた

# 環境
* windows10
* IE11
* python3.6.7
* celenium

# 動作確認

## 準備

### selenium install
pipでやる
`pip install selenium`

### driver download
[ここでおとす](https://www.seleniumhq.org/download/)

## 確認ソース
```py
from selenium import webdriver

def get_driver():
    return webdriver.Ie('C:/01_work/98_python/python_selenium/driver/IEDriverServer.exe')


if __name__ == '__main__':
    driver = get_driver()
```

## エラー
`SessionNotFoundException(Unexpected error launching Internet Explorer. Protected Mode)`が出た
[解決](http://rey1229.hatenablog.com/entry/2017/09/05/134227)

## 無事first pageが出ました
`driver.get(url)`とかで遷移可能
クロールとかに使えそう？
スクリーンショットとかもできるらしいから普段の業務にも使えそう
TableauレポートをGASでSlackに自動連携する方法

はじめまして、Classiの企画の小坂井です。
この記事では、GoogleAppScript（GAS）を使って、TableauレポートをSlackに連携する方法を紹介します。

# きっかけ
KPIとなる数値を、チームでウォッチしてアクションに繋げていく文化を作りたいと思ってました。
Classiでは、Tableauというデータを可視化できるツールを使っていますが、わざわざオンラインで開いて見る人は限られています。そのため、Tableauレポートをチームメンバーが一番確認しやすいSlackに連携することで、数値を見る文化を醸成できるのでは思い実施しました。

# 手順
1. 連携したいTableauレポートを選択し[サブスクライブ機能](https://onlinehelp.tableau.com/current/online/ja-jp/subscribe_user.htm)を使って、自分のGmail宛に定期配信します
2. GASファイルにコードをコピペします
3. コードの4箇所を置き換えます
4. 投稿させるSlackBotをチャンネルに招待する
5. 動作が問題ないか、GASの画面で実行ボタンを押下して確認します
GASファイルのトリガーを設定します（毎週月曜9時など）


## GASファイルをGoogleDriveから新規作成します
GoogleDriveの新規ボタン押下後、その他からGASファイルを作成できます
![スクリーンショット 2018-12-21 18.03.25.png](https://qiita-image-store.s3.amazonaws.com/0/323089/69e57ca9-b79b-0a6a-f18e-4805ae6eb569.png)
作成すると下記画面が表示されます。
![スクリーンショット 2018-12-21 18.04.57.png](https://qiita-image-store.s3.amazonaws.com/0/323089/1227d056-1f4c-b7b6-ca8a-668a77b20f30.png)

## GASファイルに下記コードをコピペします

先ほどのGASファイルの中に、以下のコードをコピペします。

Slack連携用GASソースコード

```javascript:
function myFunction() {
  //Tableauからの自動メール取得（条件に一致する最新のメールを一件取得）
  var Threads = GmailApp.search('from:"no-reply@tableau.com" subject:"[メールタイトル]"', 0, 1);
  var messages = Threads[0].getMessages();
  var message = messages[messages.length-1];
 
  //自動メールから画像と日付を取得
  var attachments = message.getAttachments();
  var date = message.getDate();
  var time = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy年M月d日');
  
  //slackAPI
  var SLACK_TOKEN='[TokenID]';
  var data = {
  'token':SLACK_TOKEN,
  'file':attachments[0],
  'filename': time + "KPIレポート",
  'channels':'[Slackチャンネル名]',
  'title':time + 'KPIレポート',
  'initial_comment': '[コメント]'
  };
  var option = {
  'method':'POST',
  'payload':data
  };
  UrlFetchApp.fetch('https://slack.com/api/files.upload',option);
};
```

## コードの4箇所を置き換えます
- [メールタイトル]
    - サブスクライブするTableauレポートのメールのタイトルに置き換えます。
- [TokenID]
    - 投稿させるSlackBotのトークンIDに置き換えてください。（IDの確認は[この記事](https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21)参照）
- [Slackチャンネル名]
    - 連携したいチームのSlackチャンネル名に置き換えてください。（#は不要です）
- [コメント]
    - Tableauレポートの画像合わせて送りたいメッセージを自由に記載ください。

## 投稿させるSlackBotをチャンネルに招待する
該当チャンネルで以下を入力し、Botを招待してください。
/invite @bot名

## 動作が問題ないか、GASの画面で実行ボタンを押下して確認します
動作に問題ないか▶︎実行ボタンを押下します。
![スクリーンショット 2018-12-21 18.11.22.png](https://qiita-image-store.s3.amazonaws.com/0/323089/f202fcd6-9e37-fce3-fbc9-64b2ebc3dfed.png)

## GASファイルのトリガーを設定します（毎週月曜9時など）
定期配信するために、時計マークのボタンを押下し、配信時間を設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/323089/bc5c5e4b-efd6-a1bf-ef60-d3510b2b45e1.png)


# まとめ
この結果、定期的にSlackにTableauのレポートを連携できるようになりました。以下のようにKPIとなる数値が簡単に見ることできるので、スレッドの中で議論が起きるなどの行動にも繋がりました。
連携するKPIレポート自体がアクションに繋げられない質のものだと意味はないですが、この取り組みを通して、前進できている気がします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/323089/90d93c86-4cf9-1daf-26bf-93c2b32592fd.png)
PHPでwebshellを作る

Make IT Advent Calendar 2018 21日目です。

コマンドを実行するPHPプログラムを作ろうと思います。

**今回のプログラムを他人がアクセスできるサーバに置くのは危険です。
実行する際は、注意してください。**

#環境
OS: Windows10
XAMPP: 7.2.7
PHP: 7.2.7
Apache: 2.4.33

#とりあえずコマンドを実行できるものを作る
###GET
```php:get_webshell.php
<pre><?php system($_GET["cmd"]);?></pre>
```
`system($_GET["cmd"])`でGETで受け取ったコマンドを実行し、表示しています。
URLにパラメータを付加し、コマンドを送ります。
######dateコマンドの送信
![get_webshell (2).png](https://qiita-image-store.s3.amazonaws.com/0/323583/fb8693a4-965d-069c-e29a-1739b9fbc236.png)
コマンドを実行できました。

###POST

```php:post_webshell.php
<pre><?php system($_POST["cmd"]);?></pre>
<form method="POST"><input autofocus type="text" name="cmd"></form>
```

テキストフォームを追加し、POSTでコマンドを送信します。
######timeコマンドの実行
![post_wevshell (2).PNG](https://qiita-image-store.s3.amazonaws.com/0/323583/2ff50d0a-7774-c180-f445-c67bba67fd12.png)
こちらも実行できました。

#機能追加
このままでは少し分かりづらいので、カレントディレクトリとコマンドの履歴を表示できるようにしてみました。

```php:webshell.php
<?php
session_start();

$rpath1 = [" ./", " .\\"];
$rpath2 = [" ../", " ..\\"];

if ($_POST["cmd"]) {
    $cmd= $_POST["cmd"];
    //相対パスの置き換え
    $cmd = str_replace ($rpath1, " ".trim($_SESSION["path"])."\\", $cmd);
    $cmd = str_replace ($rpath2, " ".trim($_SESSION["path"])."\\..\\", $cmd);
    $cmd = str_replace (":\\\\", ":\\", $cmd);
    if ($_POST["cmd"] === "session_reset") {
        //session_resetと入力することでリセットする
        $_SESSION = [];
    } elseif (preg_match("/^cd\s/i", $_POST["cmd"])) {
        // cd コマンドでカレントディレクトリを更新
        $_SESSION["history"] .= $_SESSION["path"]."<br>>".$_POST["cmd"]."<br>";
        $_SESSION["path"] = shell_exec($cmd." & @cd");
    } else {
        $_SESSION["history"] .= $_SESSION["path"]."<br>>".$_POST["cmd"]."<br><pre>".htmlspecialchars(mb_convert_encoding(shell_exec($cmd), "UTF-8"), ENT_QUOTES, "UTF-8", true)."</pre>";
    }
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>WebShell</title>
</head>
<body>
    <?php 
        if (empty($_SESSION["history"])) $_SESSION["history"] = "";
        if (empty($_SESSION["path"])) $_SESSION["path"] = shell_exec("@cd");
        echo $_SESSION["history"];    
        echo $_SESSION["path"] 
    ?>
    <form method="POST">
        ><input autofocus type="text" name="cmd">
    </form>
</body>
</html>
```

セッションを利用し、実行したコマンドとカレントディレクトリを保存しています。

ディレクトリの指定はコマンド中の` ./`や` ../`の相対パスを、保存したカレントディレクトリに置き換えることで再現しています。(ディレクトリを指定しないとカレントディレクトリはこのプログラムと同じ階層になる)
![webshell.PNG](https://qiita-image-store.s3.amazonaws.com/0/323583/34dac378-8245-a06e-0b9b-14cb4bd656a8.png)
###CSSの追加
せっかくなので見た目も変えます。
`<head>`内に下記を追加します。

```html
<style>
    *{
        color: #00ff00;
        font-size: 15px;
        font-family: Hack, monospace;
    }
    body{
        background-color: #000000;
    }
    input{
        border: 0px;
        background-color: transparent;
    }
</style>
```
![green_webshell.PNG](https://qiita-image-store.s3.amazonaws.com/0/323583/29c9beff-2316-7c63-67b3-a3d55699e75f.png)
かっこよくなりました。
#最後に
冒頭でも触れましたが、今回のプログラムを他人がアクセスできるサーバに置くのは危険なため、実行する際は注意してください。

------
PHP初心者でうまく実装できませんでしたが、最低限の機能をつけられたのは良かったです。
以上、Make IT Advent Calendar 2018 21日目の記事でした。
【PHP】sql文でデータベースのデータを取ってくる順番を指定する方法

データベースに保存されている内容をforeachで表示したいときに、保存されている内容の取ってくる順番を指定する方法を解説します。

今回は僕が作ったメモアプリを例にして説明します。
<br>

１、データベースに保存する内容のID(ここではmemo_id)のカラムをデータベースに作って、新しく保存されたらAL(オートインクリメント)で数値が1つずつ増えるようにする。
<br>
２、データベースの内容を取ってくる関数内のsql文を

```php
$sql = 'SELECT * FROM memo WHERE user_id = :u_id AND delete_flg = 0 ORDER BY memo_id DESC';
```

このようにする。
ORDER BYを使えば、昇順（そのままの順番・１から順にってこと）のASCか、降順（逆の順番）のDESCを指定できる。
１の手順のときのオートインクリメントによって、新しいデータほどIDの数値は大きくなっているので降順にするDESCを指定すれば新しい順にとってくることができる。

何も指定しなかったら昇順になる。
SORACOM LTE-M Button powered by AWS まとめのまとめ

ソラコムの江木です。
そしてこの記事は [SORACOM LTE-M Button powered by AWS Advent Calendar 2018](https://qiita.com/advent-calendar/2018/soracom) 21日目の記事でもあります。

今年も残り1週間と少しを残すのみになりました。ふりかえれば 4月の [Technology Camp 2018](https://soracom.jp/events/report-technology-camp2018/)、7月の[Discovery2018](https://pages.soracom.jp/report-discovery2018.html)、そして11月の [Technology Camp 2018 Fall](https://pages.soracom.jp/20181122_TechnologyCampFall_Report.html)など今年も主催イベント、これ以外にも各イベントに出展/参加させていただきました。皆様ありがとうございました。

2018年、ここまでのべ **28 の新サービス、機能追加をリリース**しました。*（注:まだ今年は終わってませんよ!)*
その中で最も多くの反響をいただいたのが [#あのボタン](https://twitter.com/search?f=tweets&vertical=default&q=%23%E3%81%82%E3%81%AE%E3%83%9C%E3%82%BF%E3%83%B3&src=typd) です

まとめは、@ko2aさんの[SORACOM LTE-M Button powered by AWS ドキュメントガイド](https://qiita.com/ko2a/items/6b7acc88da7312ae3aaf )をみていただくとして、ここではよくある質問をまとめたいと思います。

---

### LTE-M Button ってなにができる？

こちらをご覧ください！

* [SORACOM LTE-M Button powered by AWS でできる事や環境の準備まとめ](https://blog.soracom.jp/blog/2018/10/25/are-you-ready-for-lte-m-button/)


### でも、お高いんでしょ？

特別価格 3,980円（税別・送料別）は12月26日23:59までです。そのあとは通常価格 7,980円（税別・送料別)となります。

* [商品案内](https://soracom.jp/products/gadgets/aws_button/)


### 1年or1500回クリックを超えると使えないの？

* ソラコムのコンソールから登録することで期間およびクリック回数は自動更新となります。(更新手数料は 1,200円（税別)です。)


### みんな何に使ってるの？

「で、何に使えるの？」ですが、使い方はあなた次第です。たくさんのやってみたブログがありますが、@ko2aさんの[SORACOM LTE-M Button powered by AWS ドキュメントガイド](https://qiita.com/ko2a/items/6b7acc88da7312ae3aaf) にまとまっています！

ちなみに、私のは[SORACOM LTE-M Button で Google Home と Line に「いまからお父さん帰るよ」通知やってみた](https://qiita.com/NoriyukiEgi/items/bd0eca4a7b05ea939765)です。

[SORACOM LTE-M Button powered by AWS Advent Calendar 2018](https://qiita.com/advent-calendar/2018/soracom) にも #やってみた がたくさんあります。
さらに [#あのボタン](https://twitter.com/search?f=tweets&vertical=default&q=%23%E3%81%82%E3%81%AE%E3%83%9C%E3%82%BF%E3%83%B3&src=typd) でTwitterを検索するとホットな話題に出会えるはずです。



### よくわかった。それで注意点とかある？

よくある注意点はこの2つです。

* コンソールから登録することなく、1 年間（365 日）もしくは 1,500 回分のクリックを超過した場合は使用できなくなりますのでご注意ください。（解約処理が実施されます）
    *  → なので、継続して使いたい方は早めに登録を！

* ソラコムのコンソールからデバイスを解約した場合はデバイスは使用できなくなります。再び使用することはできません。
    * → そして、こちらにも注意してください。

ぜひ、お試しください！
Kubernetes 1.13.0 SIG-Storage変更点

# はじめに
本ドキュメントでは、Kubernetes 1.13.0のCHANGELOGをベースにStorageに関する機能について紹介します。

# 主な変更点
Kubernetes v1.13にてCSI(Container Storage Interface)がGAとなりました。:confetti_ball:
これによりサードパーティのストレージベンダはKubernetesのソースコードに触らずに、Kubernetes用のストレージドライバを開発することができます。
さらに、ファイルフォーマットなしのrawボリュームであるBlock VolumeがBetaに昇格、Topology AwareのVolume SchedulingがStableに昇格しました。

# その他の変更点
- CSI Volumeの容量制限が正しく表示されず、ノードに割り当てられてしまうバグを修正  ([#70540](https://github.com/kubernetes/kubernetes/pull/70540))
- CSI DriverがVolumeの割り当て時に、StorageClassのmountOptionsを利用できるようになりました ([#67898](https://github.com/kubernetes/kubernetes/pull/67898))
- Azure fileをマウントした際のパーミッションのデフォルト値を`0755`から`0777`へ変更されました ([#69854](https://github.com/kubernetes/kubernetes/pull/69854))
- コンテナ化されたkubeletは、シンボリックリンクを参照する前にリンク先が存在するかどうかをチェックするようにしました([#69565](https://github.com/kubernetes/kubernetes/pull/69565))
- iSCSIをデタッチする際にpanicを起こさないように強化しました。加えてunmount済みのディレクトリを再度unmountしないようにしました ([#69140](https://github.com/kubernetes/kubernetes/pull/69140))
- CSIPersistentVolume機能がGAとなりました ([#69929](https://github.com/kubernetes/kubernetes/pull/69929))
- CSI Driver APIの幾つかのObjectにて空文字許可を設定しました ([#69331](https://github.com/kubernetes/kubernetes/pull/69331))
- Flex volume pluginにて、ボリューム容量を増やすことができるexpandvolumeと、ファイルシステムのリサイズを行うexpanfsの2つのコマンドをサポートしました ([#67851](https://github.com/kubernetes/kubernetes/pull/67851))
- ノードに接続できるボリューム数の制限をレポートするAttachVolumeLimitがデフォルトで有効になりました ([#69225](https://github.com/kubernetes/kubernetes/pull/69225))
- 全てのaddonのStorageClassにbetaである`storageclass.beta.kubernetes.io/is-default-class`のannotationが付いていましたが、GAの`storageclass.kubernetes.io/is-default-class=true`のannotaionに変更となりました ([#10149](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.13.md#sig-storage-1))
- GlusterFS のPVの`glusterfsVolumeSource`が`glusterfsPersistentVolumeSource`に変更となりました。さらにendpointのnamespaceへの参照である`EndpointsNamespace`フィールドが追加しました。これを利用する際は、kubelet1.13以降にアップグレードしてください ([#60195](https://github.com/kubernetes/kubernetes/pull/60195))
- GetVolumeLimits で出力されるログを修正しました ([#69558](https://github.com/kubernetes/kubernetes/pull/69558))
- `MountPropagation`機能は、v1.13では無条件で有効になります。無効には出来ません ([#68230](https://github.com/kubernetes/kubernetes/pull/68230))

# 参考情報

- [ Major Themes#sig-storage](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.13.md#sig-storage)
- [ Release Notes From SIGs#sig-storage](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.13.md#sig-storage-1)
ちょwwwPyTorchでnanが出て困ってるんだがww【解決してやるよ】

YouTubeみたいなタイトルをつけたことは後悔してない(してる)。

さて今回はご紹介するのはこちら!
複雑なDeep Learningのネットワークで学習していたら出てくるnanさん〜(BGM)。

うざいですよね〜。しかも一回出るとやり直さざる得ない。
でも奴の出現する法則がよくわからない。

うまくいっている風でもなんか出ます。

検索しても「てめえの学習が悪いんじゃね?(意訳)」と言われます...(実際悪いんでしょうけど)。

とはいえ、それを直すのも泥沼なので対処療法で直しましょう!!

注意点として、nanの回避はできますが、学習がうまくいくかは保証できません。

環境としては

- **PyTorch >= 0.4.1**
- Python3.7

とします。
ChainerやTensorflow使いのかたは申し訳ありません...。

# サクッと解決法

```
model = ...
optimizer = ...
loss =  ...

if torch.isnan(loss):
    model = prev_model
    optimizer = torch.optim.Adam(model.parameters())
    optimizer.load_state_dict(prev_optimizer.state_dict())
else:
    prev_model = copy.deepcopy(model)
    prev_optimizer = copy.deepcopy(optimizer)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
```


# Step by step

## 1.nan検出をしよう

まずはこれが重要ですね。
`torch.isnan()`を使いましょう。

```
>>> import torch
>>> torch.isnan(torch.tensor([1,2,float('nan')]))
tensor([0, 0, 1], dtype=torch.uint8)
```

## 2.modelとoptimizerの値を保存しておこう

nanが出るケースは2パターンあります。

1.lossがnanになる
2.1つ前のパラメータのbackward時に一部パラメータがnanになる

現象としては結局どちらも同じですが、
一番最初にlossがnanになるのかパラメータがnanになるのか、という話ですね

1のケースが多いと思われがちですが、意外と精査すると2のケースもあります。

そのためうまくいっているデータを取っておきましょう。
optimizerも取っておくのは次で必要だからです。

```
if torch.isnan(loss):
    # ignore this section
else:
    prev_model = copy.deepcopy(model)
    prev_optimizer = copy.deepcopy(optimizer)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
```

一応ちゃんとdeepcopyしておきましょう。

## 3.nanが出たら代入しよう

そのまま代入すれば解決...と思いきや、
prev_modelをmodelに代入すると紐づいてるoptimizerの何やかんや(何かはわからない)が切れて更新されなくなります。

optimizerをもう一度定義し直しましょう。

```
if torch.isnan(loss):
    # section 3
    model = prev_model
    optimizer = torch.optim.Adam(model.parameters())
    optimizer.load_state_dict(prev_optimizer.state_dict())
else:
    prev_model = copy.deepcopy(model)
    prev_optimizer = copy.deepcopy(optimizer)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
```

これで一応解決です。

# 確認用コード
```
import copy
import torch
import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
  # 
  def __init__(self):
    super(Model, self).__init__()
    self.l1 = nn.Linear(10,5)
    
  def forward(self, x):
    out = self.l1(x)
    return out

criterion = nn.CrossEntropyLoss()
model = Model()
optimizer = torch.optim.Adam(model.parameters(), weight_decay=1e-5)

x = torch.rand((1,10), requires_grad=True)
t = torch.tensor([3])

# save model and optimizer
prev_model = copy.deepcopy(model)
prev_optimizer = copy.deepcopy(optimizer)

optimizer.zero_grad()
print(model.l1.weight)
y = model(x)
loss = criterion(y,t)
loss.backward()
optimizer.step()

print(model.l1.weight)

optimizer.zero_grad()
y = model(x)
loss = criterion(y,t)
loss.backward()
optimizer.step()

print(model.l1.weight)

model = prev_model
optimizer = torch.optim.Adam(model.parameters(), weight_decay=1e-5)
optimizer.load_state_dict(prev_optimizer.state_dict())

optimizer.zero_grad()
print(model.l1.weight)
y = model(x)
loss = criterion(y,t)
loss.backward()
optimizer.step()

print(model.l1.weight)
```
cocoonで1対多対1のフォームを作ろうとしたときの話

# 概要
[cocoon](https://github.com/nathanvda/cocoon)で関連モデルも含めたformを作ることができるが、1対多対1のような、関連先の更に先の関連まで含めたフォームを作るためのTipsがあまりなかった&うまくできない部分もあったので、ここに残しておきます。

# cocoonで1対多対1のフォームを作る

コントローラー、ビュー、モデルそれぞれに分けて書いていきます。

## モデル

```Ruby
class Parent < ApplicationRecord
  
  has_many :children, dependent: :restrict_with_exception, inverse_of: :parent
  accepts_nested_attributes_for :children, allow_destroy: true
end

class Child < ApplicationRecord

  belongs_to :parent
  has_one :grand_son, dependent: restrict_with_exception, inverse_of: :child
  accepts_nested_attributes_for :grand_son, allow_destroy: true
end

class GrandSon < ApplicationRecord

  belongs_to :child
end
```

親側に`accepts_nested_attributes_for`をつければいいだけです。
cocoonのREADMEに書いてあるとおりですね。

## コントローラー

```Ruby
class ParentsController < ApplicationController

  # 詳細は省略
  def create
    @parent = Parent.create!(parent_params)
  end

  private

  def parent_params
    params.require(:parent).permit(
      :name,
      children_attributes: [
        :id,
        :name,
        :_destroy,
        {
          grand_son_attributes: [
            :id,
            :name,
          ],
        },
      ])
  end
end
```

以上のような形で、ストロングパラメーターに`xxx_attributes`を孫のモデルまで一気に書いてしまいます。
これで一気に孫のモデルまで登録できるようになります。

## ビュー

問題はビューです。

[このWiki](https://github.com/nathanvda/cocoon/wiki/has_one-association)によれば、`force_non_association_create`を`true`にしてしまえば、1個しか追加できないようなのですが、子と孫が1対1の関係の場合は、複数個追加できてしまいます。
これでは狙ったとおりにできないので、自分は以下のように対応しました。

```application.js
$('#children')
  .on('cocoon:after-insert', function () {
    $(this).css('cssText', 'display: none !important');
});
```

上記のようにすることで、追加ボタンを押した際に、その追加ボタンを消してしまうことができます。
ただ、すごくかっこ悪いので、いい方法があれば、ご教示いいただけますと幸いです。
機械学習論文読みメモ_146

[On Characterizing the Capacity of Neural Networks using Algebraic Topology](https://arxiv.org/abs/1802.04443)
データの複雑性に関する計算可能な指標を用いて直接に
異なったネットワークの学習可能性を特徴付ける事は可能である。
本論では、inductive biasを超えて、最も表現性と一般性の高い構造
はデータに対してどのように決まるのかという観点より構造探索の
問題を再定義する。
本論ではまず代数的幾何をデータの複雑性を表す指標として用いる事
を提案する。
その上で、モデルの一般化性能を限定する要因として位相構造に対する
表現力があることを示す。
そしてさらにネットワークの位相的な複雑性を特徴づけを行う。

[Learning Multiple Levels of Representations with Kernel Machines](https://arxiv.org/abs/1802.03774)
ニューラルネットワークにインスパイアされたカーネルマシンを提案する
この手法は従来のカーネルマシンに対していくつかのメリットを持つ。
提案モデルは、分散または階層表現が可能である。
性能はカーネル関数の選択に対してロバストである。
解空間はＲＫＨＳ上の学習データのspanに限定されない。
このモデルに対して、greedyな学習手法を提案する。
この手法によって、各層毎の学習が勾配法を利用する事なく可能になる。
これはＲＫＨＳ上の学習データ構造に対する最適化を行うことで実現する。

[Image Transformer](https://arxiv.org/abs/1802.05751)
画像生成の問題は自己回帰的な逐次生成の問題にうまく帰着できる。
最近の研究では、self-attentionを用いる事でtextual sequenceを効率的に扱う事ができる事がわかっている。
本論ではこうしたself-attentionに基づく手法を一般化し、画像生成に適用可能にした。
提案手法で用いるTransformerは近傍のみのattentionに限定する事で、
実用時に処理効率を改善する事ができる。
その一方で、CNNと比べて大きな受容体領域を確保する事ができる。
また2次元データである画像の性質に合わせたattentionの仕組みも提案する
C++ Builder XE4 > TPanelとColor > TPanel上の指定コンポーネントの背景色を変更する

```txt:動作環境
C++ Builder XE4
```

### 処理概要

- TPanel(PNL_base)上にコンポーネントがある
    - TEdit
    - TChart
    - TPanel
    - TShape
- これらのコンポーネントに対して同じ背景色で塗りたい

### 実装

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	changeColor(PNL_base, clAqua);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::changeColor(TPanel *pnlBasePtr, TColor toColor)
{
	TComponent *ptarget;

	for(int idx=0; idx < pnlBasePtr->ControlCount; idx++) {
		ptarget = pnlBasePtr->Controls[idx];
		// 1. TEdit
		if (dynamic_cast<TEdit *>(ptarget) !=NULL) {
			TEdit *dstPtr = (TEdit *)ptarget;
			dstPtr->Color = toColor;
		}
		// 2. TChart
		if (dynamic_cast<TChart *>(ptarget) != NULL) {
			TChart *dstPtr = (TChart *)ptarget;
			dstPtr->Color = toColor;
		}
		// 3. TPanel
		if (dynamic_cast<TPanel *>(ptarget) != NULL) {
			TPanel *dstPtr = (TPanel *)ptarget;
			dstPtr->ParentBackground = false;
			dstPtr->ParentColor = false;
			dstPtr->Color = toColor;
		}
		// 4. TShape
		if (dynamic_cast<TShape *>(ptarget) != NULL) {
			TShape *dstPtr = (TShape *)ptarget;
			dstPtr->Brush->Color = toColor;
		}
	}
}
```

### 動作例

Button1押下後

![2018-12-21_15h32_18.png](https://qiita-image-store.s3.amazonaws.com/0/32870/38b4293e-3ecf-5f2a-7231-30b931c9d4a6.png)

PNL_baseの色変更時に子コンポーネントの色も合わせて変更する
時などに使う。
Cloud Bigtable用のインタラクティブCLI btcli を書きました

これは [Google Cloud Platform その２ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/gcp2) 21日目の記事です。

## 作ったもの

インタラクティブUIを備えたcbtベースのBigtable用CLI [btcli](https://github.com/takashabe/btcli) を作りました。

## モチベーション

[GoでClean Architecture導入とDual WriteによるDB移行をした話](https://qiita.com/takashabe/items/e7f3027f4f7781e090fe) にある通り、現在はBigtableをメインに使っているプロダクトで開発を行っています。Bigtableはチョッパヤでめちゃくちゃスケールするので非常に便利で僕も大好きなプロダクトです。
手元でBigtableのデータを読み書きするには公式で [cbt](https://github.com/googleapis/google-cloud-go/tree/master/bigtable/cmd/cbt) というものが用意されていて、最低限必要なものは揃っています。
先の記事でも言及していますが、Bigtableのincrement関数を使うためには8byteビッグエンディアンにエンコードした値を使う必要があります。ところがcbtでは文字列としてでしか値を表示することが出来ません。内部的にはデータはbyteで保存されていて、型による区別がないため当然といえば当然ですが、人間が扱うときには少し困ります。

当初はビッグエンディアンのデコード機能をcbtにモンキーパッチを当てて使っていましたが、もう少しリッチなクライアントが欲しくなり作ったのが [btcli](https://github.com/takashabe/btcli) です。ちなみに名前はmycliからインスパイアしました。

## 出来ること

### インタラクティブな補完

ほぼ全て [go-prompt](https://github.com/c-bata/go-prompt) のおかげで実装出来ています。

![tty](https://user-images.githubusercontent.com/681508/44247754-9ad3ea80-a221-11e8-9172-2cb709e1420a.gif)

### 豊富なフィルタオプション

現在 `read` サブコマンドで以下のオプションが使用可能です。

```
read <table> [args ...]
        start          Start reading at this row
        end            Stop reading before this row
        prefix         Read rows with this prefix
        value          Read rows with has value
        family         Read only columns family with <columns_family>
        version        Read only latest <n> columns
        from           Read cells whose version is newer than or equal to this unixtime
        to             Read cells whose version is older than this unixtime
        decode         Decode big-endian value
        decode-columns Decode big-endian value with columns. <column_name:<string|int|float>[,<column_name:...>]
```

これだけあると大体の場合において事足りない感じがしています。全てのフィルタは網羅出来ていませんが、需要ベースで追加しているので、ここにないフィルタや機能があったらカジュアルに追加しています。もし欲しいものがあればissues, PRお待ちしております。
また冒頭に書いていたdecodeオプションもここに用意しています。 `decode` が全体設定、 `decode-columns` が個別設定でこちらのほうが優先度高い感じです。環境変数 `BTCLI_DECODE_TYPE` を設定することでデフォルトの `decode` オプションを指定することも出来ます。

## 出来ないこと

write系のコマンドは自分自身あまり使ったことが無いので実装していません。

## インストール方法

`go get` で入ります。調子に乗ってmodule化したので環境変数 `GO111MODULE` が必須です。

```
go get -u github.com/takashabe/btcli/cmd/btcli
```

## まとめ 

インタラクティブUIを備えたcbtベースのBigtable用CLI [btcli](https://github.com/takashabe/btcli) を作りました。

実際に仕事でも使っていて、チームでも好評なので作ってよかった感があります。まだまだやりたいことがあるので時間を見つけては開発を続けていきたいと思っています。
ユースケースが合致する方はぜひ使ってみてください！