2009年6月29日月曜日

gemの作り方

自前の gem の作り方
その記事の中で
と書いてある。
そのうち調べよう。

set_trace_funcは使ったことがない

Ruby で debug する7つの方法という記事。

set_trace_func は使ったことがない。
間接的にはお世話になってるけれど、直接使ったことはない。

2009年6月23日火曜日

"make install"したソフトウェアを管理できる超便利ツール「Paco」

"make install"したソフトウェアを管理できる超便利ツールPaco
へぇ~
もうちょっと早くきがついていたら、使ってみる気になったかもな~。

CentOS 5.2 で swfmill をソースからビルド

pkg-configが使えなくてちょっと苦しんだ。

libxml2-2.7.3.tar.gz を ./configure ; make ; make install
libxslt-1.1.25.tar.gz を ./configure ; make ; make install
freetype-2.3.9.tar.bz2 を ./configure ; make ; make install
libpng-1.2.37.tar.bz2 を ./configure ; make ; make install

最後に、swfmill-0.2.12.tar.gz を

patch -p 1 <>
export XML_CFLAGS=-I/usr/local/include/libxml2
export XML_LIBS="-L/usr/local/lib -lxml2"
export XSLT_CFLAGS=-I/usr/local/include/libxslt
export XSLT_LIBS="-L/usr/local/lib -lxslt -lexslt"
export FREETYPE_CFLAGS=-I/usr/local/include/freetype2
export FREETYPE_LIBS="-L/usr/local/lib -lfreetype"
export PNG_CFLAGS=-I/usr/local/include/libpng12
export PNG_LIBS="-L/usr/local/lib -lpng"
./configure
make

swfmill.cpp:395: error: ‘xslt_simple’ was not declared in this scope
こんなこと言われたので、vi +395 src/swfmill.cpp して、適当な位置に extern const char* xslt_simple; 追加。

make
su
make install
ldconfig

2009年6月20日土曜日

Hamlしてみた

Haml

なんだか便利そう・・・だけどまだよく分からない。

sample.rb
require 'rubygems'
require 'haml'

e = Haml::Engine.new('%p= foo')
puts e.render(Object.new, :foo => "Hello World")

e = Haml::Engine.new('%p= yield')
puts( e.render do
'Hello World ' * 2
end )

FLEX BUILDER 3 をアップデート

Flex Builder 3 をアップデートしたら 3.0.2.214193 になった。

2009年6月17日水曜日

RoRのActiveRecord

SinatraActiveRecord使いたい。
あ、組み合わせとして使えないのではなくて、使ったことがないだけ。

Sinatraでアップローダー

Rubyスクリプト1つで書けるところが面白い。

app.rb
#!ruby
require 'rubygems'
require 'sinatra'
require 'sinatra/authorization'
require 'erb'
require 'fileutils'

helpers do
def authorization_realm; 'Private Zone'; end

def authorize(login, password)
login == 'id' && password == 'pw'
end
end

module Uploader
attr_reader :upload_path, :upload_dir
def initialize
@upload_path = 'files'
@upload_dir = File.join(Sinatra::Application.public, @upload_path)
end

def files
Dir.entries(upload_dir).select do |x|
!File.directory?(x)
end
end

def floor3(x)
(x * 1000).floor / 1000.0
end

def file_size(x)
s = File.stat(File.join(upload_dir, x)).size
case
when 1024 * 1024 < s
"#{floor3(s/(1024.0 * 1024.0))} M"
when 1024 < s
"#{floor3(s/1024.0)} K"
else
"#{s} bytes"
end
end
end

helpers Uploader

get '/' do
login_required
erb :index
end

post '/upload' do
if params[:file]
save_file = File.join(upload_dir, File.basename(params[:file][:filename]))
File.open(save_file, 'wb'){|f| f.write(params[:file][:tempfile].read)}
end
redirect '/'
end

