読者です 読者をやめる 読者になる 読者になる

Docker for Mac から PHPをリモートデバッグする

以下を参考に設定した。

forums.docker.com


Macの設定

Macでターミナルを立ち上げて次のコマンドを入力

sudo ifconfig lo0 alias 10.254.254.254
Dockerfileの例(抜粋)
# PHP
RUN  echo "[Xdebug]" >> /etc/php.ini && \
    echo "zend_extension=/path/to/xdebug.so" >> /etc/php.ini && \
    echo 'xdebug.idekey = "PHPSTORM"' >> /etc/php.ini && \
    echo "xdebug.max_nesting_level=1000" >> /etc/php.ini && \
    echo "xdebug.remote_autostart=1" >> /etc/php.ini && \
    echo "xdebug.remote_host=10.254.254.254" >> /etc/php.ini && \
    echo "xdebug.remote_enable=1" >> /etc/php.ini && \
    echo "xdebug.remote_handler=dbgp" >> /etc/php.ini && \
    echo "xdebug.remote_port=49190" >> /etc/php.ini && \
    echo "xdebug.profiler_enable=1" >> /etc/php.ini && \
    echo "xdebug.profiler_output_dir=/tmp" >> /etc/php.ini && \
    echo "xdebug.remote_log=/tmp/xdebug.log" >>  /etc/php.ini 

これをビルドするとDocker上の /etc/php.ini は以下のようになる

[Xdebug]
zend_extension=/path/to/xdebug.so
xdebug.idekey = "PHPSTORM"
xdebug.max_nesting_level=1000
xdebug.remote_autostart=1
xdebug.remote_host=10.254.254.254
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_port=49190
xdebug.profiler_enable=1
xdebug.profiler_output_dir=/tmp
xdebug.remote_log=/tmp/xdebug.log
PhpStormの設定

あとはここを参考にしたらいけた
qiita.com


ちょっとトリッキーすぎる・・・。

sbt console で scalacOptions を指定する

これでOK

% sbt
> set scalacOptions ++=Seq("-Xprint:parser")
[info] Defining *:scalacOptions
[info] The new value will be used by compile:scalacOptions
[info] Reapplying settings...
[info] Set current project
> set scalacOptions ++=Seq("-Xlog-implicit-conversions")
[info] Defining *:scalacOptions
[info] The new value will be used by compile:scalacOptions
[info] Reapplying settings...
[info] Set current project
> console

...

scala> for {
     |   x <- List(1,2,3)
     |   y <- Some(1)
     | } yield {
     |   x + y
     | }
[[syntax trees at end of                    parser]] // <console>
package $line3 {
  object $read extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>() = {
        super.<init>();
        ()
      };
      object $iw extends scala.AnyRef {
        def <init>() = {
          super.<init>();
          ()
        };
        val res0 = List(1, 2, 3).flatMap(((x) => Some(1).map(((y) => x.$plus(y)))))
      }
    }
  }
}

<console>:10: inferred view from Option[Int] to scala.collection.GenTraversableOnce[?] = scala.this.Option.option2Iterable[Int]:(xo: Option[Int])Iterable[Int]
                y <- Some(1)
                  ^
[[syntax trees at end of                    parser]] // <console>
package $line3 {
  object $eval extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    lazy val $result = $line3.$read.$iw.$iw.res0;
    val $print: String = {
      $read.$iw.$iw;
      "".$plus("res0: List[Int] = ").$plus(scala.runtime.ScalaRunTime.replStringOf($line3.$read.$iw.$iw.res0, 1000))
    }
  }
}

res0: List[Int] = List(2, 3, 4)

株式会社プラグラムを退職しました

私事で恐縮ですが、2015年6月30日をもって、株式会社プラグラムを退職しました。株式会社プラグラムには、会社ができるジェネフィックスデザインという会社の頃からフリーランスとして、プラグラムという会社ができてからは社員として関わってきました。


約4年と半年ぐらいですが、受託から始まりスマレジという自社サービスを開始し、受託をやめて自社サービスひとつに絞ったり、最近ではアメリカ進出したりと短いなりにとても濃い時間を過ごせました。
関わっていただいた皆さまには大変お世話になり、ありがとうございました。


スマレジでは主に業務のコアになる取引周りやWebAPIなど担当させてもらい、IT業界とは違う小売業の方々や飲食店の方々がどのように業務を行っているかなど普段行ってるIT勉強会とはまた違った意味でとても勉強になりました。



