アクトインディ技術部隊報告書 http://tech.actindi.net アクトインディ技術部隊報告書 Tue, 09 Feb 2010 17:28:02 +0900 ja CanvasとWebSocketsでみんなでウロウロする http://tech.actindi.net/3474648989 火曜日担当のkomagataです。

Metasploitは一回お休みさせていただいてJavascriptのお話しです。

仕事は主にwebプログラミングなので身も蓋も無い言い方をすると「DBに入れたり出したり」しかしてません。

「もう文字列処理はうんざりなんだよ!」

というのは嘘ですが、たまには動きのある見栄えのするグラフィックとかアニメーションとかプログラムしてみたいと思い、HTML5で使えるようになるらしい、グラフィック機能のcanvasと双方向同期通信のWebSocketsを使ってキャラクターがウロウロするだけのプログラムを作ってみました。

WebSocketsを実装しているのは現状Google Chrome 4以降だけなので、動作してる雰囲気を伝えるために動画にしてみました。

最近のChromeには実装されているので下記のように簡単にサーバーに接続することができます。

ws = new WebSocket("ws://localhost:8080/")
ws.onopen = function() { console.log('open') }
ws.onclose = function() { console.log('close') }
ws.onmessage = function(evt) { ws.send('Hello!') }

CometなどよりとてもシンプルでたちまちWebSocketsが好きになりました!

Ajaxのように非同期に小さなメッセージをちょこちょこ飛ばすのではなく、1ユーザーに対して1本ガッシリしたラインを繋ぎ、双方向にドカドカ通信するイメージでしょうか。

真っ先にネットゲーム的なものでの利用方法が思い付きますが、これが標準的なブラウザで使えるようになれば、他の新しい使い方で出てきて斬新なUIが生まれれば良いなと思います。

とりあえず現状を下記のURLで動かしています。chromeやsafariのnightlyでは動くみたいです。(windows, mac, linuxどれでも動くことは確認しました。)

http://verdana.komagata.org/prowler/

ソースは下記です。

komagata's prowler at master - GitHub

]]>
Tue, 09 Feb 2010 05:16:29 +0900
CMYK http://tech.actindi.net/3474323393 こんにちは!! tahara です。 今回は Lisp on Rails はお休みで、Ruby on Rails の Paperclip の話題です。

IE で RGB の画像は表示できますが、CMYK の画像は表示できません。 CMYK から RGB に変換する手もありますが、変換時に結構色が変ってしまいます。 ということでアップロードする画像が CMYK の場合は、 バリデーションではじくようにします。

まず CMYK の判定ですが、ImageMagic の identify コマンドで可能です。

~% identify -format '%[colorspace]' ~/archive/normal.jpg
CMYK
~% identify -format '%[colorspace]' ~/archive/normal-rgb.jpg
RGB

ただし古い ImageMagic では -format '%[colorspace]' オプションが認識されないので -verbose オプションを使います。

~% identify -verbose ~/archive/normal.jpg
Image: /home/ancient/archive/normal.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Class: DirectClass
  Geometry: 290x200+0+0
  Resolution: 72x72
  Print size: 4.02778x2.77778
  Units: PixelsPerInch
  Type: ColorSeparation
  Endianess: Undefined
  Colorspace: CMYK      <=== これ!!
  Depth: 8-bit
  ...

この identify を呼び出して CMYK をチェックするバリデーションを config/initializers/paperclip.rb に組み込みます。

module Paperclip
  module ClassMethods
    ...

    # CMYK は IE で表示できないため、検証でエラーとする。
    def validates_attachment_not_cmyk name, options = {}
      message = options[:message] || "CMYK フォーマットの画像はブラウザによって表示できないため使用できません。お手数ですが RGB フォーマットに変換してください。"
      attachment_definitions[name][:validations][:not_cmyk] = lambda do |attachment, instance|
        original_file = attachment.instance_variable_get(:@queued_for_write)[:original]
        colorspace =
          begin
            attachment.file? && original_file &&
              Paperclip.run("identify", "-verbose #{original_file.path}")
          rescue
            nil
          end
        if colorspace && colorspace =~ /^\s*Colorspace: CMYK$/
          message
        end
      end
    end
    ....

これでモデルから validates_attachment_not_cmyk というひどい名前のバリデーションが使えるようになります。

  validates_attachment_not_cmyk :picture_1

まとめるとこうなります。

(incf ImageMagic)
(decf IE most-positive-fixnum)
]]>
Fri, 05 Feb 2010 10:49:53 +0900
括り出したい http://tech.actindi.net/3474287022 if pred method(100) else method(200) end のようなものを見ると
method(if pred
         100
       else
         200
       end)
と書きたくなってしまいます。ifは分岐が2つですが、Rubyのcase等の複数への分岐も同じくそうです。 LISPだと
(method (if pred 100 200))
という感じですが、このifの纏め方は、LISPではすんなり流れるものの、Rubyだとif〜endが重たくみえるので、なんとなく書いてはいけないようにさえ感じます。
条件演算子なら
method(pred ? 100 : 200)
という風にすっきりなのですが、なんとなく読みづらいですね。 ]]>
Fri, 05 Feb 2010 00:43:42 +0900
Toll-free bridge http://tech.actindi.net/3474198831 こんにちは。
masudaです。

今日は節分でしたね。
あの豆を食べるのが好きです。

早くもネタが尽きてきました。
自分がObjective-Cのポテンシャルがわかっていないので(別にObjective-Cである必要は全然ないのですが)、続き物を書くことができません。

今回はToll-free bridgeについて書いてみようと思います。
またもやどこにもあるようなネタです。

Toll-free bridgeについてはHMDTさんなどで詳しく紹介がされています。
ダイナミックObjective-C (38) Toll-free bridge(1) – 変換コスト0のブリッジ | エンタープライズ | マイコミジャーナル

CocoaのオブジェクトとCoreFoundationのオブジェクトを相互にキャストするだけで変換することができます。
たとえばCocoaのNSStringというクラスは、CoreFoundationではCFStringというものに対応します。

具体例を示しましょう。
変換の話の前に、CoreFoundationでは初期化はどうするか?

NSStringであれば

NSString *hoge = [[NSString alloc] initWithCString:"piyo"];

のように書くところですが、CoreFoundationでは

 
CFStringRef hoge = CFStringCreateWithCString(kCFAllocatorDefault, "piyo", kCFStringEncodingUTF8);

となります。

さて、本題のToll-free bridgeによる変換です。
どのようなときに使うのか?
具体例を挙げると、NSStringの遅いメソッドであるcharacterAtIndexを呼び出す代わりに、CoreFoundationにあるCFStringGetCharacterFromInlineBuffer関数を使用して高速に処理するなんて使い方をするとか。
別にすべてCoreFoundationで書いてもかまいませんが、Cocoaを使うよりも幾分面倒なのでこういう適用が多いのではないかと思います。

NSString                *hoge;
CFIndex                 length, current;
CFStringInlineBuffer    buffer;
UniChar                 ch;
 
*hoge = [[NSString alloc] initWithCString:"piyo"];
length = CFStringGetLength((CFStringRef)hoge);
 
CFStringInitInlineBuffer((CFStringRef)hoge, &buffer, CFRangeMake(0, length));
 
current = 0;
while (current < length)
{
    ch = CFStringGetCharacterFromInlineBuffer(&buffer, current);
    NSLog(@"%c", ch);
 
    ++current;
}

こんな風にキャストするだけで渡すことができます。
昔、NSDictionaryの生成をCFDictionaryの生成に変えたところ劇的に速度が向上したことがあったような気がします。

]]>
Thu, 04 Feb 2010 00:13:51 +0900
Metasploit3で脆弱性を検証する(1) http://tech.actindi.net/3474035399 Penetration Testing | The Metasploit Project

火曜日担当のkomagataです。

Gumblerウィルスが猛威を振るっているので流行に乗ってセキュリティネタです。

脆弱性検証(というか実際に脆弱性を突くので悪用厳禁)ツールのMetasploit3をMacで使ってみました。

Macportsのはrb-railsやrb-rackが普通のgemとぶつかって入りません。(port editで依存性を外せば入りましたが気持ち悪いです。)