get '/remove' do
if params[:file]
FileUtils.rm(File.join(upload_dir, File.basename(params[:file]))) rescue nil
end
redirect '/'
end

get '/logout' do
redirect '/' unless Rack::Auth::Basic::Request.new(request.env).provided?
response["WWW-Authenticate"] = %(Basic realm="#{authorization_realm}")
halt 401, 'Authorization Required'
end

get '*' do
redirect '/'
end

__END__

@@ index
<html>
<head>
<title>K</title>
</head>
<body>
<a href="/logout">logout</a>
<form method="POST" action="/upload" enctype="multipart/form-data">
<input type="file" name="file"><input type="submit" value="upload">
</form><%
files.sort.each do |x|
%><a href="<%=escape_html(File.join(upload_path, x))%>"><%
%><%=escape_html(x)%></a> (<%=file_size(x)%>)<%
%> <a href="/remove?file=<%=escape(x)%>">remove</a><br><%
end
%></body>
</html>

SinatraとSession

SinatraでCookieベースのSessionを使って認証。
sinatra-authorizationを調べる前に、とりあえず目的達成できそうな方法を模索してみた。

study_auth.rb
use Rack::Session::Cookie,
# :key => 'rack.session',
# :domain => 'takumakei.blogspot.com',
# :path => '/',
:expire_after => 3600,
:secret => 'changeme'

helpers do
def auth_ok?(id, pw)
id == 'id' && pw == 'pw'
end

def login
if auth_ok?(params['id'], params['pw'])
session[:login] = 'What should i have to put here ?'
redirect '/'
else
erb :login
end
end

def logout
session.delete(:login)
redirect '/'
end

def need_auth
unless session[:login]
erb :login
else
yield
end
end
end
app.rb
#!ruby
require 'rubygems'
require 'sinatra'
require 'erb'
require 'study_auth'

get '/' do
need_auth do
erb :index
end
end

get '/login' do
login
end

post '/login' do
login
end

get '/logout' do
logout
end

get '/*' do
login
end
index.erb
<html>
<head>
<title>index</title>
</head>
<body>
<%=Time.new.to_s%><br/>
<a href="logout">logout</a>
</body>
</html>
login.erb
<html>
<head>
<title>login</title>
</head>
<body>
<form action="login" method="POST">
<input type="text" name="id" value="<%=params['id']%>">
<input type="password" name="pw">
<input type="submit" value="LOGIN">
</form>
</body>
</html>

2009年6月16日火曜日

FlashコンテンツからFlash Lite 1.1コンテンツへの変換

最近の贅沢な高級言語からFlash Lite 1.1初心者になるといろいろ足りなくて困る。
後で読もう。
FlashコンテンツからFlash Lite 1.1コンテンツへの変換

Flash Lite 1.1 でカウントダウンしてみた