明日からはフリーランスのITエンジニアとして働く予定です。
プラグラムとも引き続き一緒に仕事をしていく予定ですが、長期常駐でなければたぶん大丈夫なので、お気軽に仕事を依頼ください。(7月はすでに仕事で埋まってますので、8月以降が有難いです)

CasperJS歴3時間でハマったこと

javascript casperjs

はまったことメモ

casper.on('http.status.404', function(resource) {
    this.echo('wait, this url is 404: ' + resource.url);
});
  • HTMLページを読み込んだときにJSのシンタックスエラーがあるかどうか知りたい(ほかのエラーも)
casper.on( 'page.error', function (msg, trace) {
    this.echo( 'Error: ' + msg, 'ERROR' );
});
  • 指定したForm内にどんなものがあるか知りたい
var utils = require('utils');
utils.dump(this.getFormValues('#form'));
  • SSLのページでもCasperを動かしたい
casperjs test --ssl-protocol=any sample.js

自分がプロジェクトでKnockoutを使うときに気をつけていること

れはKnockoutJSアドベントカレンダー24日目の記事です。


KnockoutJS Advent Calendar 2014 - Qiita


今日はネタも尽きたので自分がプロジェクトでKnockoutを使うときに気をつけていることをグダグダ書こうと思います。

1. ViewModelやModelにjQueryなどのDOM操作をするライブラリを使用しない

これは責務の問題とテストしやすくするためです。

KnockoutJSでは MVVM (Model-View-View Model) というデザインパターンを適用することでUIをシンプルに記述できるようにしています。


この "Model", "View", "View Model" という役割ですが、それぞれ


Model: データ自体を扱う

View: ユーザインターフェースを扱う

ViewModel: UIバインディングを行ったりモデルからデータ取得したり更新したりする


といったような役割分担があります。


例えばHTMLは基本的にViewレイヤー。あるデータに特化したロジックやサーバとの通信を用いた永続化処理などはModel(JS)に書きます。ViewModelはJSです。



ただ、たまにバインディング時にjQueryでDOM指定して何かやりたい場合があります。
そういう場合は自分はカスタムバインディングを使ったりしますが、基本的には使わないよう気をつけます。


こうすることで ViewModel はほぼPOJO?(Plain Old JavaScript Object)で書くことができます。
ただModelでサーバと通信をしたりします。その場合は jquery-mockjax を使ったりモックで代用します。



テストをセットアップについては以前ブログを書いたので参考にしてみるといいかもしれません。


Knockout.jsとKarmaで簡単TDD開発 - 418 | I'm a teapot



2. データを引数にModelを作成するときはコンバータを挟む

サーバからデータを取得しModelを作成するときですが、場合により形が違うデータ(JSオブジェクト)がくる場合があります。


例えば、以下のような業務システム(発注業務)を考えてみます。

  • 初期データ取得時、サーバから商品IDに紐付く商品情報を取得しModelを作成して発注明細に追加する
  • 商品検索ボタンを押すと検索ダイアログが開く。そのダイアログから商品を選択してModelを作成して発注明細に追加する
  • 商品追加ボタンを押すと空の商品情報入力フォームが発注明細に追加される。

この場合、同じモデル(商品情報)を作る場合でも場合によりModelを作成するときの引数に渡されるJSオブジェクトのデータ構造が変わる場合があります。


こういった場合、都度Model内で変換してもいいのですが、別途以下のようなコンバータみたいなのを作ってやると管理が楽になります。

var converter = {
        // 発注情報に登録されている商品情報を発注明細に追加したとき
	fromServer: function(item){
		return {
			productCode: item.order.product_code
			productName: item.order.product_name
                };
	},
        // 検索ダイアログから商品情報を発注明細に追加したとき
    	fromSearchDialog: function(item){
		return {
			productCode: item.productCode
			productName: item.productName
		};
	},
        // 空の商品情報入力フォームが発注明細に追加されたとき
	createEmpty: function(){
		return {
			productCode: null,
			productName: null
		};
	}

};


例えば初期データ取得時、サーバから商品IDに紐付く商品情報を発注明細に追加する場合は、
サーバから取得した商品情報のJSオブジェクトに converter.fromServer() を使います。

model.load("/product/1", {},
	function(result){
		var product = converter.fromServer(result);
		self.orderDetals.push(product);
	}
);


同様に検索ダイアログから商品情報を発注明細に追加する場合は以下のようにします。

function selectProduct(selectedProduct) {
	var product = converter.fromSearchDialog(selectedProduct);
	self.orderDetals.push(product);
}

