OmniAICreator/Qiita-1.07M huggingface dataset:
ElmのTaskを試してみる

　Elmでは非同期処理を行うのにTaskというものを使うようなので試してみました。0.18の公式のドキュメントサイトにはまだ準備できていない旨のコメントがありましたので、以下のサイトを参考にさせていただきました。
https://giisyu.gitbooks.io/elm_usui_book/content/src/module/task.html

　プログラムは開始時に「開始！」と表示し、5000ms後に「完了！」と表示します。それだけです。JavaScriptで言えば、setTimeout()に相当するsleep 関数を使います。以下に詳しい説明を加えていきます。

```elm:
import Html exposing (Html, div, text)
import Html.Attributes
import Process exposing (..)
import Task exposing (..)

-- MODEL
type alias Model = String

type Msg
    = TaskResult String

longTask : Task Never String
longTask = 
    Process.sleep 5000
        |> Task.map (always "完了！")

init : ( Model , Cmd Msg)
init =
    "開始！" ! [ Task.perform TaskResult longTask ] 

update : Msg -> Model -> (Model,Cmd Msg)
update msg model =
    case msg of
      TaskResult str -> (str, Cmd.none)


view : Model -> Html Msg
view model =
    text model

subscriptions : Model -> Sub Msg
subscriptions model =
  Sub.none

main : Program Never Model Msg
main =
    Html.program { init = init, view = view, update = update, subscriptions = subscriptions }
```




　ここで使うModelはStringそのものです。

```elm:
type alias Model = String
```

　Taskの実行結果は以下のMsgを発生し、updateを呼びます。

```elm:
type Msg
    = TaskResult String
```

　次にTaskを作ります。

```elm:
longTask : Task Never String
longTask = 
    Process.sleep 5000
        |> Task.map (always "完了！")
```

　まずTask型は以下のように定義されています。Taskコンストラクタに、エラーを表すerr値と、成功を表すok値が続きます。

```
type alias Task err ok = Task err ok
```

　さてsleepの型は以下のように定義されています。Timeで指定した時間が経過した後に、Task x ()　が返ります。今回のTaskのテーマに関して言えば、ここが本質ですね。

```elm:
Process.sleep : Time -> Task x ()
```

　a |> f  は f a のことですから、上のTaskの結果は Task.map (always "完了！") (Task x ()) のようになり、以下のmapの定義から Task x "完了！" になります。(always "完了！")関数は引数に()を取り　関数値は常に "完了！" になるからです。


```elm:
Task.map : (a -> b) -> Task x a -> Task x b
always : a -> b -> a
```

　以上の考察により、最終的に以下のような結果が得られます。

```elm:
longTask = Task x "完了！"
```

　次のinit関数を見ます。

```elm:
init : ( Model , Cmd Msg)
init =
    "開始！" ! [ Task.perform TaskResult longTask ]
```

　これは ! の定義により以下と同等です。

```elm:
init : ( Model , Cmd Msg)
init =
    ("開始！",  Cmd.batch [ Task.perform TaskResult longTask ])
```

　Task.performは以下のようにCmdを作り出します。Taskに実行結果の「Task x "完了！"」の"完了！"に第一引数のTaskResultを被せて、TaskResult "完了！" というMsgでupdateを呼びます。

```elm:
Task.perform : (a -> msg) -> Task Never a -> Cmd msg
```

　型を追うことでプログラムの理解が深まることがありますが、木を見て森が見えない罠に陥ることは避けたいですね。

　Taskはどうなんだろう。Http.getも0.17のころはTaskだったのに、0.18ではRequestになっているし、公式ドキュメントでもまだ扱われていないし．．．
[Swift] Notificationを一回だけObserveするよ！

たまに1回だけNotificationを受けたいということがあるのでextensionを作ったよ。

```swift
extension NotificationCenter {
    
    func addObserverOnce(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) {
        
        weak var token: NSObjectProtocol?
        token = addObserver(forName: name, object: obj, queue: queue) {notification in
            
            token.map(self.removeObserver)
            block(notification)
        }
    }
}

```
phina.jsで作ったゲームの話

##はじめに
大幅に遅刻しました。ごめんなさい。
今年もアドベントカレンダーが始まったのですが、今年は一個しかゲーム作ってないのでネタが溜まっておりません。
今回はphina.jsを使って作っているゲームの紹介をさせて頂こうと思います。