CountDown
//////////////////////////////////////////////////////////////////////
// 現在日時からXデーまでのカウントダウン
//
// 結果は4つの変数に算出する。「あと{dT}日と{HT}時間{MT}分{ST}秒」
//dT = 0; // 残り日数
//HT = 0; // 時間
//MT = 0; // 分
//ST = 0; // 秒
//////////////////////////////////////////////////////////////////////
// Xデー
yL = 2009;
mmL = 7;
dL = 7;
HL = 0;
ML = 0;
SL = 0;
//////////////////////////////////////////////////////////////////////
// 現在日時取得
yR =fscommand2("GetDateYear");
mmR = fscommand2("GetDateMonth");
dR = fscommand2("GetDateDay");
HR = fscommand2("GetTimeHours");
MR = fscommand2("GetTimeMinutes");
SR = fscommand2("GetTimeSeconds");
if(!yR){
debug_ = '現在時刻を取得できなかったYo';
stop();
}
//////////////////////////////////////////////////////////////////////
// Xデーを表示する。「年」を表示
yyyy_ = yL;
//////////////////////////////////////////////////////////////////////
// Xデーを表示する。「月」を2桁で表示
if(10 > mmL){
mo_ = '0' add mmL;
}
else{
mo_ = String(mmL);
}
//////////////////////////////////////////////////////////////////////
// Xデーを表示する。「日」を2桁で表示
if(10 > dL){
dd_ = '0' add dL;
}else{
dd_ = String(dL);
}
//////////////////////////////////////////////////////////////////////
// Xデーを表示する。「時」を2桁で表示
if(10 > HL){
hh_ = '0' add HL;
}else{
hh_ = String(HL);
}
//////////////////////////////////////////////////////////////////////
// Xデーを表示する。「分」を2桁で表示
if(10 > ML){
mi_ = '0' add ML;
}else{
mi_ = ML;
}
//////////////////////////////////////////////////////////////////////
// Xデーを表示する。「秒」を2桁で表示
if(10 > SL){
ss_ = '0' add SL;
}else{
ss_ = SL;
}
//////////////////////////////////////////////////////////////////////
// Xデーを2000年1月1日からの経過秒数に変換する。dtLが結果。
dtL = 0;
for(i = 2000; i < yL; ++i){
if((i % 4 == 0) ? ((i % 100 == 0) ? (i % 400 == 0) : true) : false){
dtL += 366;
} else {
dtL += 365;
}
}
switch(mmL){
case 2: dtL += 31; break;
case 3: dtL += 59; break;
case 4: dtL += 90; break;
case 5: dtL += 120; break;
case 6: dtL += 151; break;
case 7: dtL += 181; break;
case 8: dtL += 212; break;
case 9: dtL += 243; break;
case 10: dtL += 273; break;
case 11: dtL += 304; break;
case 12: dtL += 334; break;
}
if(2 < mmL && ((yL % 4 == 0) ? ((yL % 100 == 0) ? (yL % 400 == 0) : true) : false)){
dtL += 1;
}
dtL += dL;
dtL = (dtL * 24 * 60 * 60) + (HL * 60 * 60) + (ML * 60) + SL;
//////////////////////////////////////////////////////////////////////
// 現在日時を2000年1月1日からの経過秒数に変換する。dtRが結果。
dtR = 0;
for(i = 2000; i < yR; ++i){
if((i % 4 == 0) ? ((i % 100 == 0) ? (i % 400 == 0) : true) : false){
dtR += 366;
} else {
dtR += 365;
}
}
switch(mmR){
case 2: dtR += 31; break;
case 3: dtR += 59; break;
case 4: dtR += 90; break;
case 5: dtR += 120; break;
case 6: dtR += 151; break;
case 7: dtR += 181; break;
case 8: dtR += 212; break;
case 9: dtR += 243; break;
case 10: dtR += 273; break;
case 11: dtR += 304; break;
case 12: dtR += 334; break;
}
if(2 < mmR && ((yR % 4 == 0) ? ((yR % 100 == 0) ? (yR % 400 == 0) : true) : false)){
dtR += 1;
}
dtR += dR;
dtR = (dtR * 24 * 60 * 60) + (HR * 60 * 60) + (MR * 60) + SR;
//////////////////////////////////////////////////////////////////////
// Xデーと現在日時の差を計算して、{dT}日{HT}時間{MT}分{ST}秒にする。
if(dtL < dtR){
debug_ = 'もう過ぎてるYo';
stop();
}
dtT = dtL - dtR;
dT = int(dtT / (24 * 60 * 60));
HT = int((dtT / (60 * 60)) % 24);
MT = int((dtT / 60) % 60);
ST = int(dtT % 60);
//////////////////////////////////////////////////////////////////////
// Xデーまでの「日数」を4桁で表示
if(10 > dT){
dT_ = '000' add dT;
}
else if(100 > dT){
dT_ = '00' add dT;
}
else if(1000 > dT){
dT_ = '0' add dT;
}
else{
dT_ = String(dT);
}
//////////////////////////////////////////////////////////////////////
// Xデーまでの「時間」を2桁で表示
if(10 > HT){
HT_ = '0' add HT;
}
else{
HT_ = String(HT);
}
//////////////////////////////////////////////////////////////////////
// Xデーまでの「分」を2桁で表示
if(10 > MT){
MT_ = '0' add MT;
}
else{
MT_ = String(MT);
}
//////////////////////////////////////////////////////////////////////
// Xデーまでの「秒」を2桁で表示
if(10 > ST){
ST_ = '0' add ST;
}
else{
ST_ = String(ST);
}
//////////////////////////////////////////////////////////////////////