上記はあくまでサンプルですがイメージとしてはこんな感じです。
そろそろ本格的にグダグダしてきたのでこれぐらいで・・・。


明日はいよいよラスト! @sukobuto さんの「KO + TypeScript + Cordova でハイブリッドアプリ開発」です!よろしくお願いします!

しょぼちむをExcel方眼紙で表現してみる

これはしょぼちむアドベントカレンダー23日目の記事です。


しょぼちむ Advent Calendar 2014 - Adventar


昨日は、ばふぁさんの「しょぼちむ!スクラムチームの外側の話をちょっと書いてみたよ!」でした!


今日は特にこれといって決めてないので、しょぼちむをExcel方眼紙にしようと思います。

以下の手順で行います。

  1. Twitterからしょぼちむのアイコンをダウンロードする
  2. 画像を適当に小さくする(リサイズ)
  3. 画像を2値化する
  4. 画像を 0 と 1 でマッピングして文字列を取り出す
  5. Excel方眼紙に貼付ける


以上です。


画像のリサイズおよび2値化には OpenCVを使います。
OpenCVのインストール(Mac)はこちらを参考にしました。

Mac - OS X に OpenCV を Homebrew で入れて python で動画入出力をする - Qiita


では早速ソースコードです。

まず vim を起動します。

$ vim syobochim.py
import cv2

img = cv2.imread('syobochim.jpg', cv2.IMREAD_GRAYSCALE)

# 2. 画像を適当に小さくする(リサイズ)
thumb = cv2.resize(img,(160, 128)) 

# 3. 画像を2値化する
thresh = 120
img_bin = cv2.threshold(thumb, thresh, 255, cv2.THRESH_BINARY)[1]

# 4. 画像を 0 と 1 でマッピングして文字列を取り出す
for y in range(0, 127):
  for x in range(0, 159):
    px = img_bin[y, x]
    if px != 0:
      print '1',
    else:
      print '0',
  print ''

そしてこれを
( ^ω^)
⊃ syobochim.py ⊂


こうして…
( ^ω^)
≡⊃⊂≡

$ python syobochim.py > syobochim.txt


こうじゃ
( ^ω^)
Excel方眼紙 ⊂
f:id:tan_go238:20141223054317p:plain





本当はここから Arduinoにシリアル通信で画像を送り、LCDディスプレイで表示しようと思ったんだけど、送信データ量が多くて送れませんでした。
バイナリデータで送ろうとしたけどpySerialでは文字列でしか送れないことと、Arduinoは128byteのread bufferしかないのが原因っぽい。多分頑張ればできるはず。
とりあえず時間があったら後でやろうかなと思うので上記ソースをちょっと修正したPythonソースコードを備忘録で残しておく。

※動いたので追記
Arduinoのバッファを消費するタイミングをうまくスリープで調整すればできた。
けどスリープのタイミングがなかなか難しいし遅い。
バッファサイズをみてやればいいような気がするけどこのへんの知識ないので難しい・・。

# convert image to 160 x 128 pixel resolution.
import array
import cv2
import serial
import time

# resize
img = cv2.imread('syobochim.jpg', cv2.IMREAD_GRAYSCALE)
thumb = cv2.resize(img,(160, 128))

# binary
thresh = 120
img_bin = cv2.threshold(thumb, thresh, 255, cv2.THRESH_BINARY)[1]

# serial
ser = serial.Serial()
ser.port = '/dev/tty.usbmodemfa131'
ser.baudrate = 9600

ser.open()
time.sleep(5)

for y in range(0, 128):
  data = ""
  for x in range(0, 160):
    px = img_bin[y, x]
    if px != 0:
      data += "1"
    else:
      data += "0"
  ret = ser.write(data)
  time.sleep(0.5)

time.sleep(1)
ser.close()
#include <SPI.h>
#include <SD.h>
#include <TFT.h>  // Arduino LCD library

// pin definition for the Uno
#define sd_cs  4
#define lcd_cs 10
#define dc     9
#define rst    8

TFT tft = TFT(lcd_cs, dc, rst);
int x,y = 0;
int rcv = 0;
  
void setup() {
  tft.begin();
  tft.background(0, 0, 0);
  Serial.begin(9600);
}

void loop() {
  while((rcv = Serial.available()) > 0){
    for(int i=0; i<rcv; i++) {
      int val = Serial.read();
      if (val == 48) {
        tft.drawPixel(x, y, 0x0000);
        x++;
      } else if(val == 49){
        tft.drawPixel(x, y, 0xFFFF); // 0xFFFF
        x++;
      }      
      if(x>=160) {
        x = 0;
        y++;
      } 
    }
  }  
}

