OmniAICreator/Qiita-1.07M huggingface dataset:
sklearnのpipelineに自分で定義した関数を流し込む

## はじめに
データ分析のコードを書く時に，自分で定義した関数やモジュールがとっちらかったりすることがよくあります．（僕だけかもしれない）

簡単に書けて，どんな処理をしているかわかりやすい管理の仕方はないかと考えたところ，sklearnの[pipeline](http://scikit-learn.org/stable/modules/pipeline.html)にそのまま乗っかるのがいいのではないかという結論に至りました．

自分で定義した関数をpipelineで用いるのは割と簡単にできて，
1. sklearnからpipelineに流せるクラスを持ってくる
2. そのクラスに自分の関数をtransformという名前で定義する．
だけです．

## 環境
- Python 3.6.0
- sklearn 0.18.1

## pipelineに流せるベースクラスの定義
```python:skPlumber.py
from sklearn.base import BaseEstimator, TransformerMixin

class skPlumberBase(BaseEstimator, TransformerMixin):
    def __init__(self):
        pass

    def fit(self, X, y=None):
        return self

    def transform(self, X):
        return self
```

skleanのコードを見るとpipelineに流せるものは，BaseEstimator, TransformerMixinを継承しています．
それにわかりやすい名前をつけてベースクラスとしておきます．
（ちなみにplumberは配管工という意味らしいです．sklearnのパイプを継ぎ接ぎするという意味を込めて．）

## 自分の関数の定義
```python:skPlumber_example.py
from skPlumber import skPlumberBase

class MyProcess(skPlumberBase):
    def __init__(self, param1=10):
        self.param1 = param1

    def transform(self, X):
        Y = self.param1*X
        return Y
```

skPlumberをどこかに置いておいて，それをインポートします．
また，何かパラメータを求めたりせず，処理をするだけであればtransformという名前でメソッドを定義してあげます．

## パイプに流してみる

これだけです．
というわけで試してみましょう．

```python:skPlumber_example.py
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import FeatureUnion, Pipeline

iris = load_iris()
X = iris["data"]
t = iris["target"]

estimators = [('scaler', StandardScaler()), ('my_process', MyProcess(param1=-10))]
pipe = Pipeline(estimators)
X2 = pipe.fit_transform(X)
```

```text
X2.shape
(150, 4)

X2
array([[  9.00681170e+00,  -1.03205722e+01,   1.34127240e+01,
          1.31297673e+01],
       [  1.14301691e+01,   1.24957601e+00,   1.34127240e+01,
          1.31297673e+01],
       [  1.38535265e+01,  -3.37848329e+00,   1.39813811e+01,
          1.31297673e+01],
```

続けて処理をしてくれていそうですね．

さらに`FeatureUnion`を使えば，いくつか特徴量を計算してそれをまとめたものを返すというようなこともできます．

```python:skPlumber_example.py
estimators = [('my_process', MyProcess(param1=10)), ('my_process2', MyProcess(param1=-10))]
combined = FeatureUnion(estimators)
X3 = combined.fit_transform(X)
```

```text
X3.shape
(150, 8)

X3
array([[ 51.,  35.,  14., ..., -35., -14.,  -2.],
       [ 49.,  30.,  14., ..., -30., -14.,  -2.],
       [ 47.,  32.,  13., ..., -32., -13.,  -2.],
       ...,
       [ 65.,  30.,  52., ..., -30., -52., -20.],
       [ 62.,  34.,  54., ..., -34., -54., -23.],
       [ 59.,  30.,  51., ..., -30., -51., -18.]])
```

## おわりに
試しにしばらくこれでやってみて使い心地を試したいです．

## 追記：参考になりそうなリンク
[ラップしてpipeに流せるようにする](https://datascience.stackexchange.com/questions/10476/how-to-make-sklearn-pipeline-using-custom-model)
こんな感じですでに定義された関数をラップしまくったコードを書く方が簡単そうだ．

[sklearn準拠モデルの作り方](https://qiita.com/roronya/items/fdf35d4f69ea62e1dd91)
モデルをメインに解説してくれている．先に読みたかった．
WebRTCでAndroidアプリ作りさらにiOS&Macアプリを作ろうして難儀している話

WebRTCの力を借りてアプリ作ったんですよ。

##現物
ソーシャル仮想散歩アプリ[SmanpoWiz](https://play.google.com/store/apps/details?id=com.smanpo.wiz)

Googleストリートビューの景色に没入しFacebookまたはLINEの仲間と散歩気分でビデオ通話を楽しむ事ができる。
映像から利用者の動きを検出し、動いた分だけストリートビューの景色が進み、相手と近づいたり離れたりでき、仲間との散歩を仮想体験できる。

動画は↓(画像をクリックするとYouTubeが開きます)
[![SmanpoWiz](https://img.youtube.com/vi/QzSgrKJ8hzY/0.jpg)](http://www.youtube.com/watch?v=QzSgrKJ8hzY)


##経緯
以前より歩数計センサーとGoogleストリートビューをのっけた仮想散歩アプリ「Smanpo([Android](https://play.google.com/store/apps/details?id=com.smanpo.smanpo),[iOS](https://itunes.apple.com/jp/app/smanpo/id1076764222?mt=8))」ってのを作っていた。
その後、室内で座って腕を振りつつ流れる景色を楽しめばなんか健康的でいい感じだろうと思い、歩数計センサーの代わりにカメラで動きを検出するカメラモード(iOSのみ)って機能を追加した。ちなみに[Mac](https://itunes.apple.com/jp/app/smanpo/id1253816385?mt=12)アプリは新規で作成した。
ビデオ通話機能を盛り込めば仲間と楽しめるんじゃないかと思い、WebRTC([Skyway](https://webrtc.ecl.ntt.com/))に手を出した。


##実装
とりあえずjsベース(PeerJS)のサンプルコードを触ったらちょー簡単にビデオ通話できたのでNativeアプリにはwebview実装という安易な選択を企んだ(2017年8月頃)。
Android：手元の端末でCrosswalkというWebViewエンジンを利用したらWebRTCが動いたのでこれ使えば端末環境による差異を吸収してくれるらしいしいいなこれ、って事で採用。
iOS,Mac：Safari11からWebRTCに対応するとのことで、アプリ実装時のWebView(WKWebView)もWebRTCに対応するだろう、つまりAndroidが出来上がる[2017年秋頃には環境が整うだろう](https://www.apple.com/jp/newsroom/2017/09/ios-11-available-tomorrow/)とたかをくくっていた。

##現状
Android：[できました](https://play.google.com/store/apps/details?id=com.smanpo.wiz)！既存アプリに機能追加ではなく別アプリとしてローンチしました。
iOS,Mac：できず涙

##iOS,Mac環境について
当初の目論見から外れ、いざ蓋を開けて見るとSafari11が動いているiOS11(MacはHighSierra?)のWKWebViewでは[WebRTCが動いておりませんでした](https://forums.developer.apple.com/thread/88052)。がーん。

##今後
[mashupaward](http://mashupaward.jp/)という開発者のお祭りの[2ndSTAGE](https://mashupawards.connpass.com/event/70838/)というところで発表できることになったので自慢してくる。
ローンチ済みのAndroidを[キレイにしてから](https://support.skyway.io/hc/ja/articles/115012252947-SkyWay%E6%AD%A3%E5%BC%8F%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E5%8C%96%E3%81%AE%E3%81%8A%E7%9F%A5%E3%82%89%E3%81%9B%E3%81%A8%E3%81%8A%E9%A1%98%E3%81%84)iOSでは心を入れ替えて[SDK](https://webrtc.ecl.ntt.com/ios-sdk.html)を使い実装する。


##未解決問題←解決しました！
Macにはsdkなさげけどどうやって実装するんだろう？？素直にwebアプリという手もあるがMac app storeってiOSほど盛り上がっていないから個人アプリ供給者としては需給バランス的に配信チャネルとして魅力なんだよなぁ。
12/7追記：エレクトロンってのを使うとmac-webviewでWebRTCが使えるんじゃないかという話を[WebRTCもくもく会](https://webrtc.connpass.com/event/72799/)で教えていただきました。ありがとうございます！今回のイベント主催者の[WebRTC Beginners Tokyo](https://webrtc.connpass.com/)の皆さんはふわ系の私のような人にでも親切に教えてくれます。興味のある方はお気軽にjoinしてみましょう！
UnityからTestFlight GooglePlay 遷移先URL メモ


■Unity C# からの呼び出し

●iOS側
※TestFlightのURLへ直接遷移させるためのURL

```
　Application.OpenURL("https://beta.itunes.apple.com/v1/app/iTunesConnectのアプリID");
```

●Android側
※AndroidはオプトインURLを指定すればOK

```
  Application.OpenURL("https://play.google.com/apps/testing/バンドルID");
```
Laravel 5.4で追加された「Higher Order Messages」がすごい

Laravel 5.4 で追加された Higher Order Messages を使ってけっこう感動した。

https://laravel.com/docs/5.5/collections#higher-order-messages

Laravelのコレクションに対して、クロージャーを使わずに様々な処理を行えるもの。

具体例で説明したい。

# 前提

`Company` と `User` というモデルがあるとする。

- Company hasMany Users
- User belongsTo Company

という関係。

`Company` モデルには

- 契約期限が切れているかを判定する `getIsContractExpiredAttribute` 
- 契約期限が切れている企業の各社員にメールする `notifyContractExpiration` 

というメソッドが生えている、とする。で、

- 契約期限が切れた `Company` をランダムに5件取得
- その `Company` の社員に対して、契約期限切れのメールを送りたい

となったとする。

（色々おかしいと思いますが、コレクションの説明のため）

# Before (~ 5.3)

```php
Company::with('users')
    ->all()
    ->filter(function ($company) {
        return $company->isContractExpired;
    })
    ->take(5)
    ->pluck('users')->flatten()
    ->each(function ($user) {
        $user->notifyContractExpiration();
    });


```

# After (5.4 ~)

```php
Company::with('users')
    ->all()
    ->filter->isContractExpired
    ->take(5)
    ->flatMap->users
    ->each->notifyContractExpiration();
```

クロージャーが減ってめちゃくちゃ気持ち良い。

また、後者ではしれっと `flatMap` も使っている。これも便利。

# ちょっと解説

上の例で `Company::all()->map` とすると、 `Illuminate\Support\HigherOrderCollectionProxy` というものが返ってきて、これが色々やってくれるっぽい。


この機能が使えるメソッドは以下の通り。

- average
- avg
- contains
- each
- every
- filter
- first
- flatMap
- map
- partition
- reject
- sortBy
- sortByDesc
- sum

上記の例で、例えば `Company::all()->sum->isContractExpired` とすると、契約期限が切れた企業の総数が返ってくる。

SQLみたいで楽しい。
RailsでExcelファイルを出力する

今回は[Axlsx_rails](https://github.com/straydogstudio/axlsx_rails)というgemを使います。
ボタンを押したらダウンロード出来るとこまでやります。

## 環境
・ruby 2.3
・Rails 5.1

# 準備
gemを追加

```ruby:Gemfile
gem 'rubyzip', '>= 1.2.1'
gem 'axlsx', git: 'https://github.com/randym/axlsx.git', ref: '776037c0fc799bb09da8c9ea47980bd3bf296874'
gem 'axlsx_rails'
```

Mime::Typeを追加

```ruby:config/initializers/mine_types.rb
Mime::Type.unregister :xlsx
Mime::Type.register "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", :xlsx
```

任意のアクションに対して下記のコードを追加(model名は適当です)

```ruby:app/assets/products_controller.rb
class ProductsController < ApplicationController

def index
  @products = Product.all
  respond_to do |format|
    format.html
    format.xlsx {
      response.headers['Content-Disposition'] = 'attachment; filename="Product.xlsx"'
    }
  end
end
```

# テンプレートの作成
出力するファイルのデザインや、要素を書き込んでいきます。

Axlsx_railsはAxlsxというgemに依存しているのでAxlsxのサンプルがそのまま使えます。
[Axlsx サンプルコード](https://github.com/randym/axlsx/blob/master/examples/example.rb)

それでは実際に作っていきます。

## 実装
`app/views/products`フォルダにテンプレートファイルを作成します。

ファイル名には規則があります。
`action名.xlsx.axlsx`

今回は`index.xlsx.axlsx`になります。
もし、`actionがcreate`だとしたら
`create.xlsx.axlsx`というファイル名になります。

```ruby:app/views/products/index.xlsx.axlsx
wb = xlsx_package.workbook
wb.styles do |style|
  highlight_cell = style.add_style(bg_color: "EFC376")

  wb.add_worksheet(name: "Products") do |sheet|
    @products.each do |product|
     sheet.add_row [product.title, product.price], style: [nil, highlight_cell]
    end
  end
end

```

次にダウンロードボタンを追加します。

```ruby:app/views/products/index.html.erb
<%= link_to 'Download spreadsheet', product_path(format: :xlsx), data: {turbolinks: false} %>
```

これでExcelファイルをダウンロードできるようになりました。

## 参考サイト
・[Generate Excel Spreadsheets with Rails and the Axlsx Gem](https://www.sitepoint.com/generate-excel-spreadsheets-rails-axlsx-gem/)
・[【Rails】Rubyテンプレートで axlsx を出力する方法](http://system.blog.uuum.jp/entry/ruby-template-axlsx)
・[axlsx_rails を用いて Excel のスプレッドシートを生成する](https://qiita.com/shao1555/items/9c55dcf33d6234d197ac)
・[RailsでExcelを扱うGemまとめ](https://qiita.com/Kta-M/items/02a2c41c5624f75498aa)
定義されたgetアクセサーでソートしたい


以下、学生テーブルです。

```sqlite3:students

 | ID | 名前 | 国語 | 数学 | 英語
 |-------------------------------
 | 1  | 一郎  | 99  | 78   | 66
 | 2  | 次郎  | 50  | 100  | 87
 | 3  | 三郎  | 88  | 91   | 87
```
DBに存在しない`total`アトリビュートを作成します。

```php:App\Students.php

class Students extends Model
{
    protected $appends = ['total'];

    public function getTotalAttribute() {
        $japanese = $this->attributes['japanese'];
        $mathematics = $this->attributes['mathematics'];
        $english = $this->attributes['english'];
        return $japanese + $mathematics + $english;
    }
}
```
作成された`total`アトリビュートでソートする

```php:App\Http\Controllers\StudentController.php

class StudentController extends Controller
{
    public function index()
    {
        $students = Students::orderByRaw('(japanese + mathematics + english) desc')->paginate(10);
        return view('student.index', ['students'=> $students]);
    }
}
```
以上です。
組合せ最適化で因子の部屋を解く

Advent Calendar 6日目の記事 [組合せ最適化でタイルペイントを解く](https://qiita.com/SaitoTsutomu/items/ec7cbdb04ba05763c2b8)
Advent Calendar 8日目の記事 [組合せ最適化でのりのりを解く](https://qiita.com/SaitoTsutomu/items/7e7a6e5e0dbc396c35b6)

## これなに

**因子の部屋**を、Pythonで[組合せ最適化](https://qiita.com/SaitoTsutomu/items/bfbf4c185ed7004b5721)モデルを作って解きます。
解く楽しみは、モデル化を工夫することになります。

自分でも試してみたい人は、下記を参考にしてください。

- [数独を通して組合せ最適化を学ぼう](https://qiita.com/SaitoTsutomu/items/bd09190d8a02432b3f16)

## 問題

- すべてのマスに１からNまでの数字のどれかを１つずつ入ります（０は使いません）。
- タテ列、ヨコ列のどれにも、１からNまでの数字が１つずつ入ります。
- 太線で囲まれた四角形（部屋）の左上のマスに小さく書かれている数は、その部屋の各マスに入る数をすべてかけあわせた値となります。

左が問題で、右が答えです。

![](https://raw.githubusercontent.com/SaitoTsutomu/opt4puzzle/master/pic/inshi.png)

Pythonでは、`data`（部屋のグループ）、`nums`（グループ別の値）を使うことにします。

```py3:python
import pandas as pd
from math import log
from pulp import LpProblem, lpSum, lpDot, value
from ortoolpy import addbinvars
data = """\
ABBCD
AEEFD
GGHFD
IJHKK
ILHMM""".splitlines()
nums = {'A':6, 'B':15, 'C':1, 'D':12, 'E':20, 'F':8,
    'G':10, 'H':6, 'I':4, 'J':4, 'K':15, 'L':1, 'M':10}
```

## 変数表

下記のような変数表を作成します。各行の変数(Var)は0または1をとります。
変数の値が1ならば、該当行 該当列のマスが該当の数になります。

<table><tr><th></th><th>行</th><th>列</th><th>数</th><th>字</th><th>Var</th></tr>
<tr><th>0</th><td>0</td><td>0</td><td>1</td><td>A</td><td>v000001</td></tr>
<tr><th>1</th><td>0</td><td>0</td><td>2</td><td>A</td><td>v000002</td></tr>
<tr><th>...</th><td>...</td><td>...</td><td>...</td><td>...</td><td>...</td></tr>
</table>

```py3:python
nn = len(data)
a = pd.DataFrame([(i,j,k,data[i][j]) for i in range(nn)
    for j in range(nn) for k in range(1,nn+1)], columns=list('行列数字'))
a['Var'] = addbinvars(len(a))
a[:2]
```


## 数理モデルを作り解く

変数表ができたので、因子の部屋の解になるように、制約条件を追加し数理モデルを作成し、解きましょう。

- 各マスに数字を1つ入れる。
    - `for _,v in a.groupby(('行','列'))`で1つのマスの変数がDataFrameの`v`に入るので、`m += lpSum(v.Var) == 1`とすれば、数字を1つ選ぶことになります。
- 各行で同じ数字は1つ。('行','数')にすれば、上記と同じです。
- 各列で同じ数字は1つ。('列','数')にすれば、上記と同じです。
- かけた数がヒントと同じ。掛け算は、`log`をとれば、足し算になります。計算誤差に注意し、等号ではなく、ある幅に入るように制約をかけます。

```py3:python
m = LpProblem()
for cl in [('行','列'),('行','数'),('列','数')]:
    for _,v in a.groupby(cl):
        m += lpSum(v.Var) == 1
for g,v in a.groupby('字'):
    e = lpDot([log(i) for i in v.数], v.Var) - log(nums[g])
    m += e >= -0.0001
    m += e <=  0.0001
m.solve()
```

### 結果の表示

```py3:python
a['Val'] = a.Var.apply(value)
print(a[a.Val>0.5].数.values.reshape(nn,nn))
>>>
[[2 3 5 1 4]
 [3 5 4 2 1]
 [5 2 1 4 3]
 [1 4 2 3 5]
 [4 1 3 5 2]]
```

解けていることが確認できます。

以上
はじめてのハッカソン体験記

本記事は[MashupAwards Advent Calendar 2017 7日目](MashupAwards Advent Calendar 2017)のための投稿記事です。
私たちのチームは、2017.10.25に行われた金沢ハッカソン予選の[カナザワオープンイノベーションハッカソン〜Hack for Workstyle！〜](http://mashupaward.jp/2017/10/hackathon-kanazawa2017/)にて、[上司萌化計画](https://hacklog.jp/works/51378)という作品を作りました。
![上司萌化計画アイコン.png](https://qiita-image-store.s3.amazonaws.com/0/63892/30445a82-0958-370a-7634-be538dfcc9b9.png)

今回はザンネンながら予選敗退でしたが、とても楽しかったです。
運営の松川さん、まなみん、伴野さんありがとうございました！！

参加する前の自分みたいにハッカソンて興味あるけどなんか敷居たかそうだしなーと思ってる人が、この体験記を読んでハッカソンの敷居が少しでも下がるといいなと思い、以下に`はじめてMAに参加（ハッカソン自体初めて！）した際にいろいろ感じたこと`をまとめていきます。

# ハッカソンに参加したキッカケ
いつもお世話になっている金沢市の山田さんに「人少ないので参加検討してもらえませんか？」とお願いされたのがキッカケでした。
前々からハッカソンに興味はあったので、見学しに行こうかなとは思っていたのですが、急に参加することになってドキドキでしたw
なので、２日間参加して楽しかったらいいなーぐらいに思ってましたし、ハッカソン自体はじめての参加だったので、Mashup Awardのことも名前聞いたことあるぐらいのレベルです。

# ２日間のハッカソンタイム
１人参加だったので、当日ははじめましての方５名でチームを作ることになりました。  
5名の内訳としては、学生2名、デザイナ1名、エンジニア2名だったのですが、学生さんもプログラムバリバリに書けて負けられないと思ったり、デザイナの方がささっとアイコン画像作ったりするところを隣で見れてスゴイと感じたり、会社の中にいるだけではあまり交流することがない方達と濃密な時間が過ごせてとても刺激的でした！！
それぞれの得意なこと、出来ることに焦点を当てて作業を分担し、作品を作っていくのが面白かったです！！
この時点でハッカソンにハマってきてる自分がいました。

# 成果発表
実際に作ったものを発表して、タッチ＆トライしてもらい、ダイレクトにフィードバックをもらえることがこんなにも楽しいとは思いませんでした。
おバカアプリ系だったので、デモやタッチ＆トライで結構ウケてとても嬉しかったのを覚えています。

![デモ画像.jpg](https://qiita-image-store.s3.amazonaws.com/0/63892/43706b96-eeae-ab43-1bc0-0d8f336c17d4.jpeg)
https://youtu.be/qhvOWLMfHrQ


これは見学だと絶対にわからなかった感覚だと思いますし、見学じゃなくて参加して本当に良かったと思いました！！
また、他の人の作品発表を聞いたり、タッチ＆トライするのも楽しかったです。
みなさん、２日間で相当疲れているはずなのに、達成感もありとても笑顔で楽しそうでした。


# 表彰
残念ながら、私たちのチームは最終的に何も賞をいただけませんでした。
デモでウケてたし、もしかしてってちょっと思ってたりもしてたので、やっぱり悔しかったですねー！

そんなこんなで、２日間のハッカソン終了とともにMAも終了のつもりでした（というか、MAのルールがむずかしくて、賞もらえなかったらオンライン予選の応募できないと思ってました。。。）。

# オンライン予選＆プレゼンバトル
終了のつもりだったのですが、雲の上の存在だった`まなみん`にFacebookのコメントで「応募待ってるよ」と言われ、これは応募するしかないと奮起！！
北陸予選ではなかったけど、`まなみん賞`あればウチのチームが貰えてたに違いないwと勝手に思い込み頑張りました！！

ただ、ハッカソンで終了だと思ってたので、ハッカソンのチームの方に連絡取れない＆自分が担当してない部分のプログラムがない。。。など、いろいろ問題勃発。。。
ないものを嘆いてもしょうがないので、担当してなかったプログラムは自分で作り直して、プレゼンバトルにも参加してきました！！
幸いプレゼン資料はチームの方で連絡取れた方がいい感じに直してくれたので、とても助かりました。

プレゼンバトル自体はデモが最初うまく動作しなくてテンパりまくったりと散々な結果でしたが、懇親会では福井のふくもく会の方たちとも仲良くなれたりして、参加してよかったです。

# またハッカソンに参加したいか？
とても面白かったので絶対に参加します！！（MAじゃないですけど、今週末のキッチンハッカソンにも参加してきます）
MAでも来年は何かしら賞をもらえるように頑張りたいです！！
そして、FESTAも見に行く予定なので、参加される方はよろしくお願いします！！

# 最後に「ハッカソンに興味あるけど躊躇している方」へ
実際に今回はじめて参加するまでは、ハッカソンに参加するような人たちはすごい人たちばかりで敷居高いと思ってました。

ただ、参加してみるとみなさんとても気さくで、ものづくりが好きな方ばかり。
そして、ものづくりが好きという共通項がすでにあるので、仲間意識のようなものもあり、みなさんとても優しく接してくれます。

今は、せっかくこのような素敵な場が用意されているのに、今まで参加してこなかったのは非常に勿体なかったなと感じています。

興味持たれている方は、ぜひ！！
はじめの一歩を踏み出して、参加してみてください！！

# 謝辞
山田さんに誘われていなかったら、今回のハッカソンは見学どまりだったと思います。
まなみんにコメント貰わなかったら、オンライン予選＆プレゼンバトルへの応募もしなかったし、ふくもく会の方たちと知り合うこともなかったかもしれません。

お二人に声をかけていただいたおかげでハッカソンという楽しいイベントや、いろいろな人と巡り会うことができました。
山田さん、まなみん、本当にありがとうございました！！
遠隔制御の功罪とRiot

アドベントカレンダーの期間ということで、今までもやっと思っていたことも文章にしてしまおうかと思います。

# ここで考える「遠隔制御」
「遠隔制御」といっても、IoTの機器制御とかウイルスでリモートマシンを乗っ取るとか、そういう話をするつもりではありません。ここでいう「遠隔制御」というのは、例えば

* HTMLの要素へクラスをかけて、それに対してCSSを適用する
* ある特定の`data-xxx`属性を付けたHTML要素について、自動的に特定のJavaScriptを動かす
* ページ内に適当にRiotのタグを書いて、まとめて`riot.mount('*')`でマウントする

のように、「書いた箇所と別の箇所で何かを制御すること」というような話を意図しています。

# 遠隔制御の利点

直接書くような方法がある状況で、遠隔制御をするメリットは、「再利用性を上げられる」ことです。CSSを例にしてみると、ページに直書きしてしまうと他のページに再利用するのは困難となりますが、CSSだけ別に切り出しておけば、他の文書にもそのまま適用できます。文書の方も、CSSだけの差し替えでスタイルを変えることができます。

また、うまく作れば元のサイトにほぼ手を入れる必要もなく新たな機能を加えられます。`rails-ujs`は、unobstructiveという名前のとおり、ページを書き換えることなく、Railsに必要な機能性を追加していきます。

# 遠隔制御の欠点

遠隔制御をとることでの欠点は、（きっちり仕組みやルールを作らない限り）どこで何を使っているのかカオス化しやすい、ということです。CSS設計がいろいろと提唱されていますが、裏を返せば、機能の多くないCSSでは、設計などのルールで押さえ込まない限り、効く場所を制御するのも困難になってしまう、ということの現れとも言えます。

JavaScriptでも、`data-`属性などで自動適用するようなライブラリがありますが、細かい制御ができず使うのが逆に難しくなるような場面も見受けられたりします。

# Riotの場合

Riot.jsをこのような観点で見てみると、「タグの埋め込み」については「標準的に現れないタグ」という比較的わかりやすいマーカーを使っているので、そこまで問題にならない印象もあります。また、「タグ内部の挙動」については、（もとから外側のCSS/JSの影響がある場合を除けば）CSSはタグ内オンリーで適用できますし、JavaScriptも遠隔でなく直接`onclick`などで書く形となるので、遠隔制御とならずに済みます。そのようにして、使いやすいものとなっている、と感じました。
Herokuで複数Dynoにするとsocket.ioが繋がらなくなる問題への対処いろいろ


最近HerokuでSocket.io依存のサービスを運用する機会があったので手順だけメモ。
（日本語記事あまり見つからないので、もしかしたら `socket.io-redis`がこの問題をも解決してくれているのかな...クラスタリングするんでしょ？って忖度してくれるような）

## 症状

Heroku上でクラスタリングしたsocket.io(node.js)との接続が確立できない。
エラーメッセージは下記2種類。ポーリングで接続成功した後に、websocketにupgradeしようとして失敗しているような感じ。最初に接続確立したときと違うサーバにつなぎに行こうとして怒られてしまっているみたい。

```
Failed to load resource: the server responded with a status of 400 (Bad Request)
WebSocket connection to ......... failed: WebSocket is closed before the connection is established.
```

## 手順

1. heroku側で`http-session-affinity` をONにする
2. `socket.io`のfallback optionを`websocket`優先にする

現時点ではChromeやFirefoxであれば1の対処だけでOK。
Mac/iOS Safariやnode.jsのsocket.io-clientなどの場合は2の対処までしてやる必要があります。

### HerokuのHttp Session AffinityをONにする

詳しくは [コチラ](https://devcenter.heroku.com/articles/session-affinity)


```bash
heroku features:enable http-session-affinity
```

この問題を調べると`siticky session`を使え！って出てくるのだけど、 `heroku`は`sticky session`使えないよ！というスタックオーバーフローのページが沢山出てくる。公式的には`session-affinity`って機能で似たような事を提供しているそうですが、それよりも前の記事も結構見かけるので、やはり記事の書かれた時期って大事ですね。

### client側のsocket.ioのfallback optionをwebsocket優先にする

デフォルトでは`pollling` 、`websocket` の順番で接続をしていくsocket.ioですが、クラスタリングされたサーバに接続する場合は順番を指定して、`websocket`から繋ぐようにする。

```js

const options = { 
  transports: ['websocket', 'polling' ]
};

const socket = io.connect( "URL" ,options);

```

## 付録

socket系 x クラスタリングで発生する問題としては、セッションが各nodeで共有されないことくらいで、broadcastのときに困るくらいだろうとタカをくくっていました。Broadcastの問題に関しては別のソリューションで解決していたので、今回はたまたま`socket.io-redis`を使っていませんでした。もしかしたらこの問題自体、`socket.io-redis`が一緒に解決しちゃってくれる可能性もあります。

ちなみにsocket.io、以前はwebsocketから順番にfallbackしていっていたのを、どこかのバージョンで逆にするようにしています。そのほうがwebsocket非対応のオールドブラウザでの接続確立までの時間が短くなるという理由らしいです。
Python リストの逆順

# Python リストの逆順
Pythonのリストを逆に出力するのって・・・　あれどうやるんだっけ？

そんなビギナーな私は

- 「Python リスト　逆」
- 「Python リスト 反転」

などを毎回検索してしまう。

ここの記事にたどり着いたということは皆さんも同じなのだろう・・・
※そうでない人にはすみません

そこで一応方法を書いておきます
※python3で書いています

##　reversedメソッドの使用
```
l = [0, 1, 2, 3, 4]

for i in (reversed(l)):
    print(i)
```

##　スライスで逆順にする
```
l = [0, 1, 2, 3, 4]

for i in l[::-1]:
    print(i)
```
# その他
他にもないかと、stackoverflow を確認していたら、こんなのが書かれていた。

```
l = [0, 1, 2, 3, 4]

for i in range(len(l) // 2):
        l[i],l[-1-i] = l[-1-i],l[i]
```

- 参考資料：[How can I reverse a list in python?](https://stackoverflow.com/questions/3940128/how-can-i-reverse-a-list-in-python)

アルゴリズムセンスがない私には、見た瞬間さっぱり分からなかったがみなさんはもうお分かりだろう。

私は風呂に入った時に分かったのだが・・・・・

このままのソースだと分かりにくいので、以下のように修正してみた。
【修正したコード】

```
l = [0, 1, 2, 3, 4]

for i in range(len(l) // 2):
        print("Before,i:{0},l[i]:{1},l[-1-i]:{2}".format(i, l[i], l[-1-i]))
        l[i],l[-1-i] = l[-1-i],l[i]
        print("After,i:{0},l[i]:{1},l[-1-i]:{2}".format(i, l[i], l[-1 - i]))
        print("\r")

print(l)
```

【結果】

```
Before,i:0,l[i]:0,l[-1-i]:4
After,i:0,l[i]:4,l[-1-i]:0

Before,i:1,l[i]:1,l[-1-i]:3
After,i:1,l[i]:3,l[-1-i]:1

[4, 3, 2, 1, 0]
```

イメージしやすくすると、以下のような感じです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/159184/0bfbfb8f-ef09-ba40-ce6d-f77bdd99b2f4.png)

こんな遊び心のある回答、いつかはしてみたいなと。
大切ですね。

### 参考資料
- [リストの逆順 reverse / reversed](http://www.python-izm.com/contents/application/reverse.shtml)
仮想環境で稼働しているArch linuxでnginxを使ってみた

#仮想環境で稼働しているArch linuxでnginxを使ってみた

##概要
sambaに続いて第２回目。
今回、サーバの勉強の一環として仮想環境で稼働しているArch linuxにnginxを入れて動かしてみました。

その時の行動についてまとめたいと思います。

##環境
Windows8
VirtualBox 5.2.0
Arch Linux 4.13.11-1
nginx 1.12.2

##詳細

###VirtualBox側の設定
nginxをインストールする前に、仮想環境の設定を少しだけ変更します。

####ポートフォワーディングの設定
VirtualBoxを起動させて、メニュー画面から設定を選びます。

![設定選択.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/5808e934-8c37-2953-1b39-691e2149b597.jpeg)

設定を選んだら以下の画像のように**高度(D)**と書かれた文字をクリックしましょう。
以下のように、ポートフォワーディングと書かれたボタンが出現します。
![ki-ta.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/918e8227-6c7d-24d4-c2c6-a9396e368e83.jpeg)

ポートフォワーディングボタンを押して以下のように80番ポートを設定します。

![ki-ta4.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/145e89d3-fe05-a596-9a43-74e307e50122.jpeg)



ちなみに443番のポートの設定は後にオレオレ証明書作ってhttps通信にした為です。


これでVirtualBox側の設定は終わりです。


###nginxを使ってみる

####nginxのインストール
まずは、公式のリポジトリからsambaをインストールしましょう。

```bash:コマンド
pacman -S nginx
```

nginxを動かすには、下記のコマンドを実行します。

```:コマンド
 systemctl start nginx
```

起動した際に自動で動かしたい場合にはenableに設定しておきます。

```:コマンド
 systemctl enable nginx
```
enableになっているかどうかは以下のコマンドで確認できます。

```:コマンド
systemctl list-unit-files | grep nginx
```

これで、基本設定は終わりです。


###ブラウザからアクセスしてみる
nginxを起動したのでブラウザからアクセスしてみます。
Windows側のブラウザでlocalhostとたたきましょう。

下記の画面が出現すると成功です。

![ki-ta5.JPG](https://qiita-image-store.s3.amazonaws.com/0/195114/d7812f44-f1e3-e2d2-38b8-1cfd45a585e5.jpeg)


sambaよりは、簡単に動かせることができました。

###おまけ
VirtualBox側の設定の時に出てきたhttps通信ですが、私もやってみたい！
という方は、下記の記事がとてもシンプルで分かりやすかったのでお勧めです。
https://qiita.com/nenokido2000/items/1d1c79a0a443ed923e92


以上です。
数百円で出来るメールサーバのバックアップ

今日はレンタルサーバを活用しエンジニアじゃない人でも数百円でお手軽にバックアップメールサーバを構築する方法をまとめました！

一般的なレンタルサーバでは、WEBサーバーと共にMTAやMDA、MRA（POP、IMAP）などの仕組みがパッケージ化され、運用を完全にレンタルサーバ会社にお任せできるメリットがありますが、一方でカスタマイズの余地が少なく可用性や完全性を強化したいと思っても自由度が無いというデメリットもあります。

もちろん、レンタルサーバ各社それぞれにサービスを止めない努力や工夫をされていると思いますが、ちょっとした工夫でユーザ側でも出来る防衛策を紹介したいと思います。

#１，解決できること

- メインのメールサーバが落ちている時でも代わりにメールを受信できます。 
- 受信したメールの中に急ぎのものが無いか確認する事ができます。 
- メインのメールサーバが復旧したらバックアップ側から自動的に再送されます。

#２，用意するもの

- バーチャルドメインとメール転送が使えるレンタルサーバを2台
- AレコードやMXレコードの設定が自由にできるDNSサーバ

#３，構成のイメージ

![image1.PNG](https://qiita-image-store.s3.amazonaws.com/0/82655/c3b8bacb-f598-0626-9f0c-aa0e35e0c1a1.png)

#４，設定方法

![image2.PNG](https://qiita-image-store.s3.amazonaws.com/0/82655/743bf425-ca12-fa87-936d-7823a0a2251d.png)

#５，最後に
最近のレンタルサーバではバーチャルドメインが標準的になっているので、DNSと上手く組み合わせて使う事でメールに限らず、簡易的な冗長化が組みやすくなっています。高機能になったレンタルサーバを上手く使って運用費用を抑えつつユーザ側でも出来る対策を検討頂ければ幸いです。
SendGridで何か問題があったときに見ておくべき管理画面まとめ


SendGrid は控えめに言っても最高なんですが、使い始めはどこで何を確認したらいいか分からないことがあります。
そんな時のために管理画面の見方をまとめてみました。

## 現在のステータス
https://app.sendgrid.com/statistics

メール送信/受信の状況を把握するためにも、まずは現在のステータスがまとまっているページを確認することが大事です。
普段の平均値と乖離している項目があればそれに注視していきましょう。

ちなみに SendGrid は毎日メールで前日のステータスを通知してくれるので、それさえチェックしていればよかったりします。

## Bounces
https://app.sendgrid.com/suppressions/bounces

メールの配送が失敗した場合、SendGrid では Bounce としてカウントされます。
代表的な配送の失敗は、例えばメールアドレスが存在しないなどですね。

## Blocks
https://app.sendgrid.com/suppressions/blocks

配送はできたが、送信元IPアドレスがブラックリストやブロックリストに登録されていた場合、SendGrid では Block としてカウントされます。
以前、自動送信メールの BCC に特定のメールアドレスをつけるようにしていて、それが Gmail 側でブロック（Blocks）されたことがあったのですが、それもこの画面で気づけました。

## Bounce Drops
https://app.sendgrid.com/email_activity?events=drops

配送時に Block が続くと、SendGrid 側で配送不可とみなしてメール自体を破棄することがあります。その場合 SendGrid では Bounce Drop としてカウントします。

## Inbound Parse
https://app.sendgrid.com/settings/parse

特定のドメインの MX レコードに SendGrid が設定されており、そのドメイン宛にメールが送信された場合、Inbound Parse で設定された URL に RAW を含んだメールデータを転送することができます。
で、何らかの原因でそれが送信できなくなったり SPAM メールが大量に送られてきたりしていると、上記設定画面にてアラートが表示されます。

## まとめ
ステータス中に何かスパイクがあったときは上記のURLを参考に障害の原因を切り分けていきましょう。
また、SendGrid の正規代理店である[構造計画研究所](https://sendgrid.kke.co.jp/)さんのサポートはとても丁寧なので、困ったことがあればそれを利用するのも手ですね。
クレジットカードを使わないでlinebotを作ったときの話

7日目担当の @esu_eichi です。
6日目は @tsubasaogawa さんの「[pushd と dirs を peco でちょっと便利に使う](https://qiita.com/tsubasaogawa/items/f1c9de7062bf3ee165a8)」でした


#書く内容
このページにはタイトル通り、クレジットカードはないけどlinebotが作りたい、という数少ないであろう人々向けに
クレジットカードなしで登録/利用できたサービスなどをまとめておきます。

##書かない内容
linebotの作り方やapiのtips、ハマリポイントなどは書きません。
クレジットカード登録なしで使った技術の話をまとめておくだけです。


#経緯
先日学生向けインターンシップを担当しました。
学生でもとっつきやすい課題ということで[Line Messaging Api](https://developers.line.me/ja/services/messaging-api/)とlaravelで
簡単なリマインダを作るというハンズオンを行いました。
今回はその準備のときの話です。


##課題
学生向けということで、無料かつクレジットカードが無くても登録できるサービスを使う必要があると気づきました。
サーバーに関して、色々探しましたがクレジットカードを使わないと無料分すら利用できないものが多かったため
実際に利用したサービスなどをまとめておきます。

#利用したもの
##Laravel
[Laravel](http://laravel.jp/) は最近日本でも流行ってきたPHPのフレームワークです。
今回サーバー上で動かすプログラムはこれで作ります。利用は完全無料です。

##Line Messaging Api
今回の主役です。少なくとも開発アカウントとして使う分には
こちらも特にクレジットカード登録は不要で使えます。
仕様上、botのプログラムを置くサーバーは *https対応されている必要* があります。

##github
ハンズオンで使うスケルトンのプログラムは[github](https://github.com/)にあげておきました。
学生たちにはここから今回のプログラムを落としてきてもらってサーバーに上げてもらいました。
privateリポジトリを作らない限りは無料のはずです。

##git
[git](https://git-scm.com/)も説明するまでもありませんが、github からスケルトンを入手し、サーバーにアップするときに使いました。こちらも無料で使えます。

##heroku
サーバーの選定が一番大変でした。
awsやazure、GAEなど、無料で結構高スペックなサーバーを一時的に使わせてもらえるサービスもたくさんあったのですが、
**どれも利用登録段階でクレジットカード登録が必須です**。
今回HTTPS対応されており、かつクレジットカード登録が不要ということでherokuを選定しました。
**が、此処から先がけっこう大変でした**。

### heroku とクレジットカード登録
herokuは登録と無料分の利用こそクレジットカード登録が不要ですが、
Paasであるherokuでは各種ミドルウェアがプラグイン形式で提供されており
それらを利用するには一部を除き **クレジットカード登録が要求されます。**
#### heroku postgres
今回リマインダを作るので、リマインドの内容を保持するDBが必要です。
mysql を使うにはクレジットカード登録が要求されるようです。
自分はmysql派なので思わず「全部テキストで管理してやるわ！！」と思い、
実際に半日くらいマジでテキストで管理するよう設計と開発をしましたが面倒すぎて断念。
調査の結果 **postgresはクレジットカード登録が不要** でした。なぜだ......
#### google app script
「リマインドを送る」という以上、ある時間になったらメッセージを送ってほしいですよね。
本来であればDBに保持されたリマインドの内容をcronなどで定期的に確認し、リマインドを実行するという作りにすると思います。
**しかしheroku上でのcronはクレジットカード登録が必要です。**
完全に詰んだと思い、「学生もクレジットカードくらい持っているのでは」という甘えが強くよぎりましたが、
Google app script　を利用することで解決しました。

以下スクリプトを記載します

```remind_webhook
function myFunction() {

   var options =
   {
     "method" : "post",
     
   };

   UrlFetchApp.fetch("your-own-heroku-app-url:443/api/linebot/remind", options);
}

```
このスクリプトはただ指定したURLへwebhookを飛ばすだけです。
これを定時実行し、プログラム上でwebhookによるリマインドを実装し解決しました。


#まとめ
書いてみると簡単な内容になりましたが、実際意外とこの縛りで遠回りは多かったです。
ただ、linbot自体は結構簡単に作ることができました。
また、herokuも実は触ったことなかったのですが、癖は感じるものの、
慣れてくると結構便利で、ちょっとしたAPIを動かすくらいなら全然ありです。

ただ、クレジットカードを登録できたほうが10倍は楽なので、
エンジニア、エンジニア志望の学生はクレジットカード一枚くらい持っていたほうがいいです。

以上です。
PostgreSQLのデータベース容量をチェックする方法


データベースの容量をチェックするのはどうすれば良いか調べた結果、SQL自体は簡単そうだ。
ページ数 * ブロックサイズ = ディスク使用量になる？

```sql
psql (9.6.2)
Type "help" for help.

=# select sum(relpages) * 8192 as db_size FROM pg_class;
 db_size
----------
 87310336
(1 row)
```

## ページ数？
> RDBMSがディスク領域を管理する際に基本となる単位

> ページには，テーブルを構成するレコードや，インデックスのエントリ＊4を複数格納します。RDBMSはメモリーとディスクの間の入出力をページ単位で管理し，キャッシュ・バッファ＊5への入出力もページごとに行います。

DBにあるデータの領域が、このペース数になるのかな。

## ブロック数？
> データベースで使用されるデータの最小単位です。これとは対照的に、物理的なオペレーティング・システム・レベルでは、すべてのデータはバイト単位で格納されます。各オペレーティング・システムには、ブロック・サイズがあります。

```
=# show block_size;
 block_size
------------
 8192
(1 row)
```

## テーブルの使用量チェック
```
=# select sum(relpages) * 8192 as db_size FROM pg_class where relname='table_name'

 db_size
---------
   24576
(1 row)
```



## 参考にさせていただいたサイト
http://d.hatena.ne.jp/kurita1/20130323/1364030340
http://itpro.nikkeibp.co.jp/article/COLUMN/20060113/227231/?rt=nocnt
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19215-02/logical.htm#51854

うーん、よくわからなかった...
[PowerPoint VBA]コンマを全消しするマクロ(Replaceの使用例)

# PowerPointとPublisherは似ているが...
[[PowerPoint VBA] コンマを全消しするマクロ (Replaceの使用例)](https://qiita.com/Q11Q/items/52f33d856a02cb71ed1c)を作ってみたのでこれをPowerPointで実行するマクロです。

```vbnet
Sub ppDeleteCommas()
'For PowerPoint VBA
Dim ppP As PowerPoint.Presentation
Dim sh As PowerPoint.Shape, shs As PowerPoint.Shapes
Dim sld As PowerPoint.Slide, slds As PowerPoint.Slides
Dim tFrame As PowerPoint.TextFrame, tRng As PowerPoint.TextRange
Dim FoundRng As TextRange
Set ppP = ActivePresentation
Set slds = ppP.Slides
For Each sld In slds
Set shs = sld.Shapes
For Each sh In shs
If sh.HasTextFrame Then
Set tFrame = sh.TextFrame
Set tRng = tFrame.TextRange
Do
Set FoundRng = tRng.Find(FindWhat:=",", After:=1)
If Not FoundRng Is Nothing Then
tRng.Replace FindWhat:=",", ReplaceWhat:="", MatchCase:=msoFalse, wholewords:=msoFalse
Else
Exit Do
End If
Loop
End If
Next
Next
End Sub
```

#Publisherとの相違点
 - DocumentではなくPresentationになる（当たり前ですね）
 - Pageではなくスライドになる（これも当然でしょう）
 - そこからShape-Textrangeへもっていく方法はよく似ている。
 - 置換は1行でかける。
 - あいまい検索が使える。
 - この書き方はPowerPointの置換のたぶん基本
009 == 011 -> true, '009' == 011 -> true, JavaScriptの8進数にまつわる不思議な話

```
$ node
> 009 == 011
true
```
__なんだだこれは？__

## JavaScriptの8進数

JavaScriptのnum型の最初に0がついていると、8進数として扱われます。

というわけで、

```
> 011
9
```

こうなります。ここまでは普通。

問題は009の挙動で、どうやらJSは8進数に9が混ざると10進数として扱い、頭の0を無視するらしい。
そういうわけで、009==011 -> true なかなか不思議な挙動ですね。

ちなみに、どちらも数値型なので、

```
> 009 === 011
true
```
当然こちらもtrue。

## '009' == 011, 009 == '011'

```
> '009' == 011
true
> 009 == '011'
false
```
こんな挙動になります。

一瞬迷いますが、parseIntを使うと簡単に説明できます。

```
> parseInt('009')
9
> parseInt('011')
11
```

どうも自動でparseするときには基数10でparseされ、前方についている0は無視されるようです。

## parseIntは基数を指定できるけど……

```
> parseInt('011', 8)
9
```

当然　'011'をparseすると10進数では　9になります。

ただ……

```
> parseInt('009', 8)
0
```

エラーはないらしい

## まとめ

　JavaScriptは独特の挙動はするものの、一定のルールには基づいているっぽいよ。
[Publisher VBA] コンマを全消しするマクロ (Replaceの使用例)

[Publisher VBA 全世界初数字をコンマ付き数字に変えるマクロ](https://qiita.com/Q11Q/items/8678d24fd1549d16fc67)ができたので、こんどはコンマを全消しするマクロを作りました。
これは全消しだけでなく、変換もできます。


```vbnet

Sub pbDeleteCommas()
'For Publisher VBA
Dim pbDoc As Publisher.Document
Dim sh As Publisher.Shape, shs As Publisher.Shapes
Dim pbPage As Publisher.Page, pbPages As Publisher.Pages
Dim tFrame As Publisher.TextFrame, tRng As Publisher.TextRange
Dim FoundRng As TextRange
Set pbDoc = ActiveDocument 'アクティブドキュメントをセット
Set pbPages = pbDoc.Pages 'ページのコレクションをセット
For Each pbPage In pbPages 'ページごとに処理をする
Set shs = pbPage.Shapes 'ページのシェイプコレクションをセット
For Each sh In shs 'シェイプごとに処理をする
If sh.HasTextFrame Then 'シェイプがテキストフレームを持っているか、シェイプがテキストボックスだったら
Set tFrame = sh.TextFrame 'テキストフレームをセット
Set tRng = tFrame.TextRange 'テキストレンジをセット
With tRng.Find 'With tRng.Find の書き方がポイント
.Clear
.FindText = "," '検索文字
.ReplaceWithText = "" '置換文字
.ReplaceScope = pbReplaceScopeAll
.Forward = True
.Execute 'Clear と Executeで必ず挟む
End With
End If
Next
Next
End Sub
```

# ポイント

 - PublisherのReplaceだけを使用しているので、汎用性が高い
 - 全消しになる理由はReplaceScopeの変数
 - Forwardは順方向にするか逆方向にするか
 - ワイルドカード、正規表現は使えない
 - テキストレンジが全文になっているため一部だけ適用したいときはテキストレンジをさらに行単位、単語単位、文字単位で絞り込んだテキストレンジを作ってテキストレンジファインドに持ち込む。
 - すべてのページのすべてのシェイプのすべてのテキストボックスにアクセスするのはこちらが確実かも。
ファクトリーを使ってインピーダンスミスマッチを解消し、ポリモーフィズムを実現する

Nuco Advent Calendar 6日目の記事です。

#はじめに
タイトルを読んでイメージが出来る方にはあまり面白みがないかもしれないです。。

#インピーダンスミスマッチ？
分からない♪（ぱんぱん）、分からない♪（ぱんぱん）、分からないなら帰ってウィキペディア！！

ということでウィキペディアから拝借
>オブジェクト指向プログラミングとリレーショナルデータベースは異なるデータモデルを持つ。
リレーショナルデータベースの関係モデルは整合性を重視した２次元表の構造を持っており、データ同士は関係（リレーション）によって表現される。
一方オブジェクト指向プログラミングのデータはひとまとまりのオブジェクトとして扱われ、関係モデルにおける関係と同じような構造を持つとすれば、オブジェクト指向としての恩恵が得られるモデル設計ができない。
逆も然り、オブジェクトモデルをリレーショナルデータベースで実現しようとすると、整合性が損なわれたり、関係が表現できなくなる。
このデータ構造や概念の隔たりがインピーダンスミスマッチと呼ばれる。


#ポリモーフィズム？
分からない♪（ぱんぱん）、分か
>プログラミング言語の型システムの性質を表すもので、プログラミング言語の各要素（定数、変数、式、オブジェクト、関数、メソッドなど）についてそれらが複数の型に属することを許すという性質を指す。
ポリモルフィズム、多態性、多相性、多様性とも呼ばれる。

いや、ちょっと何言ってるかよく分からな・・・

ポイントは、
**共通のメソッドを呼んだ際に、オブジェクトによってその機能を変えられる**
ことじゃないでしょうか。

#例：複数の権限があるECサービスの場合
ECサイトのユーザー権限として以下の４つがあったとします。

 - **タイプ１**：閲覧のみ可能
 - **タイプ２**：閲覧、販売、購入が可能
 - **タイプ３**：閲覧、販売が可能
 - **タイプ４**：閲覧、購入が可能


### ポリモーフィズムを使わない場合
ユーザーの権限をセッション等で管理していた場合、以下のようになるのではないでしょうか。
![NG.png](https://qiita-image-store.s3.amazonaws.com/0/186503/88ac74b9-5029-0111-d876-0945464bd009.png)

この場合、権限が増える度にcase文を増やすことになります。
また、他の処理でもif-elseやswitchが乱立することになり、色々面倒です。

### ポリモーフィズムを適用した場合
![OK.png](https://qiita-image-store.s3.amazonaws.com/0/186503/2e55aeff-7835-9ebb-d775-414d4170619a.png)

この場合、アカウントの権限が増えてもメソッドの処理を変更する必要がありません。

#どうなってるの？
ソースコードは[こちら](https://github.com/ishigero/polymorphism/tree/master/controllers)

※ControllerとModelしか置いてないですが、Repository以外はPOPOで書いてます
※フレームワークはcodeigniterです

想定してるDBはこんな感じです

| user_id       |       type|    name    |    password    |
|:-----------------|------------------:|:------------------:|:------------------:|
| 001             |              1 |        田中        |       #hs465_dd         |
| 002             |              2 |        山田        |       fff5_lkj         |
| 003             |              3 |        内山        |       gs323_jlg        |
| 004             |              4 |        佐藤        |       eeeelkj         |

そして、typeごとに以下のようなクラスを作ります。
（今回はAccount1～Account4まで作りました）

![OK2.png](https://qiita-image-store.s3.amazonaws.com/0/186503/1ce5e137-f6b6-bf46-fcea-ac2cf12b3c1c.png)

![OK2.png](https://qiita-image-store.s3.amazonaws.com/0/186503/793f8339-b924-e415-aa8a-2fa377534993.png)

12行目の`$user`には、`$userId`に対応する権限のオブジェクトが入ります。

### 田中さんの場合

AccountRepositoryのfindメソッドが呼ばれます。
![OK3.png](https://qiita-image-store.s3.amazonaws.com/0/186503/ff857c82-6554-3aee-a9e5-3a7192f15d1d.png)

user_idが001と一致するため、AccountFactoryのcreateメソッドが呼ばれます。
![OK4.png](https://qiita-image-store.s3.amazonaws.com/0/186503/b203d2b7-914f-6ca6-b723-c4603301d000.png)

typeが1なので、`$user`には Account1オブジェクトが入ります。

タイプ１の権限の場合、閲覧のみなので、Account1オブジェクトを参照する`$user`がbuyメソッドを呼び出すとNotAuthorizedExceptionが呼ばれます。

buyメソッドの中身は書いてないですが、タイプ２の山田さんの場合は例外処理にならず、「何か買う」が表示されます。

#まとめ

**共通のメソッドを呼んだ際に、オブジェクトによってその機能を変えられる**
本記事とソースコードが、ポリモーフィズムを理解する手助けになれば幸いです。
SwiftのフレームワークでBundleを取得する方法

#とりあえずおさらい

Cocoa Touch Frameworkで初めて開発した時にハマるあるあるなのですが、UIImageを取得する際には、

```swift
public init?(named name: String)
```

ではなく、

```swift
@available(iOS 8.0, *)
public init?(named name: String, in bundle: Bundle?, compatibleWith traitCollection: UITraitCollection?)
```

を使用しなければなりません。

前者の方はメインのBundleからUIImageを取得するメソッドなので、メインであるアプリ側のBundleからUIImageを取得しようとしてしまいます。
メインのBundleがフレームワークのBundleではないので、フレームワーク側で前者を使用した場合、正しい画像取得ができなくなってしまうためです。

画像だけでなく、xibなどのリソースファイルをフレームワークのプロジェクト上で取得する際には、後者のような通常のアプリのプロジェクトで使用しているメソッドにさらにBundleを引数で指定するメソッドで取得しなければいけなかったりするので注意が必要です。

#classでバンドルを取得する場合

フレームワーク上では、フレームワークのBundleを取得しなければならないことがわかったので、その取得方法について見ていきましょう。
classで取得する場合は以下のメソッドを利用します。

```swift:Bundle
public init(for aClass: Swift.AnyClass)
```

このメソッドを使用して以下の処理を実行すれば、classが所属するBundleを取得することが可能です。

```swift:FrameworkClassSample.swift
let bundle = Bundle(for: type(of: self))
```

#enum・structの場合

Swiftでenumやstructの機能がかなり強化されたので、フレームワークでも使いたいパターンもあります。
その際もenumの値によって画像なんかをBundleから取得したいとかってよくあると思います。

そんな時、先ほどのclassで使用した方法は、あくまで、classが所属するBundleを取得するのでコンパイルエラーを起こしてしまいます。

そういう場合は、下記のように仮のクラスを作成して、そこからBundleを取得するのがいいのではないかと思います。

```swift:enum
enum hoge {
    
    case fuga
    case piyo
    
    var image: UIImage? {
    	//仮のクラスを作ってそこからBundle取得する
        class DummyClass {}
        let bundle = Bundle(for: type(of: DummyClass()))
        
        switch self {
        case .fuga:
            return UIImage(named: "fugaImage", in: bundle, compatibleWith: nil)
        case .piyo:
            return UIImage(named: "piyoImage", in: bundle, compatibleWith: nil)
        }
    }
}
```

```swift:struct
public struct SampleStruct {
    var image: UIImage? {
    	//仮のクラスを作ってそこからBundle取得する
        class DummyClass {}
        let bundle = Bundle(for: type(of: DummyClass()))
        return UIImage(named: "structImage", in: bundle, compatibleWith: nil)
    }
}
```

#extension作ったよ
さすがに毎回仮のクラスを作るのは面倒なのでextension作ったよ。

```swift:Bundle+current.swift
extension Bundle {
    static var current: Bundle {
        class DummyClass{}
        return Bundle(for: type(of: DummyClass()))
    }
}
```

```swift:呼び出す時
let bundle = Bundle.current
```
fluentdでログをS3に送るとき, ホスト名をパスに含める

# はじめに

こんにちは。
fluentdでログをS3に送るとき、ホスト名をパスに含みたいことがあったので、そのときのメモです。

例えば `foo.baz.com` からのログであれば、 S3の `your-bucket/foo.baz.com/your-file` に、`bar.baz.com` からのログであれば、 `your-bucket/bar.baz.com/your-file` などのパスに保存できます。

# やり方

[fluent-plugin-record-reformer](https://github.com/sonots/fluent-plugin-record-reformer
)というプラグインを使います。このプラグインは、レコード中のフィールドを書き換えるもので、以下のようにホスト名をタグに付け、タグをプレフィックスに指定します。

```
# ホスト名をタグに付ける
<match your.tag>
  type record_reformer
  renew_record false
  enable_ruby true
  tag ${tag_parts[1]}.${tag_parts[2]}.${record['Host']}
</match>
 
# ログをS3に送る
<match your.tag.*>
  type forest
  subtype s3
  remove_prefix your
  remove_prefix tag
  <template>
    aws_key_id your-key
    aws_sec_key your-sec-key
    s3_bucket your-bucket
    s3_region your-region
    path your-bucket/${tag}/
    buffer_path /var/log/td-agent/buffer/${tag}
    time_slice_format your-format
    flush_interval 60m
    buffer_chunk_limit 512m
  </template>
</match>
```

# かんたんに解説

- `${tag_parts}` ： 入力されたタグが入っています
- `${record}` ： レコード内のデータが入っています。 `${record['Host']}` とするとホスト名が取れます
- `enable_ruby` ： trueにすると簡単なRuby式が書けます
- ↑のような方法でホスト名をタグに付与し、S3に送るときに `${tag}` でタグをパスに指定します

# 使用例

サブドメインを使っているシステムでは、サブドメインごとにログを保存するパスを変えたいこともあるかと思います。そのときはタグを付与する部分を以下のように変えます。

```
# ホスト名をタグに付ける
<match your.tag>
  type record_reformer
  renew_record false
  enable_ruby true
  tag ${tag_parts[1]}.${tag_parts[2]}.${record['Host'] ? record['Host'].split(".")[0] : '-'}
</match>
```
とかんたんなRuby式を書くことで、サブドメイン部分のみ取り出して、タグに含めることができます。そして `your-bucket/foo/your-file` や `your-bucket/bar/your-file` のようなパスに保存できます。

# まとめ

他にも似たようなプラグインはありましたが、今回はこれが一番使いやすかったです。他にも方法はありそうですが、参考までに〜〜

# 参考

http://y-ken.hatenablog.com/entry/fluentd-how-to-use-tag_parts-placeholder
続・LumberyardのShaderを覗いてみた

# 前回に続いてLumberyardのShaderを覗いてみます。

前回の記事
https://qiita.com/dgtanaka/items/7901b1b9283eaf148da0

気になるファイル名のシェーダーを適当にチョイスして覗いてみます。

* PostAA.cfx 
　名前の通り、ポストプロセスにるアンチエイリアスのコードですね。
TAA,SMAA,FXAAの３種類のシェーダーが記述されていますが、SMAAはDEPRECATEDと書かれているので、使われていないようです。
　標準はTAAで、FXAAも使用可能なのはUE4と同じですね。Shaderの中でApplyFilmGrainという関数があって、AntiAliasの後にFilm Grainを足しています。Film Grainはフィルム撮影独特の粒子状のノイズですね。

* PostEffectsGame.cfx
　こちらはゲーム向けのポストエフェクト、水滴、雨、雪、閃光など。KillCameraFilterなんてのも実装されています。これは周辺減光とノイズと色変換ぽいですね。

* CommonSVO.cfi
　Sparse voxel octree global illumination、Lumberyardの目玉、ボクセルベースのリアルタイムGIの実装。UE4が割りと早い段階で諦めたやつですねｗ
　どの程度使い物になるのか興味あるので、時間ができたらじっくり触ってみたい。

* DeferredShading.cfx
　Deferred Shadingの処理がぎゅっと詰まっています。
　Deferred DecalとかSSR(Screen Space Reflections)とかSSDO(Screen Space Directional Occlution)とかいろいろ入ってます。
　Deferred DecalのMip LevelをgetDecalMipLevelsという関数で補正してるところとか個人的に見どころ。

## まとめ
　こんな短いのにまとめも無いですが、時間がなくてちょっとしか書けませんでした。
　こんなんでもアドカレが途切れるよりは良いかなと思ったので、恥ずかしながら投稿させていただきました。
　シェーダーコード見てるだけで時間は過ぎていくのですが、記事としてまとめられる事って思ったほど無いものです。
ホクソエムを見るとき、君もまたホクソエムに覗かれているのだ

# これはなに
R言語界隈に彗星のごとく現れ、数々の逸話を残しながら未だに実態がつかめないホクソエム。
かつては匿名知的集団という肩書きの抽象的な集団であったが、気づけば法人化までされており、最近ではR言語関連の本を監修していたりと、着実にその実績を積み上げつつある集団である。
私も草創期から、この集団とはつかず離れずの関係性を保ってきているように記憶しているので、
ちょうど良いタイミングなので、振り返ってみたいと思う次第である。

なお、本エントリは[HOXO-M Advent Calendar 2017](https://qiita.com/advent-calendar/2017/hoxo-m) 9日目の記事に相当するものである。

# どうしてこうなった
なぜ皆がホクソエムと主張し始めたのか。
その起源は、現在ホクソエムに所属しているyutani氏が当時の状況を赤裸々に綴っている

[匿名集団的知性・ホクソエム――その傾向と対策](http://notchained.hatenablog.com/entry/2015/03/25/001527)

当時の状況から、初期のホクソエムは自らのアイコンをラテアート化し、視覚的統一を図ることで、徐々に自己のアイデンティティを融解させていった。
私も一当事者であったことを記憶している。Tokyo.Rなどの会で逐次報告されていた中では、最大30名ほどがこの統一化を図っていたように記憶しているが、エビデンスを見つけることができなかった。

当時リアルタイムにこの現象を目撃していた私の脳裏には名作SF「攻殻機動隊」における'笑い男事件'を彷彿とさせる何かがあった。
笑い男事件に関する詳細な記述は[Wiki](https://ja.wikipedia.org/wiki/%E7%AC%91%E3%81%84%E7%94%B7_(%E6%94%BB%E6%AE%BB%E6%A9%9F%E5%8B%95%E9%9A%8A))に譲るので、そちらを参照されたい

大事なポイントは下記の点である
<blockquote>あまりにセンセーショナルな事件だった故か、これ以後犯人である「笑い男」の模倣者が数多くの事件を引き起こし、「笑い男マーク」がかばんやTシャツにプリントアウトされ流行するなど一種の社会現象となった。</blockquote>

すなわち、皆がホクソエムというアイデンティティを模倣し始めたのである。恐ろしいミームである。

しかし、一定期間を経過すると、人間の本能的に組み込まれる飽きという症状により、徐々に正常なアイコンに回帰する人間が増えていった。

事態も収束し、平和な日常に戻りつつあったそんな折だった。
まぎれもない昨年のJapan.Rの発表「ホクソエムとはなんだったのか」
<img width="587" alt="スクリーンショット 2017-12-06 18.39.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/38233/d08d0060-18a9-854c-2d03-6c24c27063e3.png">
この発表内において、ホクソエムの法人化が発表され、法人化されたHOXO-Mがスタートしたのだった。

# 誰がいるの
この法人の[ホームページ](http://hoxo-m.com/)にメンバーの紹介がある
9名の所属を確認することができた。
いずれもR界隈やデータサイエンス界隈の猛者ばかりである。

# 何をやっているの
ホームページによると、メインの業務は3つのようだ。

- Research and Product Development
- Trainings, Seminars and Lectures
- Writing Books and Series Articles

当方の観測範囲だと3つめの業績が目立つように感じるが、リサーチやセミナーなども一部請け負っているようである。

どうやら、次の訳書に着手もしているようだ。
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">そろそろ次の訳にとりかかる。前の訳は増刷のタイミング(あるのか？)に対応する。</p>&mdash; マストバーイ (@dichika) <a href="https://twitter.com/dichika/status/937689246948659200?ref_src=twsrc%5Etfw">December 4, 2017</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これら書籍はRを扱う僕らにとってはとても質の高い本になる可能性が高いので、ぜひとも継続的に推進していただきたいものだ。

そんな彼らの活躍を期待しながら、そろそろ筆を置きたいと思う。
最後に一言

```
かたい壁に向かって卵を投げつければ、やわらかい卵は簡単につぶれてしまう。
それでも、わたしは、卵の側に立ちたい。 by 春樹
```

Enjoy！
ベクトルタイルスキーマの話

2016年から2017年にかけ、ベクトルタイルスキーマについて一つの事案があり、それによって「雨降って地固まる」ことがあったと思っていますので、その事案を紹介します。

## 権利的にクリアなベクトルタイルスキーマの再開発
[gh:osm2vectortiles/osm2vectortiles/issues/387](https://github.com/osm2vectortiles/osm2vectortiles/issues/387) に "Move to OSM2VT-developed cartography"という題名の興味深いイシューがあります。2016年7月27にオープンして、2017年1月18日にクローズしたイシューです。

ここでは、現在でいう OpenMapTiles のコミュニティと、Mapbox の方との間での建設的なやりとりが記録されています。

詳細は実際の issue を読んでいただければと思いますが、Mapbox の michaelsteffen さんが、OpenMapTiles の技術的仕事に賛辞を送り、Mapbox のオープンソースプロダクトの活用に感謝と歓迎を示しつつも、Mapbox Streets のベクトルタイルスキーマについては知的財産権で保護しているので、これを侵害しないようにしてほしいと申し入れて来ています。OpenMapTiles コミュニティ側は、一部に感情的な反応や権利に関する原理的な確認の試みを含みながらも、最終的には Mapbox Streets との相互運用性を放棄した新しいベクトルタイルスキーマ（現在の [gh:openmaptiles/openmaptiles](https://github.com/openmaptiles/openmaptiles/)）を新しく開発し、本件は終了しています。

私は本件について、次の通り感じました。

1. ベクトルタイルの形式やベクトルタイルにまつわるソフトウェアではなく、ベクトルタイルのスキーマ、とりわけソースデータからのデータの取捨選択等の構成について争われたが、関係者の努力により、問題は解決されたようである。
2. OpenMapTiles のベクトルタイルスキーマは、このような経緯により、権利的にクリアであることを意識して作られたものとなっており、今後の洗練まで見越せば、それなりによく考えられたものになってくるのではないか。
3. この OpenMapTiles のベクトルタイルスキーマをきっかけとして、ベクトルタイルスキーマの相互運用性という観点は重要になってくる。ベクトルタイルスキーマが相互運用しなければ、ソフトウェアの利用者にとってベクトルタイルが不安定なものとなってくるので、ベクトルタイルの相互運用性は、できるかぎり確保する努力をする価値がある。
4. 今回着目した issue では、同じ OSM データからベクトルタイルを作るという状況にあったから、OpenMapTiles ベクトルタイルスキーマのクリーンさについて、再度争われる余地は残存しているといえなくもない。OSM データではないソースデータを用いて、OpenMapTiles ベクトルタイルスキーマと互換するバイナリベクトルタイルを作成するということは、ベクトルタイルスキーマの安定を通じた、ベクトルタイル技術の普及のために意義深いことである。
fishでも"git "って打つのめんどくさい…!

[前回](https://qiita.com/ryotako/items/d2997d17f9cf29744b44)，fishのコマンドをgitのサブコマンドとして呼び出せるラッパーを書きました．

で，実はこのラッパー，`git-`という名前の関数を作ると「無引数でgitを実行した場合の挙動」を上書きできます．

この性質，うまく利用できないかと思っていたのですが

["git " って打つのめんどくさい…!](http://pocke.hatenablog.com/entry/2015/12/09/000000)

という記事を参考に，次の関数を書いてみました．

```sh:git-.fish
function git-
    if functions -q __git_mode
        functions -e __git_mode
    else
        function __git_mode -e fish_postexec
            commandline "git "
        end
    end
end
```

これを定義しておくと，`git`と一度実行すると，次回以降コマンドラインに`git `が挿入された状態になります．もう一度`git`を空引数で実行すると`git `の自動挿入が解除されます．便利！
![git-.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/124405/0ee28049-0452-0d21-2a03-b077c141f0f1.gif)

# 余談
ちなみに，元ネタの["git " って打つのめんどくさい…!](http://pocke.hatenablog.com/entry/2015/12/09/000000)で紹介されている`subsh`コマンドをfishで書くと以下のようになります．

```sh:subsh.fish
function subsh
# 指定した文字列を毎回コマンドライン先頭に挿入するようにする関数

    set -l sub "$argv"
    
    # --inherit-variable でフック定義時の値をキャプチャ
    function __subsh_hook -e fish_postexec --inherit-variable sub
        if test -n "$sub" -a -n "$argv"
            commandline "$sub "
        else
            # 空エンターあるいは引数なしの`subsh`で終了
            functions -e __subsh_hook 
        end
    end
end
```

fish版の面白いところは，フック関数`__subsh_hook`が呼ばれるタイミングでは変数`sub`が存在しないのに，関数内部で`sub`を使えるところです．つまり，オプション`--inherit-variable`に渡された変数は関数の定義時に値が確定します．
CSSファイルやJavaScriptファイルの末尾のバージョン番号を追加する方法

CSSファイルやJavaScriptファイルを編集した際には、ブラウザはそのファイルの以前のキャッシュを利用しないため、ファイルの末尾にバージョン番号を付与されると、その変更内容がすぐに反映される事となります。

## ステップ 1
まず、以下のような独自のヘルパー関数を定義します。

```php:App/Helpers/Version.php
<?php


if (! function_exists('v')) {

    /**
     * [v description]
     * @param  [type]  $path   [description]
     * @param  boolean $secure [description]
     * @return [type]          [description]
     */
    function v($path)
    {
        $path = ltrim($path, '/');

        if (! file_exists(base_path($path))) return "/{$path}";

        $file = "/{$path}?ver" . filemtime(base_path($path));

        return app('url')->asset($file);
    }

}
```

## ステップ 2
次、composer.jsonのautoload.filesへ以下のようにパスを追加します。

```json:composer.json
"autoload": {
    "classmap": [
        ...
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        // ↓↓↓　追加　↓↓↓
        "app/Helpers/Version.php"
    ]
}
```

## ステップ 3

最後、以下のComposerコマンドを実行します。

```shell-session
composer dump-autoload
```

以上です。

各場所から自作のヘルパー関数が読み込めるようになっていると思います。

# 例

```php:welcome.blade.php

<link rel="stylesheet" href="{{ v('/public/css/app.css') }}">
```

```html:結果

<link href="http://localhost/demo/public/css/app.css?ver1499187293" rel="stylesheet">
```
【入門者向け】AWS Cloud9+echoでGoのAPIサーバーをさくっと作ってpreviewする

# はじめに

この記事は、[Leveragesアドベントカレンダー](https://qiita.com/advent-calendar/2017/engineer)5日目の記事になります。

出番が二回あるので、一回目は軽めなやつを出します。

---

AWS Cloud9が発表されたのでちょろっといじった感じ、GoのAPIサーバーをさくっと試すのに便利な気がしてやってみました。

予想通り、かなりさくさく立てられたのでメモっておきます。

# Cloud9の準備

## AWS Cloud9の環境を用意する

入門用なのでAWSアカウントはあるけど、それ以外はなんもない人前提でお話します。

まず、AWS　Cloud9のページに行き、「Create environment」ボタンをクリックします。（AWSにはログイン前提です、一応）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/4db6c0c1-f3af-2ed0-52e1-b290e5b43fd7.png)

## 環境名とか登録

nameに任意の文字を入力して「Next step」ボタンをクリックします。
descriptionは必要があれば。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/ab85aff2-bf0c-593d-e50e-61d7bac53711.png)


## Configure Settingsは一旦そのまま

EC2のインスタンスとか設定するところですが、デフォで一番小さいのになってるようなので、そのままにして「Next step」

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/675caa8c-51df-137a-c032-d68a615de269.png)

## Review

問題なければそのまま「create environment」します。

これでCloud9の環境設定は終了。

# GoとechoでHallo wolrd文字列返すAPIサーバーを用意するとこ

上までの手順が終わるとIDE画面になるので、まず、Goの開発準備をします。

ありがたいことにgo自体は最初から入ってるので、wgetしなくて大丈夫。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/ea9a2f9e-488a-f2d8-abde-55f04bc43a50.png)

## GOPATH、PATH設定

GOPATHとPATHを設定します。
設定にはIDEの右下に表示されているコンソールを利用します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/2d741d5b-b55f-c6b2-898c-4c7e691e5027.png)


## depのインストール

直接echo をgo getしてもいいんですが、一応、、、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/b7e10ebc-1289-335e-938a-b04779abb6b2.png)

## ディレクトリを掘って、server.goを書く

Goはgo/srcの下にリポジトリ名とかのディレクトリを掘るのが慣例なので、掘ります。
ぶっちゃけそのままコンソールでmkdirした方が早いのですが、せっかくなのでIDEからやります。

今までの状態だと、IDEの左側のペインはこんな感じになっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/aaaae3e0-fcb7-b729-b53f-76c9f0010c4c.png)

github.comのところで右クリックして、「New Folder」

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/c3f708b4-75b8-676e-6363-dd368024e027.png)

そしてこんな感じでserver.goを作ります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/82f3f162-414d-0f40-516d-7b6e4fddf888.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/497a9118-6d27-7593-c30f-59ac2b0c64b2.png)


**<font color="crymson">重要なところは、今のところAWS Cloud9のpreviewは8080ポートでしか機能しないっぽいので（間違ってたら教えてください）サーバーの実行時のポートを8080にすることです。</font>**

## echoインストール

echoをimportしているので、インストールします。
右下のコンソールから以下を叩きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/1d7de34e-f7db-3d48-7945-263fa7256f7a.png)


# 実行

作ったらまずAPIサーバーを起動します。
※右の方にあるRUNをクリックすると起動します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/390ef88f-cb49-5676-0596-bd7757698b25.png)

コンソールが以下のようになったら成功です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/83500750-6ae1-aabd-2702-12de9fa4a3b2.png)

# プレビュー

プレビューはワンタッチでできます。

runの横にあるpreviewをクリックして、「Preview Running Application」をクリックするだけです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/d1421a77-1f00-9225-089b-ba6c5c7e5bcf.png)

## 結果

これでIDEにpreviewが表示されました！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/105934/a3f78264-20dd-697c-c812-664f5bfbebf7.png)

意外とめんどい、サーバー用意したり、goの最新をwgetする（というかURL拾う）する部分が省けるのはいいですね！
BigQuery標準SQLでAppEngineのエラーメッセージログを検索する

# 背景

AppEngineはStackDriver Loggingにログが蓄積されますが、それをBigQueryにストリーミングさせることができます。
私も普段この設定を入れて過去のログ保管や検索を行なっているのですが、エラーメッセージはArrayになっており単純に `WHERE` しただけではエラーになるため備忘としてここに記します。

# クエリー内容

UNSET()でArray部分を展開し別名（この例では `l` （アルファベットの小文字エル）を付ける。
その `l` に対してWHEREをかける。
下記の例では2017年11月中に発生したOOMのログ、且つURLが `/example` で始まるものを日付順で抽出する。


```sql
SELECT
  timestamp,
  l.logMessage,
  protoPayload.resource 
FROM
  `appengine_request.appengine_googleapis_com_request_log_201711*`,
  UNNEST(protoPayload.line) as l
WHERE
  l.logMessage LIKE 'Exceeded soft private memory limit%'
  AND
  protoPayload.resource LIKE '/example%'
ORDER BY
  timestamp ASC
```

# 出力イメージ

| timestamp | logMessages | resource |
|:-----------------:|:------------------:|:------------------:|
| 2017-11-11 00:12:02 UTC | Exceeded soft private memory limit of 128 MB with 152 MB after servicing 56 requests total | /example?url=xxxxx |
| 2017-11-30 00:13:03 UTC | Exceeded soft private memory limit of 128 MB with 132 MB after servicing 11 requests total | /example?url=yyyyy |

# 注意点

例によって時刻はUTCが基準なので、キッチリ抜き出したい場合は [期間指定クエリー](https://qiita.com/ryo-yamaoka/items/6e4f122b3f656877f795) の要領でJSTベースにすると楽。