QRコードを表示してみた


QRcodeG.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
showStatusBar="false" paddingBottom="3" paddingLeft="3" paddingRight="3" paddingTop="3"
width="174" height="188"
minWidth="174" minHeight="188">
<mx:Script>
<![CDATA[
private const GOOGLE_CHART:String
= 'http://chart.apis.google.com/chart?chs=150x150&cht=qr&chl=';
private function create():void
{
var url:String = GOOGLE_CHART + encodeURIComponent(txt_.text);
qrImage_.scaleContent = true;
qrImage_.source = url;
}
]]>
</mx:Script>
<mx:HBox width="100%">
<mx:TextInput id="txt_" width="100%"/>
<mx:Button label="QR" click="create()"/>
</mx:HBox>
<mx:HBox width="100%" height="100%" horizontalAlign="center" verticalAlign="middle">
<mx:Image id="qrImage_" width="100%" height="100%"
source="icons/icon_128.png" scaleContent="false"
autoLoad="true" verticalAlign="middle" horizontalAlign="center"/>
</mx:HBox>
</mx:WindowedApplication>

2009年6月12日金曜日

Flash Lite 1.1 遊び始めました

Flashで遊び初めて2日目。
対象デバイスは携帯なので、Flash Lite。
複数バージョン存在するけれど、ひとつひとつ対応していられないのでFlash Lite 1.1をターゲットにするのが現時点での最適解みたい。
しかし、なんと制約が多いことか。
Flashの動的生成とか動的合成が不可欠なのね。

Sinatra + Passenger

さっそく遊び始めた。

2009年6月9日火曜日

Sinatra + Passenger

最近気になってること

2009年6月4日木曜日

ActionScriptでISO8601をDateに変換してみた

ちゃんとテストしてない。ていうか、ほとんどテストしてない。そのうえ作る時に考えてない。
parseIso8601
private static const ISO8601_RE:RegExp
= /^(\d{4})(-?(((\d{2})(-?(\d{2}))?)|(\d{3})|(W(\d{2})-?(\d)))([T ](\d{2})(:?(\d{2})(:?(\d{2})([,\.](\d+))?)?)?(Z|(([+-])(\d{2})(:?(\d{2}))?))?)?)?$/;
public static function parseIso8601(s:String):Date
{
var year:int = 1970;
var month:int = 0;
var date:int = 1;
var hour:int = 0;
var minute:int = 0;
var second:int = 0;
var millisec:int = 0;
var offset:int = 0;
var m:Array = s.match(ISO8601_RE);
if(!m) return null;
if(m[1]) year = int(m[1]);
if(m[3]) date = int(m[3]);
if(m[5]) month = int(m[5]) - 1;
if(m[7]) date = int(m[7]);
if(m[10] && m[11]){
var first:Date = new Date(year, 0, 1);
var w:int = (first.day == 0 ? 6 : first.day - 1);
date = 8 - w + (int(m[11]) - 1) + 7 * (int(m[10]) - 2);
}
if(m[13]) hour = int(m[13]) % 24;
if(m[15]) minute = int(m[15]);
if(m[17]) second = int(m[17]);
if(m[19]) millisec = int(m[19]);
if(m[20] && m[20] == 'Z')
return new Date(Date.UTC(year, month, date, hour, minute, second, millisec));

if(m[23]) offset = int(m[23]) * 60;
if(m[25]) offset += int(m[25]);
if(m[22] && m[22] == '-') offset = -offset;

offset *= 60 * 1000;
return new Date(Date.UTC(year, month, date, hour, minute, second, millisec) - offset);
}