f:id:tan_go238:20141227172325j:plain

KnockoutでHandlebarsを使ってみる

これはKnockoutJSアドベントカレンダー22日目の記事です。


KnockoutJS Advent Calendar 2014 - Qiita



Knockoutでは外部のテンプレートエンジンを組み込んで使うことができます。

組み込み方はソースコード内に記載してあります。

knockout/templateEngine.js at master · knockout/knockout · GitHub


要約(ちょっと後半の訳があやしい)

// 独自のテンプレートエンジンを作りたい場合は次のようにしてください。
//
// [1] ko.nativeTemplateEngineと同じようにこのクラスを継承します。
// [2] 'renderTemplateSource' をオーバーライドし、次のシグネチャのメソッドを実装します。
//
//        function (templateSource, bindingContext, options) {
//            // - templateSource.text() はテンプレートでレンダリングするテキストです
//            // - bindingContext.$data はテンプレートに渡すデータです
//            //   - 他にも bindingContext.$parent, bindingContext.$parents, bindingContext.$root がテンプレートで使えます
//            // - options は "data-bind: { template: options }" で与えられたプロパティにアクセスすることができます
//            // - templateDocument はテンプレートの documentオブジェクトです
//            //
//            // Return value: DOM要素の配列
//        }
//
// [3] 'createJavaScriptEvaluatorBlock' をオーバーライドし、 次のシグネチャのメソッドを実装します。
//
//        function (script) {
//            // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
//            //      'script' を評価して結果を出力します。
//            //     例えば、 jquery.tmpl テンプレートエンジンは 'someScript' を '${someScript} に変換します
//        }
//
//     This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
//     これはあなたがデータバインドの属性を任意のテンプレート変数が参照する場合にのみ必要です。
//     もしこれを許可したくない場合は 'allowTemplateRewriting' プロパティを false にします(ko.nativeTemplateEngineと同じように)
//     その場合は 'createJavaScriptEvaluatorBlock' をオーバーライドする必要はありません。


ko.templateSourcesあたりのソースコードに renderTemplateSource の引数の templateSource の詳しい内容が書かれています。


というわけで KnockoutJS から Handlebars を使ってみましょう。

公式ドキュメントの template バインディングの一番下にUnderscoreのサンプルがあるのでこれを真似てみます。

Knockout : The "template" binding


ソースはこんな感じ。

<div data-bind="foreach: people">
  <div data-bind="template: { name: 'person-template' }"></div>
  <hr>
</div>

<script type="text/html" id="person-template">
<table>
<tr>
  <th>Name</th>
  <td>{{name}}</td>
</tr>
<tr>
  <th>Gender</th>
  <td>{{gender}}</td>
</tr>
<tr>
  <th>Profile</th>
  <td>
  {{#each profiles}}
    <span>{{@index}} : {{{this}}}</span>
  {{/each}}
  </td>
</tr>
{{#if country}}
<tr>
  <th>Country</th>
  <td>{{country}}</td>
</tr>
{{/if}}
</table>    
</script>

<script type="text/javascript">
ko.handlebarsTemplateEngine = function () { }
ko.handlebarsTemplateEngine.prototype = ko.utils.extend(new ko.templateEngine(), {
    renderTemplateSource: function (templateSource, bindingContext, options) {
        var precompiled = templateSource['data']('precompiled');
        if (!precompiled) {
            precompiled = Handlebars.compile(templateSource.text());
        }
        var renderedMarkup = precompiled(bindingContext.$data).replace(/\s+/g, " ");            
        return ko.utils.parseHtmlFragment(renderedMarkup);
    },
    allowTemplateRewriting: false,
    createJavaScriptEvaluatorBlock: function(script) {
       return "{{" + script + "}}";
    }
});
ko.setTemplateEngine(new ko.handlebarsTemplateEngine());

function Person(name, gender, profiles, country){
  this.name = name;
  this.gender = gender;
  this.profiles = profiles;
  if(country) {
    this.country = country;
  }
}
function ViewModel() {
  this.people = ko.observableArray([
    new Person("Bob", "Male", ["Hello", "World"]),
    new Person("Mike", "Male", ["Foo"]),
    new Person("Katherine", "Female", []),
    new Person("Ken", "Male", [], "Japan"),
  ]);
}
ko.applyBindings(new ViewModel());
</script>

jsfiddleで見れます。
http://jsfiddle.net/vjj309sz/


明日は @motoyan_k さんの 「Knockout.hxについて」です。
よろしくおねがいします!