[The Quest for Tanelorn](https://minimo.github.io/QuestForTanelorn/)【[Github](https://github.com/minimo/QuestForTanelorn)】
※Chrome推奨
※音が出ます

![test.gif](https://qiita-image-store.s3.amazonaws.com/0/31052/64084167-2f0a-a7af-4376-7f77f99bb32f.gif)

![12月-23-2017 00-27-34.gif](https://qiita-image-store.s3.amazonaws.com/0/31052/fa7bbb6e-5826-a262-73bc-c706babded78.gif)

横スクロールタイプのアクションゲームです。
全８ステージ（予定）

##開発期間
去年の暮れ頃からぼちぼち作っております。
そろそろ１年です。時間経つのって早い。

##元ネタについて
そうです、このゲームには元ネタがあるのです。
[9leap : ささわーるど by akisasa33](http://9leap.net/games/1110)
横スクロールアクションは、サイドビューのマップチップを用意するのが普通と思っていたのですが、このゲームは見下ろし型のＲＰＧ用マップチップを使用していて「こんなやり方もあるのか！」と衝撃を受け、「いつか俺も作ろう！」と思ったのが始まりです。
安易ですね。

タイトル名については、ぐぐると[出てきます](https://www.youtube.com/watch?v=3IAT06unls8)。
さらにその元ネタの[エターナルチャンピオンシリーズ](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%82%BF%E3%83%BC%E3%83%8A%E3%83%AB%E3%83%BB%E3%83%81%E3%83%A3%E3%83%B3%E3%83%94%E3%82%AA%E3%83%B3%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA)は読んでおいて損はありませんぜ、ダンナ。


##技術的な話
このゲームに限った話ではありませんが、少し凝ったゲームを作ると利用するアセットも多くなり、容量も嵩む為、起動時のロードにかなりの時間がかかります。
プレイヤーを待たせない工夫としてオープニングデモを用意し、そのバックグラウンドで基本アセットのロードを行う事にしました。

```JavaScript:AssetLoaderEx
phina.define("phina.extension.AssetLoaderEx", {

    //進捗
    loadprogress: 0,

    //読み込み終了フラグ
    loadcomplete: false,

    init: function() {
    },

    load: function(assets, callback) {
        this._onLoadAssets = callback || function(){};
        var loader = phina.asset.AssetLoader();
        loader.load(assets);
        loader.on('load', function(e) {
            this.loadcomplete = true;
            this._onLoadAssets();
        }.bind(this));
        loader.onprogress = function(e) {
            this.loadprogress = e.progress;
        }.bind(this);
        return this;
    },
});
```
こんな感じのクラスを作り、

```JavaScript
var assets = qft.Assets.get({assetType: "common"});
phina.extension.AssetLoaderEx().load(assets, () => {console.log("終わったよ")});
```
シーンの初期化でこのように呼び出してバックグラウンドで読み込みをさせています。
※*qft.Assets.get*は独自に作成したアセット管理クラスで、*assetType*に従ったアセットのリストを返します。


ステージマップ、イベント等は作成と変更の手間を削減する為、TiledMapEditorというレベルエディタを使っています。
[phina.jsでTiledMapEditorを利用する](https://qiita.com/minimo/items/b55b792c2fa19964acb4)
地味に便利で実用性も上がったので、そろそろプルリクしようかなと。

ゲームパッド対応も、例によって去年のアドカレで書いた物を使ってます。
[phina.jsでGamePadを使う](https://qiita.com/minimo/items/27020fdb66375f1f868b)

正直、去年とやっている事に代わり映えありません。
過去の資産で生きている上に、ここ一年成長してない事を痛感してスカイツリーから紐無しバンジーやりたい気分になってきますが、とりあえず元気に生きてます。

##今後の課題
いい加減疲れたので、もうこれで完成にしたいと思っていますが、ラスボスが決まってません。
このまま、盛り上がりも無くゴールってのも味気ないので何とかしたい感じではあります。
当初はこんなに時間掛けるつもりはなかったんですよね…何故こうなった。
今年はこれ一辺倒であったので、そろそろ別のゲーム作りたくはあります。

##まとめ
・phina.jsでゲーム作るのは楽しい。
・オープニング作ると一気にそれっぽくなってちょっと気分がアガる。
・TiledMapEditorのプラグインは便利なので誰か使って。

来年はもうちょっと規模の小さいゲームをサクサク量産して行きたいですな。
ccacheを使って build 時間を短縮する

# はじめに
大量のソースコードを build する場合、build 時間が長時間になることがしばしばです。
ccacheを使うことで、2度目以降の build 時間を短縮することができます。
ここでは ccacheの使い方を説明します。 OS は Ubuntu 14.04 です。

# install
apt-getを使ってinstallします。version は 3.1.9 です。

```bash:console
$ sudo apt-get install -y ccache
$ ccache --version
ccache version 3.1.9
```

# setup
PATHを設定します。.bashrc に追記しておきます。

```bash:console
$ export PATH=/usr/lib/ccache:$PATH
$ echo -e "\nexport PATH=/usr/lib/ccache:\$PATH" >> $HOME/.bashrc
```

# sample
build する ソースコード を取得します。
なんでもいいのですが、ここでは busybox を download します。
https://busybox.net/downloads/

```bash:console
$ tar jxvf busybox-1.26.2.tar.bz2 
$ cd busybox-1.26.2
$ make defconfig
$ time make -j4
real	2m44.376s
user	4m5.563s
sys	0m53.794s
```

2m44sかかりました。

make clean 後 再度 build します。

```bash:console
$ make clean
$ time make -j4
real	1m18.415s
user	1m35.769s
sys	0m33.424s
```

1m18になりました。 build 時間が 半分になりました。

# cache 情報
-s オプションでcacheの情報を見れます。

```bash:console
$ ccache -s
cache directory                     /home/user/.ccache
cache hit (direct)                     4
cache hit (preprocessed)             516
cache miss                           526
called for link                       37
called for preprocessing               7
no input file                        174
files in cache                      2133
cache size                          16.6 Mbytes
max cache size                       1.0 Gbytes
```

cacheの実体はデフォルトで$HOME/.ccacheに置かれます。

```bash:console
$ ls /home/user/.ccache
0  1  2  3  4  5  6  7  8  9  CACHEDIR.TAG  a  b  c  d  e  f  tmp
```

cache data の 最大値 は -M option で指定します。

```bash:console
$ ccache -M 2G
Set cache size limit to 2.0 Gbytes
$ ccache -s
(...)
max cache size                       2.0 Gbytes
```
Ubuntu 16.04 サスペンド復帰後にキーボードが効かない

# 0.環境
- Linux
    - Ubuntu 16.04 LTS (16.04.3)

# 1.現象
サスペンド復帰後にUSBキーボードが効かなくなってしまう。
（USBを挿し直すと復活する・・）

# 2.対策方法
dmesgコマンドで確認すると、「usb_submit_urb(ctrl) failed: -1」というエラーが発生していて、どうもキーボードの認識に問題がある模様。
ちなみにキーボードは、中華製の「I-600」というキーボード。

```
$ lsusb
Bus 004 Device 003: ID 05e3:0732 Genesys Logic, Inc. All-in-One Cardreader
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 003: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 04d9:a0cd Holtek Semiconductor, Inc. 
Bus 001 Device 005: ID 046d:0994 Logitech, Inc. QuickCam Orbit/Sphere AF
Bus 001 Device 004: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 001 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

上記、「Bus 001 Device 002: ID 04d9:a0cd Holtek Semiconductor, Inc. 」が問題のキーボードとなる。
以下を参照して対策を行った。

https://askubuntu.com/questions/948982/mechanical-keyboard-aukey-km-g9-doesnt-work-after-suspend-ubuntu-gnome-17-04/948988

```
$ sudo vi /etc/default/grub
```
```
     11 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
     12 GRUB_CMDLINE_LINUX=""
```

12行目を以下のように変更してセーブする。

```
     11 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
     12 GRUB_CMDLINE_LINUX="usbhid.quirks=0x04d9:0xa0cd:0x00000008"
```

"0x04d9:0xa0cd"の部分が、USBキーボード「Bus 001 Device 002: ID 04d9:a0cd Holtek Semiconductor, Inc. 」のID部分となる。
セーブしたら、リブートする。

```
$ sudo update-grub
```

以上、無事解決しました。
Prophetでインスタント機械学習

## はじめに
この記事はMicroAd Advent Calendar 2017の23日目の記事です。

現在マイクロアドで内定者としてアルバイトをしています。
つい最近Prophetを知ったので、そのことについて少しだけ書かせて頂きます。

## Prophetとは
すーぱー簡単に書くことができる時系列データ専用のフェイスブックが作った機械学習ライブラリです。
現時点ではpythonとRに対応しているみたいです。
今回はバージョン```fbprophet==0.2.1```をpythonで試していきます。

## 今回試してみるデータ
最近乱高下の激しいBTCをお題にして、今後1年間どのような値動きをするかを適当に予測します。
今回は以下のサイトでデータを入手しました。csvで保存できるため、pandas等での使い勝手が良いです。

https://jp.investing.com/currencies/btc-jpy-historical-data

```
"日付け","終値","始値","高値","安値","前日比%"
"2017年12月23日","1,709,670","1,593,787","1,839,993","1,278,313","7.27"
"2017年12月22日","1,593,787","1,830,241","1,993,563","1,260,284","-12.92"
"2017年12月21日","1,830,241","1,875,889","2,105,416","1,768,900","-2.43"
...
"2014-09-19","43,370","45,779","52,882","41,302","-5.26"
"2014-09-18","45,779","48,559","52,882","45,020","-5.73"
"2014-09-17","48,559","49,299","50,653","47,561","-1.50"
```
過去2~3年分くらいのBTC/JPYのデータを入手できます。


Prophetを利用するときには、dateやdatetimeのカラム名を```ds```とすることと、分析対象の数値を```y```にしなければなりません。
なので今回は「yyyy年mm月dd日」を「yyyy-mm-dd」に変換、終値を数値に変換してそれぞれカラム名を```ds```と```y```にします。

```
ds,y
2014-09-17,48559
2014-09-18,45779
2014-09-19,43370
...
2017-12-21,1830241
2017-12-22,1593787
2017-12-23,1709670
```
## プログラム
必要なライブラリはpandasとfbprophetだけです。

```
pip3 install pandas
pip3 install fbprophet
```

そしてコードはこれだけです!

```python3
import pandas as pd
from fbprophet import Prophet

data = pd.read_csv("BTC_JPY.csv")
model = Prophet()
model.fit(data)
future = model.make_future_dataframe(periods=365)
forecast = model.predict(future)
model.plot(forecast)
model.plot_components(forecast)
```

細かくて煩わしいことは全部Prophetがやってくれますが、
ある程度のパラメーターを設定することもできます。
例: ```model = Prophet(growth='logistic')```
以下は設定できるパラメータとその初期値です。

```
growth='linear', 
changepoints=None, 
n_changepoints=25, 
yearly_seasonality='auto', 
weekly_seasonality='auto', 
daily_seasonality='auto', 
holidays=None, 
seasonality_prior_scale=10.0,
holidays_prior_scale=10.0, 
changepoint_prior_scale=0.05, 
mcmc_samples=0, 
interval_width=0.80, 
uncertainty_samples=1000
```

## 実行結果
![スクリーンショット 2017-12-23 19.43.16.png](https://qiita-image-store.s3.amazonaws.com/0/198141/d3088c36-9509-4b11-2c03-c2c0739fa8f5.png)
![スクリーンショット 2017-12-23 19.45.12.png](https://qiita-image-store.s3.amazonaws.com/0/198141/3244dc40-04b6-7b40-5dff-898dbfda269c.png)

###### -考察-
これからも上がりそう(適当)

## まとめ
統計や数学やプログラミングが全くできない私でも、なんとなくそれっぽい結果を出力したふりをすることができました。
使ってみて思った利点は以下の3点です。

・ 細かい設定なしにとりあえず実行できる
・ 学習が速い
・ 結果のグラフの出力も簡単

比較的簡単といわれるscikit-learnやKerasでも、今回と同じことをしようとするとそれなりに知識が必要になります。
もちろん、それらのライブラリでは時系列データに限らず学習でき、モデルの設計やチューニングができる柔軟性があります。
Prophetはとりあえず一旦サクッと予測してみるというような使い方が出来るのが非常に魅力的です。


#### P.S.
VisualStudioCodeに拡張機能"Jupyter"を入れたらPythonの開発環境としてとても素晴らしいものになりました。
![スクリーンショット 2017-12-23 19.47.11.png](https://qiita-image-store.s3.amazonaws.com/0/198141/fd3cab60-2e5f-b683-d075-a8eaf7b6e683.png)
社内のテストケースの管理がバラバラな件について 


[株式会社オズビジョン](http://www.oz-vision.co.jp/)の@s-nagayamaです。

現在社内で既存処理のリプレイスを行っています。
開発の中で既存処理のテストを行おうとしたときに困ったことが出てきたのでそのことについて書いていきます。

## 何が困ったのか
- 既存のテストケースが様々な場所散らばっている
- テストケースの内容が更新されていない
- 既存処理の仕様が残っていない

## 既存のテストケースが様々な場所散らばっている
既存の処理のテストを行うにあたり、まずは過去のテストケースをまとめる作業から始めました。基本的に社内のドキュメントはGithub上で管理していますが、古い機能はその限りではありません。社内の共有フォルダ・googleスプレットシート・さらには各個人のローカルに眠っているケースもあり、テストケースをまとめるのにかなりの時間を要してしまいました。

## テストケースの内容が更新されていない
チームのエンジニアの記憶等を参考にしつつ過去のテストケースをひとしきり集めた後、中身を確認していくと現在の仕様とテストケースが合わない箇所が多々あることがわかりました。複数人のエンジニアが改修を重ねているので当然ではあるのですが、都度ドキュメントが更新されているわけではないのでいざというときにやはり困ってしまいます。

## 既存処理の仕様が残っていない
中にはテストケースが残っていない機能も存在します。この場合テストケースの作成が必要になるのですが、そもそも仕様が残っておらず挙動が正しいものであるのか細かいバグが放置されているものなのか判断がつかないものがあります。それでもテストをしないわけにはいかないので、どうにかテストケースの作成を行わなければなりません。

## 結果どうしたのか
- テストケースを作成しなおす
- 仕様がわからないものに関しては現在のコードを正とする
- バグか判断がつかないものについては運用を担当しているチームとすり合わせを行い現状の正しい挙動を定義する

今回は社内のエンジニアの皆さんの力をお借りしつつテストケースの作り直しを行いました。合計で2000ケースほどのテストケースになりましたが、現状のサービスの大体の部分をカバーできるテストが作成されたと思います。ご協力いただいた皆様ありがとうございます。

## 良かったと思うこと
現状動いているコードをいったん正としてテストケースを作成するのが効率が良かったと思います。もちろんバグがある箇所もありますが、運用担当のチームとすり合わせることで正しい挙動を定義できるとともに今後改修しなければならない箇所の洗い出しにもなりました。現在テストの結果とともに細かいバグのリストをスプレットシートで管理を行いリスが作成されています。リストの内容を改修した際に、今回作成したテストケースが更新できる形になっているのでこれまで起こっていたドキュメントが更新されない問題が解消されていきそうです。また、機能ごとにテストケースをまとめたので現時点での最新のテストケースが一か所に集約されました。これで既存機能のテストを行うときに余計な時間を減らすことができていきそうです。

## 終わりに
ほぼ最近大変だったことの感想になってしまいました。
次はテストの中身についてもう少し詳しい内容で書いていければと思います。
（パラメータの組み合わせのみ書かれていたり、遷移図があったりなかったり、想定結果が書いていなかったり）

さんざん書きましたが、過去のテストケースの中には自分が作成したものも含まれており、とても反省したのでこれからはドキュメントを適当に終わらせないようにしたいと思います。
ガラケープログラミング

# はじめに

最近は、ガラケー向けサイトを構築することもなくなりました。
ガラケー向けサイトを作ったことがない人も増えてきていると思います。

今回は、ガラケー向けサイトを作る上で、利用したテクニックを紹介します。

サンプルコードは、すべてPHPです。
2013年ごろの情報をもとに記述しています。現在と仕様が異なる場合があります。

# ユーザーエージェント

ユーザーエージェントからキャリアを判定します。

はじめに、ユーザーエージェントを取得する方法です。

```php
$agent = (isset($_SERVER['HTTP_USER_AGENT']) && !empty($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : '';
```

ドコモのとき、trueを返します。

```php
ereg("^DoCoMo", $agent) == 1;
```

auのとき、trueを返します。

```php
ereg("^UP.Browser|^KDDI", $agent) == 1;
```

ソフトバンクのとき、trueを返します。J-PHONEやVodafoneもソフトバンクとします。

```php
ereg("^J-PHONE|^Vodafone|^SoftBank", $agent) == 1;
```

Willcomのとき、trueを返します。

```php
strpos($agent, 'WILLCOM') || strpos($agent, 'SHARP/WS') || strpos($agent, 'DDIPOCKET') == 1;
```

# Cookieサポート判定

iモードブラウザ1.0、iモードブラウザ2.0の一部端末では、Cookieが利用できません。
一度、Cookieに値を書き込んで、その値が読み取れるかでCookieが利用できるか判定します。

```php
// cookieが使えるか判定するために1を入れておく
@setcookie('cookie', '1', 0, '/');
(preg_match('/^DoCoMo\/1.0/', $agent) || preg_match('/^DoCoMo\/2.0[^(]+\(c100;/', $agent) || @$_COOKIE['cookie'] != 1);
```

Cookieが利用できない場合、セッションIDを付与したURLを作成する必要があります。

```php
$url = $url.(strpos($url, '?') == false) ? '?' : '&'.session_name().'='.session_id();
```

# IPアドレス

IPアドレスからキャリアを判定します。

OpenPNEの[携帯電話IPアドレス帯域リスト](http://www.openpne.jp/pne-downloads/mobile_ip_list/)からymlファイルを入手します。

例えば、ドコモのIPアドレス帯域は、以下のとおりです。

```ruby
docomo:
  - 124.146.174.0/24
  - 124.146.175.0/24
  - 202.229.176.0/24
  - 202.229.177.0/24
  - 202.229.178.0/24
  - 210.136.161.0/24
  - 210.153.84.0/24
  - 210.153.86.0/24
```

IPアドレスを取得します。

```php

$ip = $_SERVER['REMOTE_ADDR'];
        
/* HTTP_X_FORWARDED_FORがある場合は上書きする */
if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
```

ymlファイルを読み込みます。yaml拡張モジュールが必要です。

```
$table = yaml_parse_file(dirname(__FILE__).DIRECTORY_SEPARATOR.'mobile_ip_address.yml');
```

このIPアドレス帯域リストにIPアドレスが含まれているか確認します。

```php
$carrier = 0;

foreach($table as $c => $caddrs){
	foreach($caddrs as $check_addr){
		list($p_ip, $mask) = explode("/", $check_addr);
		$ip_long = ip2long($p_ip) >> (32 - $mask);
		$p_ip_long = ip2long($ip) >> (32 - $mask);
		if($ip_long == $p_ip_long) {
			$carrier = $c;
			break;
		}
	}
}
```
SQLのSELECT文と関係代数の関係について整理する

　関係データベース(Relational DataBase)における関係モデルの代数的演算が関係代数です．
　SQL の SELECT文も，この関係モデルにより記述されるものであり，関係代数がその要素として含まれています．
　そこで，関係代数と SELECT 文の関係について整理してみます．

## SELECT 文における関係代数

### SELECT　の構成要素
　SELECT 文と関係代数の関係は，およそ，以下のようになります．

SELECT **射影** FROM **結合** WHERE **制限** ;

　それぞれについて，見ていきましょう，

### 結合
 結合は，2つのテーブルを 1つのテーブルに合成する演算です．
　　結合には
　- クロス結合（直積）
　- 内部結合
　- 外部結合
などがあります．

　直積の場合には，　```t1, t2``` のようにカンマで接続し，
　内部結合の場合には， ```t1 INNER JOIN t2 ON t1.c1 = t2.c2``` のように記述します．

### 射影
　射影は，あるテーブルから指定された列だけを抜き出したテーブルを生成します．
　たとえば，テーブル t1 が以下のようなものであった場合，

| c1 | c2 | c3 |
|:-:|:-:|:-:|
|1|2|3|
|4|5|6|

以下のような，c2　と c3 を抜き出したテーブルを取得する演算が **射影** です．

| c2 | c3 |
|:-:|:-:|
|2|3|
|5|6|

　これを取得するには，```SELECT c2,c3 FROM t１``` のように射影の部分に ```c2,c3``` の指定をします．

### 制限
　**制限**は，テーブルに含まれる行から，指定された条件の行だけを含むテーブルを生成する演算です．
　たとえば，先の t1 から c1 に 4 が含まれる行だけをもつテーブル

| c1 | c2 | c3 |
|:-:|:-:|:-:|
|4|5|6|

を生成するには，```SELECT * FROM t1 WHERE c1=4``` のように，**制限**の部分に ```c1=4``` を指定します．

## 関係代数の演算の効果を意識しよう

　以下の 2つの SELECT 文の違いを考えてみましょう

```
SELECT
　　 * 
FROM
　　 t1, t2
　WHERE
　　 t1.c1 = t2.c4 AND t1.c1 = 4
```

```
SELECT
　　 *
FROM
　　 t1 INNER JOIN t2 ON t1.c1 = t2.c4
WHERE
　　　t1.c1 = 4
```

　先の SELECT 文は
　　結合： ```t1, t2``` (クロス結合）
　　制限：　```t1.c1 = t2.c4 AND t1.c1 = 4```
です．
　したがって， t1 に n行，　t2 に m行のデータがあった場合，結合によって n*m 行のテーブルが生成され，そのテーブルの中から，制限によって　```t1.c1 = t2.c4 AND t1.c1 = 4```　である行だけが抽出されます．
　ですので，一時的に n*m 行のテーブルが生成されることになります．

　これに対して，後の SELECT 文は
　　結合： ``` t1 INNER JOIN t2 ON t1.c1 = t2.c4``` (内部結合）
　　制限：　```t1.c1 = 4```
です．
　つまり，結合では ```t1.c1 = t2.c4``` を満たす行（r行）だけを含むテーブルが生成され，制限では r行のテーブルから ```t1.c1 = 4``` である行だけが抽出されます．
 n*m >> r であれば，こちらの SELECT 文の方が，一時的に生成されるテーブルが小さくなります．

### まとめ

　この説明は原理的なものであり， 実際に ```EXPLAIN``` で双方の実行計画を確認してみると，ほとんど違いがなかったりします．
　ですが，長い　SELECT文を書いたりするときには，この原理を念頭において書いた方が良いと思います．
Anaconda環境でscrapyをインストールしたときにつまづいた(Windows)

scrapyのインストールに少し時間がかかってしまったので、同じエラーでつまづいた時のために書いておきます。


## 結論
* 「conda install -c conda-forge scrapy」を実行する


## 環境
* Windows 10
* Anaconda 1.6.0
* python 3.6

## エラーメッセージ
普通にpipでインストールしようとするとエラーが出ます。

```
pip install scrapy
```

```
copying src\twisted\internet\test\fake_CAs\thing2.pem -> build\lib.win-amd64-3.6\twisted\internet\test\fake_CAs
    copying src\twisted\mail\test\rfc822.message -> build\lib.win-amd64-3.6\twisted\mail\test
    copying src\twisted\python\test\_deprecatetests.py.3only -> build\lib.win-amd64-3.6\twisted\python\test
    copying src\twisted\words\im\instancemessenger.glade -> build\lib.win-amd64-3.6\twisted\words\im
    copying src\twisted\words\xish\xpathparser.g -> build\lib.win-amd64-3.6\twisted\words\xish
    running build_ext
    building 'twisted.test.raiser' extension
    error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools

    ----------------------------------------
Command "C:\Users\****\Anaconda3\python.exe -u -c "import setuptools, tokenize;__file__='C:\\Users\\****\\AppData\\Local\\Temp\\pip-build-_9uutx9s\\twisted\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record C:\Users\****\AppData\Local\Temp\pip-gozb9s14-record\install-record.txt --single-version-externally-managed --compile" failed with error code 1 in C:\Users\****\AppData\Local\Temp\pip-build-_9uutx9s\twisted\
```

調べたらVisual C++が14.0がインストールされているのにエラーが出てました。
Twistedをインストールしている際に出たエラーのようなので、調べてみると、Windows環境でpythonのversionが3.0以上の場合、Twistedがインストールできないらしいです。
Wikipediaの最新の更新情報を取得する

こんにちは、23日目の投稿になります。

皆さんは[recent change stream](https://www.mediawiki.org/wiki/API:Recent_changes_stream)というWikipediaのAPIをご存知でしょうか。

具体的には下記の「最新の更新」ページの内容を取得するためのAPIです:
https://ja.wikipedia.org/wiki/特別:最近の更新?hidebots=1&hidecategorization=1&hideWikibase=1&limit=50&days=7&urlversion=2

今回はこれをPerl 6で取得してみましょう

[IO::Socket::Async::SSL](https://github.com/jnthn/p6-io-socket-async-ssl)
を使うととりあえず(※)は実現できます:

```
use IO::Socket::Async::SSL;                                                                         
use JSON::Tiny;                                                                                     
                                                                                                    
my $conn = await IO::Socket::Async::SSL.connect('stream.wikimedia.org', 443);                       
$conn.print: "GET /v2/stream/recentchange HTTP/1.0\r\nHost: stream.wikimedia.org\r\n\r\n";          
                                                                                                    
react {                                                                        
    whenever $conn { 
        if $_ ~~ /^^data\:\s(\{.+\})\r*\n/ {                                             
            try { 
                CATCH {    
                  when X::JSON::Tiny::Invalid { $*ERR.say($_) } # (#1)
                }                                                                      
                my $json = from-json(~$0);                                                          
                say $json if $json<wiki> eq 'jawiki'; # (#2)                                              
            }                                                                                       
        }                                                                                           
    }                                                                                               
}                                                                                                   
                                                                                                    
$conn.close;                                                                                        
```

+ ポイント
  + [IO::Socket::Async::SSLのサンプル](https://github.com/jnthn/p6-io-socket-async-ssl#synopsis)をベースに書いていきましょう
  + JSON::Tinyが吐く例外はCATCHで捕らえてあげると良いです。ちなみに`$*ERR.say($_.perl)`に書き換えると、どんな入力でうまくいかなかったのかSTDERRに出力できるようになります。 (#1)
  + `wiki`がキーになっている要素を見ることで日本語版のWikiepdiaに絞ることができます (#2)

以上、23日目の投稿でした。
(特定のWikipedia編集者の名前を載せるのは個人的に好ましいと思わないので実行結果は掲載しません)

※ APIから適切にエスケープのなされていない生のテキストが吐かれてしまうせいか、JSON::Tinyでのパースが結構な頻度で失敗してしまうようです
Datastoreのnamespaceを変更して複製するには？

# NamespaceごとにDatastoreを複製した
GCPのDatastoreにはnamespaceによってパーティションを作る機能があります。一つのnamespaceにあるものを丸ごと違うnamespaceに移す、というのはどのようにやればいいのか。やることがあったので書いておきます。

# Namespaceを切り替えることはできない？
そもそも最初にやりたかったのは、datastoreに保存された全てのEntityのnamespaceを変更できないかということ。
[ただ、どうやらできない?](https://stackoverflow.com/a/4228860)

> Namespace is the part of the Key. So you can't change or copy all data from one namespace to another. As I understand all you can do is to fetch all objects from one namespace and create NEW objects with the same properties in another namespace.

というわけで、デフォルトのnamespaceから新しくnamespaceを切って丸ごとコピーする方法をやってみました。

# namespace_manager
namespaceを変えるには、namespace_managerを使います。

```python
import logging
from google.appengine.api import namespace_manager

#現在のnamespaceを知るには
current_namespace = namespace_manager.get_namespace()
# defaultは空
logging.debug(current_namespace)
# namespaceをnew_namespaceに設定
namespace_manager.set_namespace('new_namespace')
# 以下でput()したら設定したnamespaceで保存される
```
保存したいもエンテティはこんな形式だと仮定します。idはitemをそのまま使うということにしておきます。

```python
class Item(ndb.Model, NDBMixin):
    item = ndb.StringProperty()
    message = ndb.StringProperty()
```

# namespaceを変更した場所に丸ごと保存するには？
前のnamespaceの状態で、datastoreから引き出してきて、set_namespaceしたあとに保存します。

```python
# 全件取得
items = Item.query().fetch()
# namespaceを変更
namespace_manager.set_namespace('new_namespace')
entities = (Category(
    id=item.item,
    item=item.item,
    message=item.message,
    ) for item in items)
# 一括保存
ndb.put_multi(entities)
```

# parentキーも保存する場合

複数のカインド含めて丸ごと複製したいときに、parentキーを持っていたりすることもあります。その際には、もちろんですがキーリファレンスも作り直して保存してあげる必要があります。

```python
class ChildItem(ndb.Model, NDBMixin):
    item = ndb.StringProperty()
```

```python
children = ChildItem.query().fetch()
entities = (ChildItem(
    id=child.item,
    parent=ndb.Key(Item, item.key.parent().get().item),
    item=child.item,
    ) for child in children)
ndb.put_multi(entities)
```


こんな感じでやってみましたが、他にいい方法がありそうな気もします。。
terraformでECS環境(Fargate)をぶち上げる

月初のre:InventでFargateが発表されてECSを使ってみたい欲が高まったので、terraformでFargateを利用したECS環境の構築をしてみました。

## 使うもの
- terraform 0.11.1
- terraform-provider-aws 1.6
- awsアカウント

## コード
githubにあげてみました。(手元で動作確認して動いたんですが、動かなかったらすみません、、)
https://github.com/yukkyun/terraform-ecs-sample

## 実行方法
1. `main.tf`のprofileを自分の環境のaws profile名に書き換えてください。
2. あとは普通にterraformを実行

    ```shell:
    $ terraform init
    $ terraform plan
    $ terraform apply
    ```
3. 終わったら下記コマンドでalbのDNS名を取得

    ```
    $ terraform state show aws_lb.alb
    ```

4. `3.`で取得したDNS名にブラウザでアクセス、Nginxのデフォルトページが表示されたら成功！

## ハマった箇所

### logging driver awsを使う場合、ロググループを先に作っておく必要がある
logging driver awsを利用する場合はタスク定義でログの出力先に指定したロググループを事前に作っておく必要があるようです。
タスクに対して`AmazonECSTaskExecutionRolePolicy`みたいなpolicyを割り当てたRoleを適用していたのですが、このpolicyだとcloudwatchlogsのロググループは作成してくれないようで(そもそも作成してくれるのかはわからないが、、、)、延々タスクが作成されてはストップされるという挙動を繰り返しました。。サンプルで作成したterraformではcloudwatchlogsのロググループを事前に作成するようにしています。

### ENIにpublicIPを持たせない場合、NATが無いとpullに失敗して、taskが立ち上がらない
タスク作成時に`publicIPの自動付与`という設定があるのですが、こいつを無効にしているとdocker pullに失敗しタスクが立ち上がりません。ロググループの時と同様、延々タスクが作成されてはストップという挙動を繰り返しました。。無効にする場合はNATゲートウェイを作成するようにしましょう。

### タスクが立ち上がらない場合のデバッグ方法がわからなかった
↑に書いたように、タスクがうまく立ち上がらないと謎にストップスタートを繰り返します。ECSの管理画面は機能のタブが色々有り、どこのログを見てデバッグすればいいかがわかりにくかったです。AWSの公式ドキュメントにはちゃんと書いてあったので、すぐ調べれば良かったなーと思いました、、

- http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/stopped-task-errors.html

## まとめ
terraformでECS環境を作ってみることでいろいろ勉強になりました。今後はオートスケールとかblue-green deploymentとかにもチャレンジしてみたいですね。
同じ長さのリストを同時にループするにはzip関数が便利

同じ長さのリストを同時にループするには[zip関数]が便利です。ちなみに圧縮するという意味のzipではないので注意が必要です。

[zip関数]:https://docs.python.jp/3/library/functions.html#zip

# [zip関数]
こんな感じの同じ長さのデータ達があるとします。

```py3:データ群
names = ["Suzuki", "Tanaka", "Kato", "Suzuki", "Kato"]
numbers = [5, 2, 4, 5, 1]

print(len(names))
print(len(numbers))

"""
5
5
"""
```
zip関数を使うと下のようにそれぞれの要素をひとつずつずらしながら表示することができます。

```py3:zip関数使用例
for name, number in zip(names, numbers):
	print(name, number)

"""
Suzuki 5
Tanaka 2
Kato 4
Suzuki 5
Kato 1
"""
```
ちなみになぜfor文を`for name, number in zip(names, numbers):`
このように書けるかは[zip関数]の戻り値を展開して表示してみればわかります。

```py3:zip関数の戻り値
from pprint import pprint

pprint(list(zip(names, numbers)))

"""
[('Suzuki', 5), ('Tanaka', 2), ('Kato', 4), ('Suzuki', 5), ('Kato', 1)]
"""
```
要素ごとをまとめたtupleを[zip関数]が作ってくれていたのでそれをループさせれば
zip関数使用例のように表示させることができたんですね。

以上です、お疲れ様でした。

#　参考
 - ライブラリーリファレンス
  - [zip関数](https://docs.python.jp/3/library/functions.html#zip)
  - [tuple関数](https://docs.python.jp/3/library/functions.html#func-tuple)
  - [tuple型](https://docs.python.jp/3/library/stdtypes.html#typesseq-tuple)
DataFrame で複数列インデックスで検索する方法

```py
df = pd.DataFrame({
    'A': ['a', 'b', 'c'],
    'B': ['x', 'y', 'z'],
    'C': [1, 2, 3],
}).set_index(['A', 'B'])

#       C
#  A B
#  - -  -
#  a x  1
#  b y  2
#  c z  3
```

これからインデックス `A='b' and B='y'` の値を取り出す方法:

```py
df.loc[[('b', 'y')]]

#       C
#  A B
#  - -  -
#  b y  2
```

`.loc[[インデックス]]` と指定することで、該当行が取れる。
インデックスが複数列の場合は `('b', 'y')` のようにタプルで指定することになる。

ちなみに `.loc[[インデックス1, インデックス2, ...]]` のようにカンマ区切りで指定すれば行を複数取れる。

```py:例
df.loc[[('a', 'x'), ('b', 'y')]]

#       C
#  A B
#  - -  -
#  a x  1
#  b y  2
```
[macOS][iOS]iCloud Driveに文書を格納する

<p>前回のおさらいから。</p>
<p>ADC文書によると、iCloudストレージを利用する方法は以下となる。</p>

<ul>
<li>キー値ストレージ</li>
<li>iCloudドキュメントストレージ</li>
<li>Core Dataストレージ</li>
<li>CloudKitストレージ</li>
</ul>

<p>前回、iCloudドキュメントストレージに読み書きしたが、macOSだと ~/Library/Mobile Documents/iCloud~バンドルID/ 配下だった。</p>

<p>iCloud Drive配下でないのだが、どうやればiCloud Driveに読み書きできるのか？調べてみた。</p>

<p>CapabilitiesでiCloudを有効にし、Info.plist に NSUbiquitousContainersキー を追加すればいいようだ。</p>

<pre><code>&lt;key&gt;NSUbiquitousContainers&lt;/key&gt;
    &lt;dict&gt;
        &lt;key&gt;iCloud.com.example.MyApp&lt;/key&gt;
        &lt;dict&gt;
            &lt;key&gt;NSUbiquitousContainerIsDocumentScopePublic&lt;/key&gt;
            &lt;true/&gt;
            &lt;key&gt;NSUbiquitousContainerSupportedFolderLevels&lt;/key&gt;
            &lt;string&gt;Any&lt;/string&gt;
            &lt;key&gt;NSUbiquitousContainerName&lt;/key&gt;
            &lt;string&gt;アプリ名など&lt;/string&gt;
        &lt;/dict&gt;
    &lt;/dict&gt;
</code></pre>

<p>NSUbiquitousContainersキー には、コンテナ識別子を設定する。</p>

ソースコード
GitHubからどうぞ。<br />
<a href="https://github.com/murakami/KeepADiary">https://github.com/murakami/KeepADiary</a> - GitHub<br />

関連情報
<a href="https://developer.apple.com/jp/documentation/General/Conceptual/iCloudDesignGuide/Chapters/DesigningForDocumentsIniCloud.html">iCloud設計ガイド</a><br />
<a href="https://cocoa-kanto.connpass.com">Cocoa勉強会 BUKURO.swift (connpass)</a><br />
<a href="https://atnd.org/groups/cocoa-study">Cocoa勉強会 BUKURO.swift (ATND)</a><br />
<a href="http://cocoa-study.peatix.com">Cocoa勉強会 BUKURO.swift (Peatix)</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />
<a href="https://t.co/6P3h2jtbRk>note</a><br />
<a href="https://qiita.com/m_yukio>Qiita</a><br />
PHP Way #1 に参加してきた

BASE株式会社さん開催の、「[PHP Way #1](https://base.connpass.com/event/73588/)」というイベントに参加しましたのでレポート。
(※メモなので、正確性は微妙です)

*開発言語をPHPから他の言語に変更するWebサービス企業がある中で、あえてPHPを使い続けることを決めており、今後のサービスの成長、チームの発展をPHPでコミットしていく企業によるプレゼンテーション*

というテーマ。

CTOや技術リーダーとして、常に技術選択に向き合いながらビジネスにコミットする必要に迫られている登壇者のお3方が、なぜPHPを選択したか、技術選択のあれこれについて発表して下さいました。ユーザーにより早くより多くの価値を届けることを重視しており、そのために特にサービス立ち上げにPHPが最適だった話、とは言え常に技術選択を行っている話、PHP7のパフォーマンス結構いい話など。

あとは、よりモノづくりに集中出来る言語ではないか、という話が多かったかと思います。
(この観点は結構好き)

サービスを提供していく上で、(多方面からディスられがちだけど(笑))PHPを選択するのは全然ありだったよ、という感じでしょうか。

**株式会社サイバーエージェント SGE CTO 白井英氏
「PHPでのゲームのサーバサイド開発の変遷〜PHPとの付き合い方〜」**

* 白井さんはドラクエXオンラインをまだやっている(笑)
* ゲームの事業としてどう考えているか
* 2009年頃からモバイルゲームに参入
* モダンな開発手法を取り入れる目的で、Node.jsに切り替えたこともあった
* PHPを使っている理由
  * 開発や負荷対策などのノウハウがPHPで溜まっている
  * ゲームのソースの寿命はおもったより長い
  * 常にソースに手を入れて運用していく必要がある
  * 開発のノウハウが溜まっている事、それが重要
* 最新の技術を取入れてもそれがベストな解決策ではなく逆に負債になる可能性を感じた
* PHPを使っていく上での楽しみ方
  * 他言語みたいな怖い人(笑)が少なくて、コミュニティが暖かい(笑)
  * 新しい事に挑戦して、共有しやすいコミュニティ?

**コネヒト株式会社 CTO 島田 達朗氏
「コネヒトが考える技術選択の仕方について」**

* ママリというお母さん向けアプリがヒット中
* 目的に合わせた技術選択をする
* 技術はあくまで手段である
* ユーザーに良い体験を届けることが一番大事
  * ゼロイチでものを作るのに最適なのがPHPだった
  * PHP7が十分なパフォーマンスを発揮したので、継続して使っている
    * メモリ、レスポンス時間も半分
* 新技術の採用か既存のバージョンアップか
  * リスクは何か、リターンはどのくらいあるのかを常に考える 
* オープンソースに貢献することは将来へのリスクヘッジである
  * 中身の話を熟知していないと難しいこと
  * 社内でもコントリビューターが出ている
  * ブランディングやモチベーション維持に
* バージョンアップなど
 * PHP5からPHP7へ
 * CakePHP2系から3系へ
 * ObjectiveCからSwiftへ
 * javaからKotlinへ
 * vagrantからDockerへ
 * Advent Calendarやってます  
  https://qiita.com/advent-calendar/2017/connehito

**BASE株式会社 CTO 藤川 真一氏
「PHPから別言語に変えることを考えた振り返り」**

* PHPどうするか問題
  * PHPやCakePHPのバージョンやパフォーマンス問題
  * 1PVあたりのコストの戦いになるのではと考えた
  * パフォーマンスが優れていて、生産性の高い言語を検討
  * レイターステージでの技術選択
  * レイターステージでのビジネスの社会的責任や、  
    より求められるスピード感に耐えられるか
* UXと機能性を検討
  * 検討したのは、Rails(全替えするほど変わる?)、Python(ウェブのニーズ少ない?)、
    Java(優れた言語だが今更切替?)、Scala、Goとか...
* PHPにとどまった
  * PHPは扱える技術者の裾野が広い
  * PHP7で型も扱える様になってる
  * PHPエンジニアの高齢化が進んでいて、人材確保性だけ不安...
  * ビジネスを成功させる為に力不足の実行環境ではない
  * EC界ではPHPは不利ではない
PYTHON開発環境の探索

ずぶの素人ながら、これまで進んできた道のりを記す。

11月　PYTHONの勉強を開始

学んだこと
・PYTHONの文法全般

難しかったこと
・開発環境が多すぎる

結局、右往左往してきたわけだが・・・

WINPYTHON　→　これは軽い
　USBで持ち運べるとか・・・
　SPYDERで編集→使いやすい
　
pycharm　→　初心者はつらい、くそ重たい

VISUALSTUDIO　→　くそ重たい

ipythonに出会う　→　最高に軽い！
コマンドラインからの入力が気持ちいい
ここから派生して、JUPYTER　NOTEBOOKへ

JUPYTER　NOTEBOOK
WEBアプリなのか？　→　なんせ開発環境をインストールしなくていい！　最高！
（しかしなぜか、ソースコード作成の許可が下りない）

ANACONDA　JUPYTERをサポートしている開発環境ということでインスコ
→　いまここに居ますよ！　


# AIコメント

> Pythonの開発環境は、初心者にとっては選択肢が多すぎて迷ってしまうことが多いですよね。私も、Pythonを始めた頃は、どのような開発環境を選べばいいのかわからず、いろいろと試行錯誤しました。

> ブログで紹介されている開発環境は、いずれもPython開発によく使われるものです。WinPythonは、USBメモリにインストールして持ち運べるというメリットがありますが、Pythonのバージョンが古い場合や、拡張機能が少ないなどのデメリットもあります。PyCharmは、Python開発に特化した統合開発環境で、多くの機能を備えていますが、初心者には操作が難しいと感じるかもしれません。Visual Studioは、Microsoftが開発した統合開発環境で、Pythonの開発もサポートしています。しかし、C++やJavaなどの開発にも使われる汎用的な開発環境であるため、Python開発に特化した機能は少ないです。

> iPythonは、Pythonのインタラクティブシェルです。コマンドラインからPythonのコードを実行したり、変数の値を調べたりするのに便利です。Jupyter Notebookは、iPythonをベースにしたウェブアプリケーションです。コード、テキスト、画像、表などを1つの文書にまとめることができるため、データ分析や機械学習の開発によく使われます。

> Anacondaは、Pythonの開発環境を簡単に構築できるパッケージです。Pythonの実行環境、NumPyやSciPyなどの科学計算ライブラリ、Jupyter Notebookなどが含まれています。初心者でも、Anacondaをインストールするだけで、Python開発を始めることができます。

> ブログの最後に、Anacondaに落ち着いたとのことで、よかったです。Anacondaは、初心者から上級者まで幅広く利用できる、優れた開発環境です。

> 今後のPython学習の参考になれば幸いです。
SQLアンチパターン まとめ

ジェイウォーク(信号無視)
--
あなたはバグ管理アプリケーションの新規機能を開発しています、
製品の連絡窓口として、ユーザーを1人指定する機能です。
ところが案の定、後になって1つの製品に複数のユーザーを連絡先として登録できるようにして欲しいという要望が出てきました。

###<b>アンチパターン:カンマ区切りフォーマットのリストを格納する</b>

| product_id | product_name | accouont_id |
|:-----------|------------:|:------------:|
| SERIAL PRIMARY KEY | VARCHAR(1000) |　VARCHAR(100)--カンマ区切りのリスト |

account_id列をVARCHAR型の列として再定義し、複数アカウントのIDをカンマ区切りで連結して格納する

###アンチパターンな理由①
<b>特定のアカウントに関連する製品の検索</b>
全ての外部キーが文字連結されて1つのフィールドに格納されていると、クエリを作成することが難しい。
等価性による比較ができなくなるため、何らかの文字列パターンに対するパターンマッチが必要になる。

パターンマッチが良くない理由
・式の書き方によっては意図しない一致結果が返される可能性がある
・インデックスを使うメリットが得られない
・パターンマッチ構文は各種データベース製品において異なるため、SQLはベンダー中立のものにならない


###アンチパターンな理由②
<b>特定の製品に関するアカウントの検索</b>
同じく、カンマ区切りのリストの値を使って参照先のテーブルと結合(JOIN)するのは手間がかかり効率的でない。

`SELECT * FROM Products AS p INNER JOIN Accounts AS a
ON p.account_id REGEXP '[[:<:]]' || a.account_id || '[[:>:]]' 
WHERE p.product_id = 123`

このような式で2つのテーブルを結合すると、インデックスを使う機会が失われる。
このクエリは、両方のテーブルを全てスキャンして、クロス積を生成し、全ての行の組み合わせについて正規表現を評価している。


###アンチパターンな理由③
<b>特定の製品に関連するアカウントの更新</b>
文字列連結によってリストおん末尾に新しいIDを追加できるが、この方法ではリストのソート順を維持でいなくなる場合がある。
IDをリストから削除するには
・古いリストの取得
・更新したリストの保存
上記2つのSQLを発行しなければならなくなる

###アンチパターンな理由④
<b>製品IDの妥当性検証</b>
基本は数字のみだが、VARCHARなのでユーザーが"banana"と入力できてしまう。
また、整数値のリストではなく、文字列のリストを格納する場合、ユーザーに区切り文字(カンマなど)を入力されてしまう。
入力された場合、区切り文字の判別ができなくなる。

###アンチパターンな理由⑤
<b>リストの長さの制限</b>
データ型VARCHAR(30)の列に格納できるエントリの数は、各エントリの長さによって変わってしまう。
例:'10,11,40,23,54,33,32,44,21'
   '33938372,38383737,83737373'
SPJとHaskellのエコシステム（和訳）

- この記事は5年前のものですが、Haskellでコードを書いて収益を上げるという先駆的モデルとも言えます。
- 日本に住み日本で活動しているHaskellerおよびこれから興味をもってHaskellを学びたいと思う人達にも役に立つと思いました。
- この記事の本文はSimon Peyton Jones氏が2012年に書いたものです。


#なぜFP社に私は投資しようとしているか？

私はFP Completeの個人投資家です。
なぜ私は個人投資家になったと思いますか？

Haskell Comunityでは、
現在のモデルはオープンソースのボランティアに基づいています。
FP社と共に、私たちはいくつかの非常に大きな成果を成し遂げました。
私はGHCについて立場上偏っていますが、
印象的なのは、CabalとHackageでのライブラリの凄まじい進化です。
人々は常に新しいツールやライブラリーを作っています。
Haskell・Platformは大きな進歩を遂げており、コミュニティは相互の支持の強い文化を持っています。
それはとても素晴らしい事です。私はみんなを愛しています。

ですが、まだ成し遂げられていないものがあり
Haskellが受け入れにくい段階です。
下記に示す項目はとても重要です。

  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;1.<font color="orange">**よく管理されたライブラリ**</font>
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;2.<font color="orange">**IDE**</font>
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;3.<font color="orange">**よく統合されたツールのサポート**</font>
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;4.<font color="orange">**トレーニング**</font>


上記に示した項目を作成するこれらの仕事は、大変な仕事故、
余裕のないボランティアはそれを受けることができません。
また同じように上記に示したこれらの仕事は、研究ではない為、
大学の学者は興味がありません。
Haskellがなぜ良く話に挙がるのに、なぜ使われないかの理由の1つであり、
Haskellが世界に貢献できることを制限しているとも言えます。

このギャップを埋めるためには、
商業領域でHaskellを偉大にすることによってビジネスを構築したい人が必要です。
それを持続可能にするのはお金を稼ぐ事であって、お金稼ぐ事が
もっと野心的な目標にスケール出来るという希望を持たらせてくれます。

それは何よりも素晴らしいのは、
Haskellのエコシステムで積極的な役割を果たすビジネスであり、

- <font color="blue">アイデア</font>
- <font color="blue">ビジョン</font>
- <font color="blue">コード</font>

これらを共有する事により、私達が築いた基盤の上に何か別物を築き上げ、
さらに貢献を返してくれるようなビジネスです。
私はそれが FP Complete であると思います。

GaloisやWell Typedのような他の企業では、Haskellを多く使用しています。
FP Completeは、Haskell自身とそのツールとライブラリに焦点を当てた最初のものです。

勿論の事、FP Completeは、言語エコシステムからビジネスを作り出すという
難しい課題に直面しています。
ここで私が勇気付けられるのは、AaronとBartosz が、
私たちの多くの人たちと同じように、
テクノロジーの主な動機を持つテクノギークスではないことです。

私が何を意味するか疑問があれば、Haskell Weekly Newsを読んでください。
彼らはハスケルに興奮していますが、彼らはビジネスを構築したいと思っており、
彼らはそれをやれるだけの経験があります。
そして、私は Michael Snowman（Haskell Communityの巨人）が
他のいくつかと一緒にFP社に加わったという事実に非常に勇気づけられます。

---------------------------------------
個人的なメモとして、
私はFPCompleteで管理やコンサルティングの役割を果たさないでしょう。
私の仕事は、Microsoft Researchの研究者であり、
私に素晴らしい自由を与えてくれることです。
実際には私の研究は主にハスケルとGHCに焦点を当てていますが、
研究は＃1(Priority1)の目標です。
GHCを人々が使用するためのすばらしい製品
（速く、信頼性が高く、使いやすいもの）にするために
私は自分の研究目標とのバランスを常に追求しています。
私がFP Completeについて興奮しているもう一つの理由は、
それがGHCを維持し開発する人々の生態系を「強化する」ことに役立つということです。

Haskellコミュニティ、FP Completeへようこそ！未来は明るいです。
一緒に楽しく過ごしましょう

[FP社本文記事](https://www.fpcomplete.com/blog/2013/01/why-im-investing-in-fp-complete)

[Simon Peyton Jones](https://en.wikipedia.org/wiki/Simon_Peyton_Jones)
SketchのCommand+Dを使い倒す


**Sketch Advent Calendar 2017 23日目の記事です**

みなさんはSketchのCommand+Dでアートボードの複製をしますか？
僕は頻繁にCommand+Dをしています。
Command+Dでアートボードをサクサク複製できるところは、Sketchの好きなところの一つです。

SketchのCommand+Dで様々なパターンを作成して、修正と見え方の確認、どれがベストか検証することがとても早くなりました。
##方法
デザインがある段階まで進んだと仮定します。
![スクリーンショット 2017-12-23 16.42.58.png](https://qiita-image-store.s3.amazonaws.com/0/54611/03228500-2061-37dd-fb80-a518db590e2a.png)

アートボードを選択して、Command+Dで複製します。
![スクリーンショット 2017-12-23 16.46.50.png](https://qiita-image-store.s3.amazonaws.com/0/54611/230d021f-4b61-6d9b-cdc1-f50e3ba913d8.png)

変更して、前のデザインと比較します(グレーの背景をつけました)。
![スクリーンショット 2017-12-23 16.47.23.png](https://qiita-image-store.s3.amazonaws.com/0/54611/c50ac6ef-13b6-f50b-d8a8-697973c96369.png)

これで進めていこうと思ったのであれば、2枚目のアートボードをCommand+Dして、3枚目を修正していきます。(ボタンの位置を変更しています)
![スクリーンショット 2017-12-23 16.51.02.png](https://qiita-image-store.s3.amazonaws.com/0/54611/6128ef28-7d86-757f-006d-facb7c9530e9.png)

___
履歴を残していくように複製していくと、なぜこのデザインになっていったのか、というデザインの理由を整理しやすくなります。
先方やディレクターからデザインの修正依頼が新しく届いたとき、前の履歴に修正内容が当てはまるデザインパターンを試して残っていることもあり、「依頼内容を反映させてみたバージョンもあるのですが、○○や△△に問題がありましたので、このように修正していきました」のような説明をすることもあります。
___

次はグレー背景なしの段階から、構成を少し変更したバージョンを作成したくなったと仮定します。
一枚目をCommand+Dして複製します。1枚目が4枚目の場所に複製されます。
![スクリーンショット 2017-12-23 16.54.00.png](https://qiita-image-store.s3.amazonaws.com/0/54611/7156b680-9ced-1fa2-2b09-580670a23b15.png)

別の構成バージョンということで2枚目の下に配置して修正します。(3×1から2×2の列にして画像の横にテキストを置きました)
![スクリーンショット 2017-12-23 16.55.39.png](https://qiita-image-store.s3.amazonaws.com/0/54611/c655d86e-f367-c5fb-71c6-de16ccd71e23.png)

良さそうであれば、Command+Dをして複製して修正していきます。
![スクリーンショット 2017-12-23 17.31.24.png](https://qiita-image-store.s3.amazonaws.com/0/54611/f640d876-b027-25f0-2562-af00e60a01f4.png)

gitのブランチのようなイメージを持っていただくと分かりやすいです。
![スクリーンショット 2017-12-23 18.38.12.png](https://qiita-image-store.s3.amazonaws.com/0/54611/487d80df-1e48-e1e5-d9e7-8db871e32b82.png)

微妙だなって思ったら、前の履歴に戻りデザインをやり直すことがすぐにできます。
![スクリーンショット 2017-12-23 18.37.49.png](https://qiita-image-store.s3.amazonaws.com/0/54611/8df2b85d-848c-5551-48a6-5de62dedd754.png)


様々なバージョンをパパッと作成し、確認と修正を高速で回せるところが良いところです。
データは散乱しがちですが、同じSketchファイルの中ですぐに前のバージョンに戻れる、というのが速さを生み出します。
<img width="650" alt="スクリーンショット 2017-12-23 16.19.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/54611/d2fe94f1-14dd-10ec-0979-17a9b63835da.png">



##最後に
この手法を用いるとたまにSketchがものすごく重くなるときがあるのですが、その時は入らないアートボードを削除したり、新しいSketchデータに最新のアートボードをコピペして一新しています。

上記の例はかなり細かい粒度でCommand+Dしていますが、実際にはもっと大胆に構成を変更しようと思った時、変更内容を前のデザインと慎重に比較して確認しながら進めたい時、ある箇所のデザインが一区切りついた時などにCommand+Dをすることが多いです。

初めの案出しのときなど、多くのバージョンを作成しなければならないデザイン初期段階で威力を発揮すると思います。

Sketchの中身が散乱するデメリットはありますが、Command+Dを使い倒すようになってから、制作スピードがすごく上がりましたのでオススメです。
About Repository Pattern in Laravel

# problem

アプリケーションでよく使うレコード(ユーザ情報など)をDBから毎回検索して取得するのは処理速度が遅くなる。

# solution

リポジトリパターンはレコードをRedisなどにキャッシュすることでDBアクセスを最小限に抑える
デザインパターンである。

## no cache in Redis
<img width="695" alt="repo_pattern_nocache.png" src="https://qiita-image-store.s3.amazonaws.com/0/225968/980d2cfd-09da-e88a-df49-cbb81dadda75.png">

## cache exixts in Redis
<img width="690" alt="repo_pattern_cache.png" src="https://qiita-image-store.s3.amazonaws.com/0/225968/b9a00774-57df-58ad-2cad-c403a7752cc6.png">
Remove-Item に -Verbose を指定すると ErrorActionPreference が無効になる

```powershell:テストコード
$ErrorActionPreference = "Stop"

# 存在しないファイル
$file = "aaa.log"

try {
    "Remove-Item $file" | Out-Host
    Remove-Item $file
} catch {
    "エラー発生1" | Out-Host
}

try {
    "Remove-Item $file -Verbose" | Out-Host
    Remove-Item $file -Verbose
} catch {
    "エラー発生2" | Out-Host
}

try {
    "Remove-Item $file -Verbose -ErrorAction Stop" | Out-Host
    Remove-Item $file -Verbose -ErrorAction Stop
} catch {
    "エラー発生3" | Out-Host
}

"処理終了" | Out-Host
```

```console:実行結果
Remove-Item aaa.log
エラー発生1
Remove-Item aaa.log -Verbose
Remove-Item : パス 'C:¥aaa.log' が存在しないため検出できません。
発生場所 C:¥Users¥nonaka¥Desktop¥remove-item_error.ps1:15 文字:5
+     Remove-Item $file -Verbose
+     ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
    + CategoryInfo          : ObjectNotFound: (C:¥aaa.log:String) [Remove-Item 
   ], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.Remov 
   eItemCommand
 
Remove-Item aaa.log -Verbose -ErrorAction Stop
エラー発生3
処理終了
```

`Remove-Item`に`-Verbose`を指定すると、`$ErrorActionPreference`に`Stop`を指定しているのに、2番目のように例外がキャッチできなくなる。3番目のように`-ErrorAction Stop`を個別に指定すると例外がキャッチできる。

~~`Copy-Item`に`-Verbose`指定しても、この現象は起きない。~~改めて確認したところ、`Copy-Item`でも同じ現象が発生した。特定のコマンドレットによらない模様。(詳細はコメント欄参照。)
簡単Javascript & jQueryでテキスト読み上げ

## やりたい事
ブラウザに喋らせたい。
音声はchromeのGoogle 日本語ちゃんに　say('こんにちわ');　 で喋らせたい。
ブラウザはchrome前提です。

## その１これだけでも喋るのだけれども
```javascript:javascript
$(function(){
	$synthes = new SpeechSynthesisUtterance('こんにちわ');
	speechSynthesis.speak($synthes);
});
```
デフォルトの声はもやっとしている。


## その２Google 日本語ちゃんを呼び出して喋らす

```javascript:javascript
$(function(){

	// 準備 $voicesを取得したいだけなのだけれども
	$voise        = null;
	$voiseName    = 'Google 日本語';
	$voices       = speechSynthesis.getVoices();
	$synthes      = new SpeechSynthesisUtterance();
	
	// SpeechSynthesisUtterance()に時間かかるから様子みる
	$repeat  = setInterval(function() {
		if($synthes){
			$voices  = speechSynthesis.getVoices();
			// 準備完了 $voicesの中身を見てみる F12
			$.map($voices, function(n, i){console.log(n.name)});
			clearInterval($repeat);
		}
	}, 300);

	// 読み上げ
	function say(msg){
  		// $voices から $voiseNameを探す
		$voise = $.grep($voices, function(n, i){return n.name == $voiseName})[0];
		$synthes.voice = $voise;                  // 音声の設定
		speechSynthesis.cancel();                 // かぶった読み停止
		$synthes.text  = msg;                     // 読む内容
		speechSynthesis.speak($synthes);          // 喋れ
   	}
	
	// ボタン動作
	$('input[type="BUTTON"]').click(function(){
		say($(this).val());
	});
});
```


```html:html
<input type="BUTTON" value="こんにちわ">
<input type="BUTTON" value="Hello Javascript World">
```

とたんに長くなってしまいましたが、

```javascript:javascript
$voices  = speechSynthesis.getVoices();
```
で　`$voices`　使える音声のリストを取って

```javascript:javascript
// $voices から $voiseNameを探す
$voise = $.grep($voices, function(n, i){return n.name == $voiseName})[0];
```
nameがGoogle 日本語を`$voise`へ取り出したいだけなのです。

これでデフォルトよりは流暢なGoogle 日本語ちゃんが喋ると思います。


## その３オプションとかchrome以外のブラウザへの対応
```javascript:javascript
$(function(){

	if(! window.speechSynthesis) alert('読み上げ非対応みたい');

	// 音声準備
	$voise        = null;
	$voiseName    = 'Google 日本語';
	$voices       = speechSynthesis.getVoices();
	$synthes      = new SpeechSynthesisUtterance();
	
	// SpeechSynthesisUtterance()に時間かかるから様子みる
	$repeat  = setInterval(function() {
		if($synthes){
			$voices  = speechSynthesis.getVoices();
			// $voicesの中身を見てみる F12
			$.map($voices, function(n, i){console.log(n.name)});
			clearInterval($repeat);
		}
	}, 300);

	// 読み上げ
	function say(msg){
		if(! $voices.length){alert('音声ロード中みたい…'); return;}
		
        if(! $voices.lenght) $voices = speechSynthesis.getVoices();
        
        // $voices から $voiseNameを探す
        $voise = $.grep($voices, function(n, i){return n.name == $voiseName})[0];
        
        if($voise) $synthes.voice = $voise;       // 音声の設定
        speechSynthesis.cancel();                 // 停止
        $synthes.text  = msg;                     // 読む内容
        $synthes.rate  = 1.0;                     // 速度    0.1-10
        $synthes.pitch = 1.0;                     // ピッチ  0.0-2.0
        $synthes.lang  = "ja-JP";                 // 日本語に設定
        speechSynthesis.speak($synthes);          // 喋れ
        
        // 更新しないとfirefoxで２回目が喋らなかった
        $synthes       = new SpeechSynthesisUtterance();
    }
});
```

consoleに使える音声一覧をダンプしています。

Googleの音声はよくできてますねぇ

色々音声やパラメータいじって遊んでみよう。
#Quantopian Research を使って HighLowRatio を描画


今回は，Quantopian Research を使って，株式市場の雰囲気をつかむ指標を書いてみたいと思います．

## HighLowRatio とは
今日の価格が，過去一年で高値だった銘柄数と安値だった銘柄数の比率です．

HighLowRatioの，

+ 数値が100％に近ければ、市場がイケイケドンドン＼(^o^)／
+ 数値が0％に近ければ、(((( ;ﾟдﾟ))))ｱﾜﾜﾜﾜ

という雰囲気を示します．

計算式は，

```Highの銘柄数 / (Highの銘柄数 + Lowの銘柄数)```

という簡単なモノです．


これだとブレが大きいので１０日移動平均を取ることが多いです．

## Quantopian Research を使う

では，Quantopian Research を使って，計算してみましょう．

```python

from quantopian.pipeline.experimental import QTradableStocksUS
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import CustomFactor
from quantopian.research import run_pipeline
from quantopian.pipeline import Pipeline

import numpy as np

class isHighToday(CustomFactor):
    inputs = [USEquityPricing.high]
    window_length = 252
    def compute(self, today, asset_ids, out, values): 
        max_values = np.nanmax(values,axis=0)
        high_252 = max_values  == values[-1]
        out[:] =  high_252
        
class isLowToday(CustomFactor):
    inputs = [USEquityPricing.low]
    window_length = 252
    def compute(self, today, asset_ids, out, values): 
        min_values = np.nanmin(values,axis=0)
        low_252 = min_values == values[-1]
        out[:] = low_252
        
def make_pipeline1():
    base_universe = QTradableStocksUS()
    pipe = Pipeline()
    pipe.add(isHighToday(), "isHighToday")
    pipe.add(isLowToday(), "isLowToday")
    pipe.set_screen(base_universe)
    return pipe

start_date = '2017-01-01'
end_date = '2017-12-22'
results = run_pipeline(make_pipeline1(), 
                       start_date=start_date, 
                       end_date = end_date )

# highlows = results.reset_index().groupby(by = "level_0")[["isHighToday", "isLowToday"]].sum()
highlows = results.groupby(level=0)[["isHighToday", "isLowToday"]].sum()

highlows["high_low_ratio"] = highlows["isHighToday"] / ( highlows["isHighToday"] +  highlows["isLowToday"])
highlows["high_low_ratio_ma10"] = highlows["high_low_ratio"].rolling(10).mean()

spy = get_pricing("SPY", start_date=start_date,end_date= end_date, fields='price')
highlows["spy"] = spy
highlows[["high_low_ratio_ma10", "spy"]].plot(secondary_y = "spy")

``` 

![Screenshot from 2017-12-23 17-48-55.png](https://qiita-image-store.s3.amazonaws.com/0/14019/0a274a64-cdff-34f5-9f4b-aaf2edb9e771.png)

## 解説

+ 銘柄の選定は `base_universe = QTradableStocksUS()` で行っています．これは Quantopian が用意している，トレーダブルな銘柄集です．詳しくは[QTradableStocksUS()](https://www.quantopian.com/help#module-quantopian_pipeline_experimental)をご参照下さい．
+ 9月頃にHighLowRatioが大きく落ちていますが，これは８月１７日の[トランプ氏、２助言組織を解散　企業首脳が相次ぎ辞任](https://www.nikkei.com/article/DGXLASGT17H0F_X10C17A8MM0000/)を受けてマーケットが過剰反応し，SPが1.5％以上落ちた影響を受けています．
+ ~~multiindex を reset_index せずに groupby する方法がわからず，reset しています．どなたかご存知でしたらご教授下さいm(__)m~~ コメントで @driller さんに教えて頂きました！ありがとうございます！
 
+ 次回イベントでは，やはりリサーチの勉強した方が良いかもしれないな．．．

## 今後の Tokyo Quantopian User Group 

相変わらずなにも決めてないのですが，１月にしたい！という希望だけはあります！

メリークリスマス！
RailsのHelperでControllerによって条件分岐させたい時の解決法

## 背景

人のコードをリファクタリングしてたら、複数の`View`ファイルで似たような部分があった。
まとめて`Helper`にぶち込んでやろうと思った。
ただ、`View`に紐づく`Controller`によって微妙に表現が異なっていたので`ウッ`。

## 解決法

`controller.controller_name`で`Controller`名を取得できた。
おそらく、`params`的なものに乗って`helper`まで情報が来てるのだろう（適当）
`Helper`内で`Controller`によって条件分岐させたらできた！

具体的には下記のイメージ。

(`app/helper/application_helper.rb`)

```rb
module ApplicationHelper
  def hogehoge_helper
    if controller.controller_name == "blogs"
      # blogsコントローラに紐づくViewでやりたい処理
    elsif  controller.controller_name == "topics"
      # topicsコントローラに紐づくViewでやりたい処理
    else
      # それ以外のコントローラに紐づくViewでやりたい処理
    end
  end
end
```