列挙型がないAS3で列挙を使う


「ActionScript 3.0 は、C++ の enum キーワードや Java の Enumeration インターフェイスとは異なり、特定の列挙機能をサポートしません」

と書いてある。さらに、代替手段も記載されている。

一つ目の方法は「staticなパブリック定数(String型かint型かuint型)を定義する」というもの。

Flex3のイベント名が類似品だろう。
この方法だと、定義していない列挙をうっかり使ってしまったり、既に定義してある列挙値と同じ列挙値をうっかり違うものと思い込んで使ったりしてしまうという心配がある。

二つ目の方法は「staticなパブリック定数にクラスのインスタンスを入れる」というもの。

これを使ったコードはまだ見たことがなかったし、考えもしなかったのでなるほどと思った。
この方法だと、値のセットを任意の新しい型として作ることができる。
それでも、任意の列挙値を後から作れてしまう。
C++だとコンストラクタをprivateにしてインスタンスを作れないようにもできるのだが・・・。
day
public final class Day {
public static const MONDAY:Day = new Day();
public static const TUESDAY:Day = new Day();
...
}
nasty day
public final class NastyDay {
public static const GALACTICDAY:Day = new Day();
}

2009年6月3日水曜日

AIRでタスクバーに表示されないアプリケーションを作る


ウィジェットをAIRで作ってみたくなった。

ウィジェットがタスクバーに表示されていたら邪魔だから、タスクバーに表示されないようにしたい。
そのためにはウィンドウのtypeをlightweightにすればよい。

  1. ベースを<mx:Window>にしたカスタムコンポーネントを作りtype="lightweight"にする。
  2. (1)が閉じられたらアプリケーションを終了させるコードを書く
  3. アプリケーションファイルを<mx:Application>にして(1)を表示する

ウィンドウの位置を動かすためにnativeWindow.startMove()をmouseDownイベントのハンドラで呼び出す。このときmouseDownをカスタムコンポーネントで拾うと、イベントバブリングがあるので、全ての子コンポーネントのmouseDownを拾ってしまう。解決方法は、イベントバブリングを中断するという方法もあるのだろうけれど(...調べてないからやり方は分からない)、mouseDownを受け取るコンポーネントを配置する方法のほうが簡単だと思う(...知識は少なくても解決できたから^^)。

ちなみに、<mx:Application>を使う理由は、Flex Builder 3でAIRアプリのプロジェクトを作ると、アプリケーションファイルは<mx:WindowedApplication>になるのだが、このときウィンドウのtypeをlightweightにする方法を見つけられなかったから。

WidgetWindow.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Window xmlns:mx="http://www.adobe.com/2006/mxml"
maximizable="false"
minimizable="false"
resizable="false"
systemChrome="none"
showFlexChrome="false"
transparent="true"
type="lightweight"
layout="absolute"
width="100"
height="100"
close="exit()">
<mx:Script>
<![CDATA[
private function exit():void
{
NativeApplication.nativeApplication.exit(0);
}
]]>
</mx:Script>
<mx:Canvas width="100%" height="100%"
cornerRadius="8" borderStyle="solid" backgroundColor="#F3F3D1"
mouseDown="nativeWindow.startMove()" backgroundAlpha="0.7"/>
<mx:VBox horizontalCenter="0" verticalCenter="0" horizontalAlign="center">
<mx:Label text="Hello world"/>
<mx:Button label="close" click="exit()"/>
</mx:VBox>
</mx:Window>

Widget.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="init()">
<mx:Script>
<![CDATA[
private function init():void
{
new WidgetWindow().open();
}
]]>
</mx:Script>
</mx:Application>

2009年6月1日月曜日