なので、svnのtrunkを持ってきました。

% svn co https://www.metasploit.com/svn/framework3/trunk metasploit

今回checkoutしたのはrevision8340でした。

% cd metasploit
% ./msfconsole
/Users/komagata/code/metasploit/lib/msf/core/exploit/mixins.rb:46:in `require': /Users/komagata/code/metasploit/lib/msf/core/exploit/capture.rb:358: syntax error, unexpected ')', expecting kEND (SyntaxError)
/Users/komagata/code/metasploit/lib/msf/core/exploit/capture.rb:375: syntax error, unexpected $end, expecting kEND
        from /Users/komagata/code/metasploit/lib/msf/core/exploit/mixins.rb:46
        from /Users/komagata/code/metasploit/lib/msf/core/exploit.rb:216:in `require'
        from /Users/komagata/code/metasploit/lib/msf/core/exploit.rb:216
        from /Users/komagata/code/metasploit/lib/msf/core.rb:52:in `require'
        from /Users/komagata/code/metasploit/lib/msf/core.rb:52
        from /Users/komagata/code/metasploit/lib/msf/ui/console/driver.rb:1:in `require'
        from /Users/komagata/code/metasploit/lib/msf/ui/console/driver.rb:1
        from /Users/komagata/code/metasploit/lib/msf/ui/console.rb:10:in `require'
        from /Users/komagata/code/metasploit/lib/msf/ui/console.rb:10
        from /Users/komagata/code/metasploit/lib/msf/ui.rb:10:in `require'
        from /Users/komagata/code/metasploit/lib/msf/ui.rb:10
        from ./msfconsole:16:in `require'
        from ./msfconsole:16

ところがcoreで読み込んでるファイルがsyntax error。ほぼ全てのコマンドが動きません。

「これは良いコミットエンドラン・・・(ゴクリ)」

% svn diff
Index: lib/msf/core/exploit/capture.rb
===================================================================
--- lib/msf/core/exploit/capture.rb     (revision 8340)
+++ lib/msf/core/exploit/capture.rb     (working copy)
@@ -355,7 +355,7 @@
                rescue RuntimeError => e
                        @pcaprub_error = e
                        print_status("Cannot stat device: #{@pcaprub_error}")
-                       raise RuntimeError, "Pcaprub error: #{@pcaprub_error}")
+                       raise RuntimeError, "Pcaprub error: #{@pcaprub_error}"
                end
                return my_net
        end

取り敢えずこれで動きますのでお急ぎの方は是非。

% ./msfconsole

                |                    |      _) |   
 __ `__ \   _ \ __|  _` |  __| __ \  |  _ \  | __| 
 |   |   |  __/ |   (   |\__ \ |   | | (   | | |   
_|  _|  _|\___|\__|\__,_|____/ .__/ _|\___/ _|\__| 
                              _|                   


       =[ metasploit v3.3.4-dev [core:3.3 api:1.0]
+ -- --=[ 176 exploits - 30 auxiliary
+ -- --=[ 104 payloads - 17 encoders - 5 nops
       =[ svn r8340 updated today (2010.02.01)

msf >

metasploitはversion3からperlからrubyになったらしく、僕にとっては読みやすくて嬉しいです。でもWebインターフェースがRailsなのは少しアグレッシヴですね。

次回は実際に脆弱性を突いてみようと思います。

]]>
Tue, 02 Feb 2010 02:49:59 +0900
Lisp on Rails 第2回 〜 メタクラス http://tech.actindi.net/3473716585 こんにちは!! tahara です。 Lisp on Rails 第2回です!

ActiveRecord::Base ではクラスメソッドとして find や all の検索メソッドが定義されています。

Common Lisp でそれらを実装するにあたり、メタクラスのメソッドとして実装してみます。 Common Lisp では自分でメタクラスを定義することができます。 次のようにメタクラスを定義します。 なんとなく、テーブル名とカラム情報を持たせています。

(defclass active-record-class (standard-class)
  ((%table-name :initarg :%table-name :accessor %table-name-of)
   (%columns :initarg :%columns :accessor %columns-of)))
各テーブル毎のクラスはこの active-record-class のインスタンスになり、 インスタンス変数としてテーブル名とカラム情報を持つイメージです。

メタクラスに全レコードを取得する all メソッドを実装します。

(defmethod all ((class active-record-class))
  (multiple-value-bind (rows columns)
      (clsql-sys:query (format nil "select * from ~a" (%table-name-of class)))
    (loop for i in rows
          collect (make-instance-from-row class i columns))))

(def-record post) は次のように展開されて :METACLASS ACTIVE-RECORD::ACTIVE-RECORD-CLASS を指定します。

(PROGN
  (DEFPARAMETER POST
    (DEFCLASS POST (BASE)
      ((ID :INITARG :ID :INITFORM NIL :ACCESSOR ID-OF)
       (NAME :INITARG :NAME :INITFORM NIL :ACCESSOR NAME-OF)
       (TITLE :INITARG :TITLE :INITFORM NIL :ACCESSOR TITLE-OF)
       (CONTENT :INITARG :CONTENT :INITFORM NIL :ACCESSOR CONTENT-OF)
       (CREATED-AT :INITARG :CREATED-AT :INITFORM NIL :ACCESSOR
                   CREATED-AT-OF)
       (UPDATED-AT :INITARG :UPDATED-AT :INITFORM NIL :ACCESSOR
                   UPDATED-AT-OF))
      (:METACLASS ACTIVE-RECORD::ACTIVE-RECORD-CLASS)))
      ...
Ruby のクラス定義と違って Common Lisp のクラス定義ではクラス名に何も束縛しないため、 わざわざ defparameter しています。

そんな感じでメタクラスによる

(all post)
ができました。

ソースはこちらから http://github.com/quek/lisp-on-rails

第3回につづきます

]]>
Fri, 29 Jan 2010 10:16:25 +0900
PerlとC++にしかできないような気がした十五の夜 http://tech.actindi.net/3473675040 今年の私のテーマは「挑戦」。 先日、そんな私にぴったりな、盗んだバイクで走り出したくなる挑戦をみつけました。
  • PerlとC++にしかできないような気がするアノ機能(挑戦者募集中)
  • #!/usr/bin/perl
    # PerlとC++は世界一。
    
    srand(time);
    
    my $a = 0;
    my $b = 0;
    for(my $i = 0; $i < 1000; $i++) {
        (rand(2)<1 ? $a : $b) += 1;
    }
    print "$a, $b\n"
    
    これをPerlや、C++以外の言語で書けるのか、と。
    私は、LISP野郎なのでLISPで回答するとして考えましたが「実行時に変数の名前によって任意の変数にアクセスし、その変数に値を代入できるか」という風にお題を解釈しました。 PerlやC++の場合は、?:にそういう機能があるのでしょう。 Common Lispだとどうなるかというと、「実行時に変数の名前によって任意の変数にアクセス」というのは、シンボル名による変数へのアクセスで可能なので、上をCommon Lispに訳すと
    (let ((a 0) (b 0))
      (declare (special a b))
      (dotimes (i 1000)
        (incf (symbol-value
               (if (< (random 2) 1) 'a 'b))))
      (format t "~A, ~A~%" a b))
    ;⇒ NIL
    ----------
    499, 501
    
    こんな感じに書くことになるのかなあと思いました。
    …というようなことをtaharaさんと昼食時に話していたのですが、taharaさん曰くifにsetfが付いてれば可能なんじゃないかとのこと。 なるほど、確かにそうです。
    setfというのは代入する構文のマクロなのですが、ユーザーが色々カスタマイズできます。 実行時に変数名でアクセス→代入というのではなく、そういう構文をマクロで定義するわけですね。
    ユーザーがifにsetfを書けば良いのですが、これが標準で付いている処理系をどっかでみたなーと思ったので調べてみるとCLISPがそうでした。 CLISPだと標準で
    (let ((a 0) (b 0))
      (dotimes (i 1000)
        (incf (if (< (random 2) 1) a b)))
      (format t "~A, ~A~%" a b))
    ;⇒ NIL
    ----------
    513, 487
    
    と書けます。自分はPerlは書けないのですが、+=をカスタマイズすることによって
    for(my $i = 0; $i < 1000; $i++) {
        if (rand(2) < 1) { 
          $a 
        } else {
          $b
        } += 1;
    }
    
    のようにも書けるようにユーザーが勝手に定義できる、という感じでしょうか。
    こんなことをしているとすぐカオスになりそうですが、LISPに構文は無いようなものなので特に混乱もなかったりします。LISPは単純で良いですね■ ]]>
    Thu, 28 Jan 2010 22:44:00 +0900
    iPhoneによる位置情報関係のまとめ http://tech.actindi.net/3473583175 こんにちは。
    先日komagataさんにgit svnの使い方を教えていただいたおかげで、少しは使えるようになってきたmasudaです。

    今回も前回のGeohashに引き続き、位置情報に関する内容です。
    ググれば出てくる内容なので、新しいことはなんにもないのが申し訳ないところです。

    位置情報に関するライブラリは

    • CoreLocation
    • MapKit
    などがあります。

    GPSで現在位置を取得するにはCoreLocationを使用し、地図を表示したり現在地の大まかな住所を取得するためにはMapKitを使用します。

    CoreLocationではCLLocationManagerDelegateを実装し

    CLLocationManager *locationManager = [[CLLocationManager alloc] init];
        if ([locationManager locationServicesEnabled])
        {
            [locationManager setDelegate:self];
            [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
            [locationManager setDistanceFilter:kCLDistanceFilterNone];
        }
    
    - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
        NSLog(@"%@", newLocation);
    }

    このようにすればLogに現在地の情報が取得できます。

    地図を表示するには

    CGRect screen = [[UIScreen mainScreen] bounds];
    MKMapView *mapView = [[MKMapView alloc] initWithFrame:screen];
    [[self view] addSubview:mapView];
    [mapView release];
    
    MKCoordinateRegion  region;
    region.center = [location coordinate];
    region.span.latitudeDelta = 0.005;
    region.span.longitudeDelta = 0.005;
    [mapView setRegion:region animated:YES];

    とすれば、locationで指定した座標に移動します。

    現在地を取得するにはMKReverseGeocoderDelegateを実装し

    MKReverseGeocoder *reverseGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:[location coordinate]];
    [reverseGeocoder setDelegate:self];
    [reverseGeocoder start];
    
    - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
    {
        NSLog(@"%@", [placemark title]);
    }

    とすることで取得することができます。
    すべてのAPIが非常にシンプルに作られているので、使用するのは非常に簡単です。

    ]]>
    Wed, 27 Jan 2010 21:12:55 +0900
    Lispに興味がない・・・だと・・・? http://tech.actindi.net/3473547098

    興味のある言語にLispと書いておいたら面接で爆笑された

    面接官「Lisp・・・ふははっ!Lisp!」

    面接官「Lispやってるんですか?wwwww」

    俺「(唖然)は、はい・・まだS式を理解したぐらいですが。。」

    面接官「Lisp・・・ニヤニヤ」

    Hunchentootで動いてるこのブログを見て弊社に面接に来た方がCommon Lispに興味なかったらメンバー全員がっかりしますね・・・。

    ]]>
    Wed, 27 Jan 2010 11:11:38 +0900
    Real (World) Git http://tech.actindi.net/3473481089 火曜日担当のkomagataです。

    gitよく分からないのでどういう風に使ってるのかデモってくれと言われたので実際に仕事のコードにコミットしてみました。

    実録!git!

    アクトインディでは「子供とのお出かけ先を探すサイト」いこーよhttp://iko-yo.net)というサイトを運営しています。 リポジトリはデザイナーさんがDreamweaverCodaのsvnクライアントを使うのでSubversionです。

    svnの最新リビジョンだけを持ってくる。(全部持ってくると死ぬほど時間がかかる。)

    % git svn clone -r HEAD https://svn.actindi.net/svn/oyaiku/trunk/outing outing --username=komagata

    Redmineのチケットを見る。 予め仕込んでおいた簡単そうなチケットを発見。(redmineではイシューというみたいです)

    いこーよ - 新機能 #3487: cityモデルのテストを書く - Redmine(タスク管理)

    チケットに対応したブランチを作る。

    % git branch issue3487

    作業ブランチを切り替える。

    % git checkout issue3487
    (git branch foo; git checkout fooはgit checkout -b fooと同じ)

    ブランチ確認。

    % git branch
      master
    * issue3487

    shouldaスタイルのマクロが使いたいのでremarkableを入れる。

    # config/environment.rb
    Rails::Initializer.run do |config|
      config.gem 'remarkable_rails', :lib => false
    end
    # spec/spec_helper.rb
    require 'spec/rails' # ここの下に書く
    require 'remarkable_rails'
    % sudo rake gems:install
    % rake gems:unpack
    % rake gems:refresh_spec

    一旦、コミット。

    % git add vendor vendor/gems/remarkable_rails-3.1.12
    % git commit -a -m'added remarkable'

    app/model/city.rbのテストを作る。

    # app/model/city.rb
    class City < ActiveRecord::Base
      belongs_to :prefecture
    
      validates_presence_of :name, :reading, :roman
      validates_length_of :name, :within => 1..40
      validates_length_of :reading, :within => 1..40
      validates_length_of :roman, :within => 1..40
      validates_uniqueness_of :roman
    end
    # spec/models/city_spec.rb
    require 'spec_helper'
    
    describe City do
      fixtures :cities
    
      should_belong_to :prefecture
      should_validate_presence_of :name
      should_validate_presence_of :reading
      should_validate_presence_of :roman
      should_validate_length_of :name, :within => 1..40
      should_validate_length_of :reading, :within => 1..40
      should_validate_length_of :roman, :within => 1..40
      should_validate_uniqueness_of :roman
    end

    テスト実行(ホントは全部のテストを実行する)

    % ./script/spec spec/models/city_spec.rb
    
    City
    - should belong to prefecture
    - should require name to be set
    - should require reading to be set
    - should require roman to be set
    - should ensure length of name is within 1..40 characters
    - should ensure length of reading is within 1..40 characters
    - should ensure length of roman is within 1..40 characters
    - should require unique values for roman
    
    Finished in 0.770165 seconds
    
    8 examples, 0 failures

    コミット

    % git add spec/models/city_spec.rb
    % git ci -a -m'added city_spec. fixed #3487'

    masterに移る。

    % git checkout master

    最新版を持ってくる

    % git svn rebase

    issue3487をマージする

    % git merge issue3487

    svnにコミット。

    % git svn dcommit

    完了。

    その他の便利機能

    いっこ前のコミットなかったことにする

    % git reset HEAD^

    昔のコミットを修正したい

    % git log --oneline
    c5524b2 * removed foo * removed remarkable
    460bfa1 [デザイン] TOPページ「外へおでかけ」の変更 (refs #3490) * 谷さん修正分
    9b819fd * add city_spec * add remarkable * add foo
    695b1eb [システム] [mobile] /facilities/:id のレイアウト変更。 (refs #2899) * いらないhrを削除。
    % git rebase -i 695b1eb

    エディタが立ち上がるので修正したいリビジョンのpickをeditに変更して終了する。

    pick 9b819fd * add city_spec * add remarkable * add foo
    pick 460bfa1 [デザイン] TOPページ「外へおでかけ」の変更 (refs #3490) * 谷さん修正分
    edit c5524b2 * removed foo * removed remarkable

    指定したリビジョンの状態に戻るので好きにaddしたり編集したりする。

    % git commit --amend
    % git rebase --continue

    修正完了

    複数の適当なコミットを一つにまとめたい

    % git log --oneline
    68fb234 add text2 in foo
    5cd81d6 add text in foo
    43fdcb7 add foo
    fb91711 removed old paperclip
    aa21e65 fixed
    % git rebase -i fb91711
    pick 43fdcb7 add foo
    pick 5cd81d6 add text in foo
    pick 68fb234 add text2 in foo

    次のリビジョンとまとめたいリビジョンの先頭をpickからsquashに変える。

    pick 43fdcb7 add foo
    squash 5cd81d6 add text in foo
    squash 68fb234 add text2 in foo

    コミットメッセージをいれて終了。

    みなさんおっしゃってますが、やはり、svnからgitにして嬉しいのはbranchの作成やcommitが気軽できるところですね。一つの作業をやってる途中に別の優先タスクが入った場合も、現在のbranchをほっぽってすぐにそちらのタスクに移れるのは精神的にもとても楽です。

    適当にfixed, fixedなどとコミットしていっても後で綺麗にまとめられるところもいいですね。

    gitは他にもいろいろ出来るみたいですが、今のところリアルにこんな感じで使っています。便利な使い方があれば教えて頂けると嬉しいです。

    ]]>
    Tue, 26 Jan 2010 16:51:29 +0900
    Lisp on Rails 第1回 http://tech.actindi.net/3473158189 こんばんは!! tahara です。

    いま仕事で Ruby on Rails を使っています。 正直 Active Record いいっすねー。 DB いじるには楽です。

    くやしいので Common Lisp でそれっぽいのを実装してみます。 Lisp on Rails ですね(何だか以前から聞く言葉のような気もします)。

    第1回目の今日は何となく Active Record っぽい雰囲気のような感じだけです。

    (eval-when (:compile-toplevel :load-toplevel :execute)
      (setf *connection-spec* '("localhost" "blog_test" "root" ""))
      (setq clsql-sys:*default-database-type* :mysql)
      (establish-connection))
    
    ;; レコードの定義
    (def-record post)
    ;; インサート
    (save (make-instance 'post :name "名前" :title "タイトル" :content "内容"))
    ;; 検索
    (all post)
    

    ソースはこちらから http://github.com/quek/lisp-on-rails

    第2回につづきます

    ]]>
    Fri, 22 Jan 2010 23:09:49 +0900
    Rubyの好きなところ http://tech.actindi.net/3473072867 x = 3 [0, *if x.even? [1, 2, 3] else [:a, :b, :c] end] ;⇒ [0, :a, :b, :c]
    def iota(n)
      if n.zero?
        0
      else
        [n, *iota(n - 1)]
      end
    end
    
    iota(10)
    ;⇒ [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    
    Proc.new do |x, y| x * y;end [100,2]
    ;⇒ 200
    
    LISP/Schemeでも、書けるといえば書けるのですが、
    ;; Common LISP
    (let ((x 3))
      `#(0 ,@(if (evenp x)
                 '(1 2 3)
                 '(:a :b :c))))
    ;⇒ #(0 :A :B :C)
    
    (defun iota (n)
      (if (zerop n)
          (list 0)
          `(,n ,@(iota (1- n)))))
    
    ;⇒ (10 9 8 7 6 5 4 3 2 1 0)
    
    (multiple-value-call #'* (values-list '(100 2)))
    ;⇒ 200
    
    ;; もしくは
    (apply #'* '(100 2))
    ;⇒ 200
    
    Rubyの方が統一感があって良いですね。 ]]>
    Thu, 21 Jan 2010 23:27:47 +0900
    Objective-C的???Geohash http://tech.actindi.net/3472988345 こんにちは!
    はまっている時間はたいていRSpecに起因するものなのではないかと以前から感じているmasudaです。
    なんとか約束の火曜日に間に合ったでしょうか???

    先日chibaさんがGeohashをdecodeするものをCLで書いていらしたので、それを微妙に参考にしながらCocoaのCoreLocationのCLLocationにgeohashをencode/decodeするメソッド追加してみました。

    本当はビット演算がしたいのですが、文字列処理の方が自分には単純で簡単だったため、とりあえず今回は文字列処理にしてみました。

    我ながらひどいコードだと思いますので、これからリファクタリングをしていきたいところです。

    [CLLocation+Geohash.h]

    #import <CoreLocation/CoreLocation.h>
    #import <Foundation/Foundation.h>
    
    
    @interface CLLocation(Geohash)
    
    @property (nonatomic, readonly)   NSString    *geohash;
    
    + (CLLocation *)locationFromGeohash:(NSString *)aGeohash;
    
    @end
    

    [CLLocation+Geohash.m]

    #import "CLLocation+Geohash.h"
    
    #include <math.h>
    
    NSString *int_to_binary(NSUInteger input)
    {
        if (input == 1 || input == 0)
        {
            return [NSString stringWithFormat:@"%d", input];
        }
    
        return [NSString stringWithFormat:@"%@%d", int_to_binary(input / 2), input % 2];
    }
    
    
    double parse_binary(NSString *binary, double max, double min)
    {
        double mid = 0.0;
        
        for (NSUInteger i = 0; i < [binary length]; ++i)
        {
            if ([binary characterAtIndex:i] == '1')
            {
                min = mid;
            }
            else
            {
                max = mid;
            }
            
            mid = (max + min) / 2;
        }
        
        return mid;
    }
    
    
    NSUInteger binary_to_int(NSString *input)
    {
        NSUInteger result, length;
    
        result = 0;
        length = [input length];
    
        for (NSUInteger i = 0; i < length; ++i)
        {
            if ([input characterAtIndex:i] == '1')
            {
                result += pow(2, length - i - 1);
            }
        }
    
        return result;
    }
    
    
    NSString * generate_binary(double input, double max, double min, int cutoff)
    {
        NSMutableString     *result;
        double              mid;
    
        result = [NSMutableString string];
        for (int i = 0; i < cutoff; ++i)
        {
            mid = (max + min) / 2;
    
            if (input > mid)
            {
                [result appendString:@"1"];
                min = mid;
            }
            else
            {
                [result appendString:@"0"];
                max = mid;
            }
        }
    
        return [NSString stringWithString:result];
    }
    
    
    @implementation CLLocation(Geohash)
    
    - (NSString *)geohash
    {
        int cutoff = 15;
        NSString *base32_characters  = @"0123456789bcdefghjkmnpqrstuvwxyz";
    
        NSString            *bin_lat, *bin_lng;
        NSMutableString     *bin_packed, *result;
        
        bin_lat = generate_binary([self coordinate].latitude, 90.0, -90.0, cutoff);
        bin_lng = generate_binary([self coordinate].longitude, 180.0, -180.0, cutoff);
    
        bin_packed = [NSMutableString string];
    
        for (int i = 0; i < [bin_lat length]; ++i)
        {
            [bin_packed appendFormat:@"%c%c", [bin_lng characterAtIndex:i], [bin_lat characterAtIndex:i]];
        }
    
        result = [NSMutableString string];
    
        // extract by 5-bit.
        for (int i = 0; i < [bin_packed length] / 5; ++i)
        {
            NSUInteger index;
            index = binary_to_int([bin_packed substringWithRange:NSMakeRange(i * 5, 5)]);
            [result appendFormat:@"%c", [base32_characters characterAtIndex:index]];
        }
    
        return result;
    }
    
    
    + (CLLocation *)locationFromGeohash:(NSString *)aGeohash
    {
        NSString *base32_characters  = @"0123456789bcdefghjkmnpqrstuvwxyz";
    
        NSMutableString *bin_packed, *bin_lat, *bin_lng;
    
        bin_packed = [NSMutableString string];
    
        for (NSUInteger i = 0; i < [aGeohash length]; ++i)
        {
            NSString *character;
            character = [[NSMutableString stringWithFormat:@"%c", [aGeohash characterAtIndex:i]] lowercaseString];
    
            for (NSUInteger j = 0; j < [base32_characters length]; ++j)
            {
                if ([character isEqualToString:[NSString stringWithFormat:@"%c", [base32_characters characterAtIndex:j]]])
                {
                    NSMutableString *binary;
                    binary = [NSMutableString stringWithFormat:@"%@", int_to_binary(j)];
    
                    NSUInteger length = [binary length];
                    for (NSUInteger k = 0; k < 5 - length; ++k)
                    {
                        [binary insertString:@"0" atIndex:0];
                    }
    
                    [bin_packed appendString:binary];
                    break;
                }
            }
        }
    
        bin_lat = [NSMutableString string];
        bin_lng = [NSMutableString string];
    
        for (NSUInteger i = 0; i < [bin_packed length]; ++i)
        {
            if (i % 2)
            {
                // a latitude is composed of odd bits. 
                [bin_lat appendFormat:@"%c", [bin_packed characterAtIndex:i]];
            }
            else
            {
                // a longitude is composed of even bits.
                [bin_lng appendFormat:@"%c", [bin_packed characterAtIndex:i]];
            }
        }
    
        return [[CLLocation alloc] initWithLatitude:parse_binary(bin_lat, 90.0, -90.0)
                                          longitude:parse_binary(bin_lng, 180.0, -180.0)];
    }
    
    
    @end
    

    NSStringでかなり遅いcharacterAtIndexを使いまくっている。

    参考

    Geohash - Wikipedia, the free encyclopedia
    GeoHashのdecodeのアルゴリズムの解説します & ScalaのGeoHashライブラリを作ってみました(仮) - ゆろよろ日記

    ]]>
    Wed, 20 Jan 2010 23:59:05 +0900
    テストを通らないリリースを止めるライブラリ http://tech.actindi.net/3472868530 昼にキリンフリーを飲むと機嫌が良くなる火曜日担当のkomagataです。

    rspecのテストが通らないとデプロイを止めてしまうcapistranoのレシピのgemを作りました。

    showstopper 0.1.0

    ShowStopper is capistrano recipe that stop deploy when rspec is red.

    インストール

    $ sudo gem install showstopper -s http://gemcutter.org

    Capfileの中で読み込むだけで設定完了です。

    $ vi Capfile
    (...)
    require 'showstopper'

    これでrspecが通ってないのに誰かがデプロイしようとすると・・・

    % cap deploy
    (...)
      * == Currently executing `deploy'
        triggering before callbacks for `deploy'
      * == Currently executing `deploy:spec'
        rspec test failed

    showstopperがデプロイを中止してしまいます!

    これを投入していい加減なテストのあるプロジェクトを恐怖のどん底に陥れてやりましょう!

    ]]>
    Tue, 19 Jan 2010 14:42:10 +0900
    autotest-stumpwm http://tech.actindi.net/3472528762 こんにちは!! tahara です。

    script/autospec の結果を表示してくれる Growl がうらやましいのですが、私 の使っているのは Linux です。しかし、Linux には Stumpwm があります。 Stumpwm の stumpish を使えば echo でメッセージを表示することができます。

    そこで script/autospec の結果を Stumpwm で表示する gem を作ってみます。

    参考サイト

    gem を作るには Jeweler を使うのがよさそうです。 Jeweler は GitHub の API を使うようなので、まずその設定を行います。 user_name と api_token には自分の Username と API Token を指定します。

    git config --global github.user user_name
    git config --global github.token api_token
    

    Jeweler をインストールしてプロジェクトを作ってみます。

    gem install jeweler
    jeweler --rspec --create-repo autotest-stumpwm
    

    これで綺麗にプロジェクトが作成されます。 おまけに GitHub にリポジトリまでできています。

    次に Rakefile を編集します。TODO になっている次の二箇所を適当に編集すればよさそうです。 あと依存する gem も指定しておきます。

        gem.summary = %Q{TODO: one-line summary of your gem}
        gem.description = %Q{TODO: longer description of your gem}
        gem.add_dependency "autotest-growl", ">= 0.1.7"
    

    次に lib の下のファイルに Stumpwm を使って script/autospec の結果を表示するたコードを書きます。 コードが出きたら次のようにリリースします。

    rake version:write
    rake gemspec
    rake release
    

    これだけで Gemcutter にも自動的に公開されます。 Jeweler すばらしい!!

    修正したら git commit して、次のいずれかでバージョンをあげ rake release するだけ。

    rake version:bump:major              # Bump the gemspec by a major version.
    rake version:bump:minor              # Bump the gemspec by a minor version.
    rake version:bump:patch              # Bump the gemspec by a patch
    

    できあがった autotest-stumpwm を使うには gem install autotest-stumpwm して、 ~/.autotest に次の一行を書きます。これで autospec と Stumpwm の幸せな生活がおくれます。

    require 'autotest/stumpwm'
    

    さて、一番大切な Stumpwm で結果を表示するコードですが、

    # -*- coding: undecided -*-
    require 'rubygems'
    require 'autotest/growl'
    
    module Autotest::Growl
      def self.growl(title, message, icon, priority=0, stick="")
        priority = if priority > 0  # error or feailed
                     1              # red
                   elsif priority == -2 # passed
                     2                  # green
                   else
                     3              # yellow
                   end
        system "stumpish echo ^#{priority}* #{title} #{message}"
      end
    end
    
    ごめんなさい autotest-growl にモンキーパッチをあてただけです。 ]]>
    Fri, 15 Jan 2010 16:19:22 +0900
    Geohash http://tech.actindi.net/3472464385 Geohash - Wikipedia, the free encyclopedia そんな感じで、説明の順番のとおりに書いてできたコードが下記です。 なんとなく仕組みは分かったけど、そういえば、エンコード手順の説明は書いてないんだなあ…、と自分勝手なことを考えながら就寝しました。
    (defpackage :geohash
      (:use :cl)
      (:import-from :shibuya.lisp
                    :$ :$*))
    
    (in-package :geohash)
    
    (defun tr (from to string)
      (map 'string 
           (lambda (c)
             (or (some (lambda (x y) 
                         (and (char-equal x c) y))
                       from to)
                 (char-upcase c)))
           string))
    
    (defun 5bits (string)
      (map 'list
           ($ format nil "~5,'0,B" 
              $ read-from-string 
              $ format nil "#32R~A" 
              $ tr "0123456789BCDEFGHJKMNPQRSTUVWXYZ" 
                   "0123456789ABCDEFGHKJKLMNOPQRSTUV" 
              $ string $)
           string))
    
    (defun longitude-latitude (strings)
      (let ((bit-c-list ($* concatenate 'list strings)))
        (loop :for c :in bit-c-list
              :for i :from (if (char= #\0 (car bit-c-list)) 0 1)
              :if (evenp i) :collect c :into even
              :else :collect c :into odd
              :finally (return 
                         (list :longitude
                               (coerce even 'string) 
                               :latitude
                               (coerce odd 'string))))))
    
    (defun bitlist (string)
      (map 'list ($ parse-integer $ string $) 
           string))
    
    (defun decode (bits min mid max)
      (if (endp bits)
          mid
          ($* decode 
              (cdr bits)
              (if (zerop (car bits))
                  (list min (/ (+ mid min) 2) mid)
                  (list mid (/ (+ mid max) 2) max)))))
    
    (defun decode-geohash (string)
      (let* ((u ($ longitude-latitude $ 5bits string))
             (lon (getf u :longitude))
             (lat (getf u :latitude)))
        (list 
         :longitude 
         ($ float $ decode (bitlist lon) -90 0 90)
         :latitude
         ($ float $ decode (bitlist lat) -180 0 180))))
    
    (decode-geohash "u4pruydqqvj")
    ;⇒ (:LONGITUDE 57.64911 :LATITUDE 10.407439)
    
    ]]>
    Thu, 14 Jan 2010 22:26:25 +0900
    Delaunay Tessellation for iPhone http://tech.actindi.net/3472341020 こんにちは!!!
    今まで更新しろとせっつかれていたのにもかかわらず、全然更新しなかったmasudaです。

    とりあえず最初は今までやったのにアップロードしていなかったプログラムプレゼンテーションのネタを書こうかなと思います。

    過去の部分はこちらを参考にしてください。

    第1回 cocoa*life - Apple Push Notification Serviceを利用した、iPhone クライアントと、Rubyによるサーバの作成。

    第3回 cocoa*life - Grand Central Dispatchを試してみる。

    以下、同様にblogに載せようと思って途中でやめていたものを載せようと思います。

    プログラムプレゼンテーションの第2回は、iPhoneを用いてDelaunay分割をするというものにしてみました。

    本当は他のものをやるつもりだったのですが、前回のプログラムプレゼンテーションではkomagataさんがObjective-Cのキメラさ、カオスさをおもしろがっていたと勝手に仮定して、Objective-C++でさらなるカオスさを目指すことにしました。

    そんな折りに以前ドロネー分割をするためのプログラムをつくって、アップロードしようかなといっていたのを思い出しました。

    ということで、今回はそれを流用することにしました。
    単純に移植するだけだから簡単だろと思ったところ、意外と手直しに時間がかかってしまいました。

    ドロネー分割については計算幾何学で出てくるものですが、この余白はそれを書くのにはせますぎるということで、ググればきっとわかる!!!

    ソースコードはこちらです。
    ライブラリとしてBoost C++ Librariesを使用しています。

    実行すると、毎回ランダムな10点を作成し、下図のようにドロネー分割された図が表示されます。

    Delaunay tessellation   Delaunay tessellation with circumcircles

    右側の図は外接円も表示させた場合です。
    ドロネー分割では生成された三角形によって作られる外接円の中に、その三角形以外の点が含まれてはいけません。

    ランダムな点を生成する部分にはboost::randomを用い、ドロネー分割を計算する部分はC++で書かれています。

    Objective-CとC++のコードを混ぜる場合の注意点は、HMDTさんによくまとめられているのでこちらを参照していただくのがよいかと思います。
    HMDT – Objective-C++

    Objective-C++のソースを書かれるときは、.mとなっている拡張子を.mmにしてくださいね。
    自分はこれをしないでObjective-C++のファイルだと認識されずはまりまくりました。

    こんな風にC++のコードも簡単に使用することができるので、Objective-Cを使われている皆様もぜひ組み合わせてみてはいかがでしょうか???

    P.S.
    本当はNSOperationを使って、スレッドを新しく作ってバックグラウンドで処理をしたかったのですが、プログラムの構造上面倒なのでやめました。

    参考
    Objective-C プログラミング言語:C++ と Objective-C の併用
    HMDT – Objective-C++

    ]]>
    Wed, 13 Jan 2010 12:10:20 +0900
    Webプログラマーチュートリアル http://tech.actindi.net/3472257910 ニコ生はじめました。komagataです。

    新しくtaharaさんをメンバーに加えて、毎日持ち回りでこのブログを更新していくことになりました。

    火曜日:komagata
    水曜日:masudaさん
    木曜日:chibaさん
    金曜日:taharaさん

    このような曜日担当で更新してきます。忘れていたら罵倒してください・・・。

    ほとんどtaharaさんが書いてくれたのですが、Webプログラマーチュートリアルを作りました。

    web-programmer-tutorial - Project Hosting on Google Code

    何らかのプログラム経験さえあれば、これをみて自習するだけで業務するのに必要なスキルが習得できるように、ゴールと参考URL・書籍の一覧を用意しました。

    入社した最初の一ヶ月を研修期間としてこれをやることにしました。(やりながらメニュー自体も改善する)

    これならば自宅を警備しながらスキルを付けることが出来るのではないかと期待しております。

    OJTのみになってしまっているのを改善したいITベンチャーの方や自宅警備員の方でこれを使ってわからないところがあれば全力で支援いたします。

    ]]>
    Tue, 12 Jan 2010 13:05:10 +0900
    Hunchentoot になりました http://tech.actindi.net/3470616064 こんにちは。12月からメンバにくわわった tahara と申します。
    chiba さんの念願でした、このブログの AllegroServe から Hunchentoot への移行を行いました。
    既に chiba さんが Hunchentoot への移植はやってくれていたので Elephant の導入がメイン作業でした。 Elephant は Common Lisp のオブジェクトデータベースです。バックエンドは色々選べるのですが、今回は SQLite3 を使いました。

    現在このブログは次のような構成で動いています。

    それでは、今後ともよろしくお願いいたします。

    ]]>
    Thu, 24 Dec 2009 13:01:04 +0900
    StumpWMは便利です http://tech.actindi.net/3466487639 今回のプログラム・プレゼンテーションのネタはStumpWMです。 StumpWMはタイル型ウィンドウマネージャーなのですが、Common LISPで色々と拡張することができるのが特長です。

    今回は、このちょっとしたカスタマイズネタや使い方です。

    Actindi社内では現在全面的にRedmineで仕事を管理していて、仕事の確認/依頼もチケット番号ですることが非常に多いです。
    いつもチケットの番号でやりとりするのですが、伝えられた番号をぱっと開きたいことが多いので、これをStumpWMで便利にしてみようということで工夫してみました

      
    (DEFPARAMETER *LAST-TICKET* NIL)
    
    (DEFCOMMAND SHOW-TICKET (TICKET-NUMBER) ((:STRING "Ticket#: "))
      (WHEN (RUN-SHELL-COMMAND 
             (FORMAT NIL 
                    "/usr/bin/firefox "https://redmine.example.com/issues/show/~A\""
                     TICKET-NUMBER))
       (SETQ *LAST-TICKET* TICKET-NUMBER)))
    
    (DEFCOMMAND EDIT-IT () ()
      (RUN-SHELL-COMMAND
        (FORMAT NIL
                "/usr/bin/firefox "https://redmine.example.com/issues/edit/~A\""
                *LAST-TICKET*)))
    

    非常にでっちあげ感の漂う適当なコードですが、show-ticket 1234という風に実行すると、Redmineの1234番のチケットがfirefoxで表示されます。
    edit-itコマンドは保存していた直前のチケット番号を編集状態で開くという単純なものです。 ちょっとした工夫ですが、割と便利で愛用しています。
    といった具合で、その他、StumpWMの機能の説明をして1時間をしのぎました。
    みなさんもご興味あれば、StumpWMをお試しあれ。

    ]]>
    Fri, 06 Nov 2009 18:13:59 +0900
    さようならsed、こんにちはCommon Lisp http://tech.actindi.net/3463978702 chibaです。

    今回のプログラム・プレゼンテーションのネタは日常で使うちょっとしたスクリプトをCommon Lispでやってみようというものです。

    ネタ切れなので自分の ブログに書いたネタ を再演しつつ、ブログでは紹介してなかったwgetも併せて動かしてみました

  • 適当なwget
  • Software ToolsのごとくCommon Lisp上にユーティリティを作成して行けば、Common Lispだけでこういう細かい仕事はできるようになるやもしれません。

    ]]>
    Thu, 08 Oct 2009 17:18:22 +0900
    ブログもどき的、あまりにもブログもどき的 http://tech.actindi.net/3463977650 chibaです。

    今回のプログラム・プレゼンテーションのネタはこのブログもどきについてです。 そもそもは、ちょっと変ったことをしてみようということで、技術方面のブログはCLで作ってみようということになりました。

    構成は、

    • CL処理系: SBCL
    • AllegroServe(RubyでいうWEBrickのようなもの)
    という風になっています。

    SBCL処理系は、ライブラリをロードした状態の処理系のメモリイメージを実行可能ファイルとしてダンプできるのですが、適当に手元のノートPCでAllegroServe(CLのウェブサーバー)をロードした状態でダンプしたものを、さくらサーバーに置いたところ動いてしまったので、そのまま動かすことにしました。(x86の実行ファイルです)

    場当たり的に作っていく中で色々な問題に遭遇しました。

    • AllegroServeだとサーバーの処理系を大文字と小文字を区別するように設定することが前提になっているのでそうしないと色々困る。
    • AllegroServeをAllegro CL上で動かさない場合、日本語の扱いに難がある
    等々、割と根本的なところに問題があったりします。
    HUNCHENTOOT というサーバーもちょっと試てみたのですが、上記のような問題はないので、こちらに乗り換えたいところです

    ]]>
    Thu, 08 Oct 2009 17:00:50 +0900
    Emacsでスクラッチファイルを日付順にして管理するライフハック http://tech.actindi.net/3462883892 chibaです。

    自分は特にプログラムを書くのが趣味という訳でもないので、プログラムプレゼンテーションは割と苦手なのですが、今回は、過去に作った便利Emacs Lispをプレゼンして場をしのぎました。

    アイデアとしては、ファイルを

    file-2009-09-26.txt
    のように命名規則を設けて作成するようにし(これもElispで生成するようにする)、その規則を元に前の日のファイルを開いたり、次の日のファイルを編集したりするのをスムースにする、というものです。
    gist: 13417 - GitHub
    この例では、前のファイルに移動するキーとしてsuper+p次のファイルがsuper+nという風に割り当てみています。
    単純なアイデアの割には便利ですので、お使いの環境でもっと洗練/発展させてみて下さい

    ]]>
    Sat, 26 Sep 2009 01:11:32 +0900
    AquesTalk Rubyバインディング http://tech.actindi.net/3462879600

    komagataです。

    “プログラムプレゼンテーション”でAquesTalkのRubyバインディングを作りました。(Windowsのみ)

    win32-aques_talk - AquesTalk rubyバインディング - p0t

    AquesTalkのrubyバインディング作りました。

    komagata’s win32-aques_talk at master – GitHub

    AquesTalkはwindows版dllのみが組み込んで配布することもOKとなっているのでwindows版をRubyから手軽に使いたいと思って作りました。RubyバインディングといってもC言語拡張ではなく、ruby-ffi(Foreign Function Interface)を使っています。

    豊富なCのライブラリをRubyからサッと使いたいと思ってruby-ffiを使ってみました。ヘッダが必要で無く、動的ライブラリを直接実行するのが面白かったです。また、Windows上で、opensshやgitがいつも通り使えるのがちょっと意外でした。(rubyのgitバインディングはうまく動かないけど)

    ]]>
    Sat, 26 Sep 2009 00:00:00 +0900
    継続インテグレーションコマンド http://tech.actindi.net/3462861600

    komagataです。

    “プログラムプレゼンテーション”で継続的インテグレーションコマンドを作って発表しました。

    saimaa - 今すぐ始められる継続的インテグレーション - p0t

    継続的インテグレーションについては、CIサーバー(Continuous Integration Server)というやつが沢山あって非常に機能も豊富です。僕の仕事には少々大げさな気がしたのと、

    「cronでsvn up && rakeじゃ駄目なのかしら?」

    などと思ったのでそれをちょっとだけサポートするコマンドを作ってみました。

    komagata’s saimaa at master – GitHub

    アクトインディではcapistranoのデプロイコマンドにrspecとcucumberのフックが掛けてあるのでテストが通らなければデプロイはできません。ですが、コミットはできるのでテスト通らないコードがコミットされるとすぐにこの仕組みでメールが飛んでくるのでなかなか便利です。

    これを作って感じたのは、rubygemsとgithubはクロスプラットフォームのCUIプログラム(コマンド)を作る環境として素晴らしいなということです。(全開と似たようなこと言ってますが)

    rubygemsはインストールするとPATHが通ってるところに実行できる場所にコマンドをコピーしてくれるんですよね。jewelerでgithubへのアップも簡単です。

    ]]>
    Fri, 25 Sep 2009 19:00:00 +0900
    Talkedbun - 日本語テキストトゥースピーチサーバー http://tech.actindi.net/3462793200 komagataです。

    アクトインディでは週一回、エンジニアが持ち回りで、「動いて、ダウロードできるプログラム」を公開・発表するという“プログラムプレゼンテーション”(まあ単なるプレゼンです)をやることにしました。

    第一回はShu MASUDAさんでしたのでそちらはお任せするとして、僕は2回目にやりました。

    Talkedbun - 日本語テキストトゥースピーチサーバー - p0t

    URLにひらがなを指定すると、そのひらがなの音声がmp3で得られるwebサーバーを作りました。

    komagata’s talkedbun at master – GitHub

    日本語のURLからそのまま音声が取れたら面白いかなと思って作りました。作っていて一番勉強になったのは、RubyはRubygems, Rack, Sinatraなど、クロスプラットフォームでのマイクロウェイブアプリケーションを作る環境が素晴らしく整っているなということでした。RailsがWebrickをローカルに立ち上げて開発するというスタイルを作ったので自然とWebサーバーの実装、WAFの実装、周辺ツールなどの選択肢がたくさんあります。

    ついでにhaml, sassも使ってみましたが、HTMLのインデントやCSSの重複した記述が病的に気になる僕にはぴったりのアホなツールでとても気に入りました。

    (ジェバンニマチダさんが30分でやってくれました)

    ]]>
    Fri, 25 Sep 2009 00:00:00 +0900
    RSSは動いているか http://tech.actindi.net/3459056185 このエントリーがRSSリーダーに捕捉されれば、とりあえず良いのですが、されてない気がします… ]]> Wed, 12 Aug 2009 17:56:25 +0900 こわれたRSSを付けました http://tech.actindi.net/3459054071 どこかが壊れているようですが、Google Readerや、LDRではがんばって表示してくれるようです。 しかし、それも動きがちょっと変なようです。 ]]> Wed, 12 Aug 2009 17:21:11 +0900 社長にお披露目 http://tech.actindi.net/3458970860 公開できると良いですね!! ]]> Tue, 11 Aug 2009 11:31:03 +0900 このブログの更新はSLIMEでしている! http://tech.actindi.net/3458946663 SLIME使ってる人には非常に優しいブログですね
    具体的には、このサーバーが動いているサーバーのSwankの4005番ポートをローカルにポートフォワードして、EmacsからSlimeで接続し、エントリーの関数を定義しています。簡単ですね! ]]>
    Tue, 11 Aug 2009 11:31:03 +0900
    見た目だけはなんとか完成 http://tech.actindi.net/3458828432 デザインされたhtmlをlmlに直したりしているのですが、これが割と大変です。
    lmlとは、htmlをS式で表現したものなのですが、簡潔でS式の編集環境が整ってさえいれば素のhtmlより簡単に編集できます。
    とはいえ、その編集環境を整えるのが面倒なのですが…。 ]]>
    Mon, 10 Aug 2009 02:40:32 +0900
    急激に重くなった様子 http://tech.actindi.net/3458566436 Fri, 07 Aug 2009 01:53:56 +0900 URLを毎度決めている http://tech.actindi.net/3458279537 (get-universal-time) が使えることに気付きました。
    SLIME上で(get-universal-time)を評価してURLにすると良いかもと。 (get-universal-time)はUNIXタイムのように1970年からではなく、1900年からの秒数になります。 ]]>
    Mon, 03 Aug 2009 18:12:17 +0900
    CSSはウェブページの命 http://tech.actindi.net/3458279064 Mon, 03 Aug 2009 18:04:24 +0900 エントリーを後でどういう風に修正したら良いか http://tech.actindi.net/3457825200 エントリーを後でどういう風に修正したら良いか
    めんどくさそうです。

    ]]>
    Wed, 29 Jul 2009 12:00:00 +0900
    Hunchentootにしたい http://tech.actindi.net/3457821600 色々面倒臭そうなのでHunchentootにしたくなってきました。 とはいえ、Hunchentootも使ったことがないのでなんとも言えません。

    ]]>
    Wed, 29 Jul 2009 11:00:00 +0900
    テストエントリー http://tech.actindi.net/3457818000 SBCLだと日本語が通らないので、無理矢理にマクロを通したり、文字列をバイト列に変換したり涙ぐましいのですが、もっと簡単な方法はないんでしょうか。
    根本的に直さないと駄目な気がしてきました。 AllegroServeより良いのってどういうのがあるんでしょう。

    ]]>
    Wed, 29 Jul 2009 10:00:00 +0900
    掃除は大事 http://tech.actindi.net/3448278000 稼働中のPCを触ってみたところかなり高温になっているという報告を受けたので、4月から新しい仲間になったmasuda氏が機転を効かせてPC内部を掃除したところ、ばっちりPCの温度が下がり、調子も良くなりました。
    どうも熱暴走でPCが落ちてしまっていたようです。
    基本ですが掃除は大事だなとあらためて思った一件です。 ]]>
    Fri, 10 Apr 2009 00:00:00 +0900
    こんにちは、こんにちは http://tech.actindi.net/3445570800 どうぞよろしくお願いします!! ]]> Mon, 09 Mar 2009 16:00:00 +0900 非常に重要なアプリケーションの導入 http://tech.actindi.net/3445513200 先週末からchiba2009さんがエンジニアとして入ってくれました。
    chibaさんは一番得意な言語がCommon Lispという素敵な方です。
    ぜひ社内のシステムのそこここにCommon Lispを忍ばせてほしいです。
    そのchibaさんに今日、とても重要なアプリケーション教えてもらいました。
    それはvrmsです。
      % apt-cache search vrms
    vrms - virtual Richard M. Stallman
    
    早速インストールして実行してみました。
      % vrms
                    Non-free packages installed on dev
    
    gdb-doc                   The GNU Debugger Documentation
    
      1 non-free packages, 0.2% of 503 installed packages.
    
    まずい!
    というかなんでgdbのドキュメントがnon-freeなんでしょうか。
      % sudo apt-get remove --purge gdb-doc
    % vrms
    No non-free packages installed on dev!  rms would be proud.
    
    これで安心。rmsもお喜びのようです。 ]]>
    Mon, 09 Mar 2009 00:00:00 +0900
    sakuraba引退記念 http://tech.actindi.net/3445167600 最初から予定されていたことですが、2月末で、中米の荒くれ者ことsakurabaがアルバイトを完了しました。
    沖縄料理屋で送別会をやって、プレゼントを贈りました。
    sakurabaはMac信者なのでMighty Mouseでも送ればちょっとうれしいのは目に見えていたので、一人おでんセットをプレゼントしました。(しかもMighty Mouseより無意味に高い)
    sakurabaは僕とmachidaさんに向かってとびっきりの呪いの言葉を吐きました。
    sakurabaはアルバイトできてから、RailsもLinuxのサーバー構築も自分でどんどん覚えてしまって、一人でできるようになってしまいました。
    いまでは僕が、「もっとテスト書いたほうがいいですよ」と怒られる始末。
    ボリビアにでも旅立ってしまうのかもしれませんが、これからのsakurabaの活躍を陰ながら応援しています。 ]]>
    Thu, 05 Mar 2009 00:00:00 +0900
    ベンチャーでのおすすめアンチウィルスソフト http://tech.actindi.net/3444519600 以前、はじめてベンチャーのシステム管理を担当したときは、張り切っていて、サーバー集中管理型のアンチウィルスソフトの見積もりを取ったりしていたんですが、今回は、「フリーでいいの無いかな?」という、ゆるふわ系です。
    人数が10人程度なのでディレクトリサービスとか、そこまでやらなくてもいいかなと思っています。(以前は10人未満の会社でActive Directoryを使ってましたが、もう設定とか思い出せません)個人ではアンチウィルスソフトは AVG を使っていて、非常に気に入っていたんですが、商用利用は有料なのでGPLの ClamWin を試してみました。
    日本語化パッチも公開されていて、定義ファイルのダウンロードやスキャンのスケジュール設定も簡単にでき、予想以上に「使える!」といった感じでした。
    会社でも導入を進めて行きたいと思います。 ]]>
    Wed, 25 Feb 2009 12:00:00 +0900
    オフィスの引越し(プロバイダー編) http://tech.actindi.net/3444476400 五反田から五反田へオフィス引越しました。
    システム管理者にとっては何かと大変なオフィスの引越しですが、僕は担当することになったばかりなので全体を把握する丁度良い機会になりました。
    予告通り、プロバイダーはインターリンクの固定IP8個にしました。
    社内にクリティカルなサーバは無いんですが、IPも振り直しです。
    /etc/network/intarfaces を変更して安心してたら、Apacheの443番ポートのバーチャルホストの設定のところに固定IPを書いていたのを忘れてました・・・。
    それと、インターリンクはOP25Bしていることを忘れていて、
    (25番で大丈夫でした。)
    「そういやRedmineのチケット関連のメールが来てないな・・・」
    などと思っていました。
    慌ててPostfixをSubmissionポートを使う設定に変えました。
    会社で25番を絶対使いたい場合は別のプロバイダをお考えください。
    参照: Postfix – Submissionポートで通信 – p0t ]]>
    Wed, 25 Feb 2009 00:00:00 +0900
    1人体制での死活監視 http://tech.actindi.net/3444217200 一定規模以上のWebサイトを運営しているエンジニアの方、業務時間外の障害対応ってどういう風にやっていますか? ルールとか体制とかを中心に教えてほしいです。 ちなみに.. – 人力検索はてな
    ちなみにぼくの会社では、監視ツールや自作監視スクリプトでアラートをエンジニア社員全員に送って、誰かが対応することになっています。(たまに誰も対応やレスをしなくて上司に怒られます) これはぼくら社員にとって正直ストレスになるので、なにかよいルールや体制を上司に提案したいなと考えています。
    はてなでこういう質問がありました。たしかに大きいところではストレスになりますよね。 うちは「一定規模以上のWebサイトを運営してい」ないので特にストレスは感じないです。(アラート受ける人も2人しかいないし・・・)
    Montasticという無料でWebのステータスをチェックしてアラートを送ってくれるサービスを使っています。
    これだとHTTPしかチェックしてくれないのでライブドアのDATAHOTEL PATROLというやつも試してみたいところです。
    それとRailsのExceptionNotifierプラグインのみです。
    社内に監視システムを構築するとその監視システム自体の維持が大変なのでやってません。
    品質とのトレードオフだと思いますが、基本的に、
    「人員1人体制想定でどこまで品質を高められるか」
    という方向でがんばってみたいと思います。 ]]>
    Sun, 22 Feb 2009 00:00:00 +0900
    迫る引越し http://tech.actindi.net/3444174000 何で今急いでブログを作ったかというと、会社が明日引越しだからです。
    明日かよ!とお思いかもしれませんが、時は無常にも過ぎ去り、明日です。
    まずは、引越し先に電話回線(FAX)・Bフレッツ回線・プロバイダを用意しました。
    お客様のサービスのようなクリティカルなものは社内に無いので、自社サービスがひとつ乗っかっているサーバー1台だけを先に人力(チャリと人手)で運んで繋いできました。(昨日)
    それ以外は止めても大丈夫なので荷造りして引越し屋さんにまかせます。
    自分のブログで ITベンチャー勝ち組セット などというエントリーを書きましたが、その通りの INTERLINKの固定IP8個のやつ を契約しました。
    カードがあればその場で使えるようになるのは助かりますね。
    引越し先はBフレッツのマンションタイプが元々あったのでVDSLモデムが届きました。
    無線LANルータは COREGA CG-WLBARGPXW を買いました。
    おいおい、こんなので大丈夫か?と思うかもしれませんが、このルーター使ったことあるので大丈夫なんじゃないかなと楽観的に考えています。
    固定IPを使うにはルータにUnnumbered IPという機能が必須だそうで、買うときに気をつけたいポイントです。
    使ったことあるルータなので、特に問題無く、無線LANと固定IPでサーバ一個(Debian etch)設定できました。
    /etc/network/interfaces を新しいIPに変えて、DNSを変更しただけです。
    無線LANはWPA2, AESでパスワードかけましたが、アクセスポイント自体を隠す設定にするかどうかちょっと悩んで隠さないことにしました。(エンジニアでない人はクライアントの設定で混乱するかと思いまして・・・) これはどっちがいいでしょうか。みなさんどうしてますか?
    引越し後の通常社員初出社は明後日で、引越し屋さんが運び込むのは明日です。
    明日中に全クライアント向けの配線や設定を済ませてこようと思います。 ]]>
    Sat, 21 Feb 2009 12:00:00 +0900
    ブログはじめました http://tech.actindi.net/3444130800 先日、アクトインディ株式会社のシステムの担当になったのでこのブログを作ってみました。
    小さくてくだらない作業までこのブログに書いていこうと思うので、「ベンチャーのシステム担当あるある」
    みたいな感じで見ていただければ・・・なとと考えています。
    現状、僕とアルバイトのsakurabaの二人でネットワークと開発(要するにパソコン関係全部)を担当しています。
    僕自身、ネットワークの知識がイマイチなところもあり、「そこはこうすべきだろう、常識的に考えて・・・」
    などというところがあれば教えていただきたいな、という面もあります。
    なにはともあれ、よろしくお願いします。 ]]>
    Sat, 21 Feb 2009 00:00:00 +0900