2008年11月18日火曜日

Rainmeterのスキン、10-Foot HUDの天気予報カスタマイズ


Rainmeterは、時刻とかの表示ツールだけど、lifehacker.jpで紹介されてた10-foot HUDはいい感じ。壁紙に時計がくっつくみたいで便利。
いじると判るんだけど、結構癖がある。スキンと言うよりも、URLを指定して正規表現で情報を抜き出したりもできるっぽい。
Weather-BlackとかのEditしようとすると、.iniファイルが直接開かれてちょっととまどうので、以下にやってみた情報を出しておく。


まず、コメントが ; らしいことは見たら判る。次に、Weather.comでお天気コードを探せと言われる。
;Find your weather code at Weather.com (like UKXX0296 below) and replace the one in this URL.

色々やった結果、日本を指定してそっから近い場所を探すのがよさそう。(クリックしづらいので根気よく探そう)

たとえば青森だと天気予報のページは http://www.weather.com/outlook/travel/businesstraveler/local/JAXX0004 になる。
だから、青森はJAXX0004というお天気コードなのが判る。
あとは、Weather-Black.iniの該当箇所を書き換える。(Weather-White.iniも同じ)
URL=http://xoap.weather.com/weather/local/JAXX0004?cc=*&unit=m&dayf=6
&unit=mを抜くと華氏表示になるけど、日本人なら摂氏じゃないかな。だからそのままで良い。

あと、[MeterTemp]の所に、Postfix="ー"って表示があるけど、これどうも°が文字化けしてるっぽい。
Postfix="°"
こうしてやる。人によっては℃とかが良いかも。
(日本語表示させたいとかは、見たら判るはずだから省略。僕は、英語のままで使ってる)
***
Weather.comの書式が変わったらしい。追記を参考に修正して欲しい。



2008年10月21日火曜日

荷物の分類

整理のコツ。

4つの容器に、ラベルを貼る。
捨てる(Throw Away):要らないモノ。好きじゃないモノ。ぐちゃぐちゃと台所にあるもの。
あげる(Give Away):寄付か友達に--どちらにせよ、良いことだし要らないものをはき出せる。
しまう(Put Away):他の部屋に入る?でも持ってくために片付けを止めないで!寄り道するから。この箱に入れてあとでやろう。
とっとく(Keep or Toss?):ソレ、どうするか決まらない?この箱に入れてテストしよう:ソレについて考えないか探しにいかなければ、遠慮せずに放り出そう。毎月チェックしよう。
http://www.squidoo.com/homemaking
より抜き書き

これで整理が進む。ハズ。

2008年9月11日木曜日

batの威力

Windowsのコンソールでスクリプト走らせると、どうしてもスクリプト内で完結してしまいがち。
(pythonだとos.walkとかでフォルダの中を走査したり)

でも、bat使って連続してファイル読み込ませると、状況見ながらリファクタリングできることに気がついた。
なんかボトルネックになってるところを発見したときに、そこを直すと、次に実行されるときには治ったやつが実行されるので便利。

for %%A in (%1) do python hoge.py < %%A
とか覚えとくと便利。

for %%A in (%2) do %1 < %%A
は、うっかり変なコマンド走らせて吃驚したのでやらない方が良さそう。

2008年9月9日火曜日

PythonでSQLiteを使う(データを書き込む)

・データを書き込む

カーソルを作成したので、データベースにテーブルを作る準備ができました。テーブルの作成には、必要なステートメントを入れて、カーソルからexecuteメソッドを呼ばなければなりません。名前(name)とメアド(email)を保存するテーブルを作ってみましょう。ついでに、それぞれの列(row)に、ユニークな番号を振るようにもしてみましょう:

>>> cursor.execute('CREATE TABLE names (id INTEGER PRIMARY KEY, name VARCHAR(50), email VARCHAR(50))')

これでテーブルが出来ました。同様にして、データの追加もexecuteメソッドで行うことが出来ます:

>>> cursor.execute('INSERT INTO names VALUES (null, "john Doe", "jdoe@jdoe.zz")')
>>> cursor.execute('INSERT INTO names VALUES (null, "Mary Sue", "msue@msue.yy")')

カーソルから、最後に登録した列(row)番号を得ることも出来ます。たぶん必要でしょう:

>>> cursor.lastrowid
2

そうそう、「ユーザの入力に応じてデータベースに入れたい」と言うでしょ。明らかに、ユーザの入力はそのままでは危ないです。悪意あるユーザは、簡単にクエリーを操ってデータベースに通せるし、深刻なダメージをデータベースに与えることが出来ます。これは許容できません。でも、ありがたいことにpysqliteにはセキュリティを確保する手段があります。ある人の名前(name)とメアド(email)を、2つの変数で持っているとしましょう:

>>> name = "Luke Skywalker"
>>> email ="use@the.force"

このとき、(自分たちで定義したんだから)これらはまあ安全です。でも、いつもそうだとは言えないでしょう。安全なクエリーに変数を入れたい時は、単にその場所にクエスチョンマークを入れればいいだけです。すると、pysqliteが残りをやってくれます(paramstyleを参照のこと):

>>> cursor.execute('INSERT INTO names VALUES (null, ?, ?)', (name, email))

今、私たちは変更を加えたので、保存しなければなりません。(もしくは、データベースに変更を通知しなければなりません)これには、コネクションのcommitメソッドを呼び出します:

>>> connection.commit()

もしも、変更したにもかかわらずcommitを呼ばず、コネクションを閉じようとすると、pysqliteはエラーを返すでしょう。こういう行動は、トラブルのもとになります。でも、やってしまった変更を保存したくないときもあるでしょう。そんなときは、rollbackメソッドを使います。(色々保存せずに電源を切るというやり方もありますけど)例えば、もう一列テーブルに加えるとしましょう:

>>> cursor.execute('INSERT INTO names VALUES (null, "Bobby John", "bobby@john.qq")')

この変更を無かったことにしたい、としましょう。我々は単にrollbackメソッドを呼べば良いのです:

>>> connection.rollback()

ほら、これで変更は消えました。
次のステップでは検索をしてみましょう。

2008年8月12日火曜日

パノラマ写真に関して

単一のレンズで全方位を映せるレンズをオリンパスが出してるが、これからはいろんなレンズで撮った画像を1枚にまとめられる技術の方が重要なのではないだろうか。
その手の技術は、技術者には普通のことなんだろうけれども、あんまりよく知らなかったので調べてみよう。

パノラマ写真をつくる
技術としてのSIFTに関して

・パノラマ写真を作るで紹介されているソフト
  1. autopano-sift
  2. hugin
  3. Enblend
説明をざっと見た感じでは、autopano-siftで特徴点の算出、huginで画像の変形、Enblendで画像の合成を行っているようだ。
何れもLinux版、Windows版ともにある。フリーでこういうものが開発されてるのはすごいなあ。見習いたい。
SIFTとか画像処理の根幹の部分は、こらからさらに重要になってくるような気がする。音声処理も。素人が処理できるレベルまでPCのスペックが上がってきてるので楽しそう。データマイニングも面白そうだし。

2008年7月15日火曜日

javascriptでクロージャ

クロージャとか、無名関数とか、引数として関数を渡すとか、javascriptって色々できるな。
難しそうだからさわってなかったけど、その場だけでごりごり書くときに便利そう。


/* New document created: 6.2.2008 18:34:27 */

function map(fn, a)
{
for (i = 0; i < a.length; i++)
{
a[i] = fn(a[i]);
}
}

function reduce(fn, a, init)
{
var s = init;
for (i = 0; i < a.length; i++)
s = fn( s, a[i] );
return s;
}

function sum(a)
{
return reduce(function(x, y){ return x+y; }, a, 0);
}

function cntYear(x) //Closure
{
var i = 0;
return function()
{
i = i + 1;
return x + i;
}
}

var a = [1, 2, 3];
map( function(x){return x*2;}, a );
map( alert, a );

years = new Array(400);
map( cntYear(2008), years );
map( function(x){ if(x%400==0 || x%100!=0 && x%4==0){return 1;}else{return 0;} }, years);
alert(sum(years));

2008年7月7日月曜日

13日は何曜日が多い?

13日の金曜日を見ていて「金曜日が最も多い」というが気になって確認してみた。


import calendar

MON, TUE, WED, THU, FRI, SAT, SUN = 0, 1, 2, 3, 4, 5, 6
dict = {MON:0, TUE:0, WED:0, THU:0, FRI:0, SAT:0, SUN:0}
for y in range(2008, 2408):
for m in range(1, 13):
w = calendar.weekday(y, m, 13)
dict[w] = dict[w] + 1
print dict

実行すると、以下のような結果に。
http://codepad.org/MuBsSX7M

{0: 685, 1: 685, 2: 687, 3: 684, 4: 688, 5: 684, 6: 687}

金曜日が688回、水・日が687回、月・火が685回、木・土が684回と言う結果に。

2008年7月2日水曜日

pythonでtwitterクライアント。コマンドプロンプト版。

作ったやつを張っとこう。
ざっくり判った。twitterのAPIは簡単で判りやすい。json便利。


Windowsならではの小細工が。
でもこれcmdで立ち上げとくと便利。メモ代わりにどんどん書き込める。

# -*- coding: utf-8 -*-

'''
twitter
friends timeline post
'''
import urllib, urllib2
import json
import calendar
import time
import sys

toplevel_url = 'twitter.com'
target_url = 'twitter.com/statuses/update.json'
protocol = 'http://'
proxy = {'http':'http://hogehoge.com:80/'}
username = 'hogehoge@gmail.com'
password = 'xxxxx'

proxy_handler = urllib2.ProxyHandler(proxy)
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, toplevel_url, username, password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(proxy_handler, authhandler)
urllib2.install_opener(opener)

def twitter_post(text):
params = urllib.urlencode({'status':text.encode('utf8')})
#print params
urllib2.urlopen(protocol + target_url, params)

def twittertime2time(created_at):
unix_time = calendar.timegm(time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y'))
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(unix_time))

while ( True ):
utext = raw_input('What are you doing?: ')
text = unicode(utext, 'mbcs')
twitter_post(text)



毎分チェックに行く方

# -*- coding: utf-8 -*-

'''
twitter
friends timeline loop_get
'''

import urllib2
import json
import calendar
import time
import shelve, sha

SLEEP_TIME = 1 * 60
HISTORY_FILE = 'tw.log'
toplevel_url = 'twitter.com'
target_url = 'twitter.com/statuses/friends_timeline/screen_name.json'
protocol = 'http://'
proxy = {'http':'http://hogehoge.com:80/'}
username = 'hogehoge@gmail.com'
password = 'xxxxxxx'

proxy_handler = urllib2.ProxyHandler(proxy)
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, toplevel_url, username, password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(proxy_handler, authhandler)
urllib2.install_opener(opener)

def twittertime2time(created_at):
unix_time = calendar.timegm(time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y'))
return time.strftime("%b %d %H:%M:%S", time.localtime(unix_time))
#return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(unix_time))

def memory_log(time, text):
FLG = True
log = shelve.open( HISTORY_FILE )
s = sha.new( text.encode('utf-8') )
if ( not log.has_key( s.digest() ) ):
log[ s.digest() ] = time
FLG = False
log.close()
return FLG

def print_twitt(contents):
for content in contents:
if ( not memory_log(content['created_at'], content['text']) ):
print twittertime2time(content['created_at']), content['user']['screen_name'], content['text']

while ( True ):
pagehandle = urllib2.urlopen(protocol + target_url)
json_contents = pagehandle.read()
contents = json.read(json_contents)
print_twitt(contents)
time.sleep( SLEEP_TIME )
print '.',

ベリサインは何を見てる?

公開鍵証明書について調べてるときに、気になった。
有名なベリサインは何を持って証明書を発行するのか。
発行先を確かにその発行先だと証明するために何を調査するのか。
それは、結構クリティカルな部分じゃないのかなあ。

で、結局第三者がまとめたデータベースから、その会社の代表電話番号を持ってきて、そこにかけると。
で、技術担当者に電話で確認すると。
後は、登記事項証明書を郵送することで確認する。
(法人じゃないと、士には出してるらしい。弁護士とか)その場合、証明するのは印鑑証明。

つまり
1.第三者がまとめたデータベースの電話番号と、実際の企業電話番号との一致
2.申請書と、技術担当者の在籍&申請意志との一致
3.登記事項証明書(or 印鑑証明)による申請者の身分保証
の3点で確認してるわけだ。

つまり、攻撃は2点必要。
1.第三者(帝国データバンクっぽい)のデータベース
2.登記事項証明書(or 印鑑証明)
両方が攻撃できれば、その本人でなくても証明書を発行してもらえる。


…気がついたときの証明書無効の方法も調べておかないとなあ。
参考:
名古屋工業大学大学院おもひ領域 情報工学専攻 岩田研
.p12の証明書が流出するとなりすまされるとかベリサインが書いてて何言ってんだろうと思ったけど、
証明書に秘密鍵がくっついてるファイルなんてのがあるのね。ということが一覧で判って便利。

urllib2でproxyを使うには

urllib2を使ったpythonのスクリプトは結構便利なのが多い。
でも、プロキシ使ってると通らないのが多い。
以下のコードを加えると、特に手を加えなくてもproxy使えるので、メモ。


proxy = {'http':'http://hogehoge.com:8080/'}
proxy_handler = urllib2.ProxyHandler(proxy)
opener = urllib2.build_opener(proxy_handler)
urllib2.install_opener(opener)

2008年7月1日火曜日

発作的にtwitter クライアントをpythonで実装してみる

なんとなくで出来た。pythonってすごいなあ。
urlib2が便利すぎる。

参考:
perlでの実装例
jsonのパージの仕方
twitterAPI DOC
urlib2でプロキシ通すとき参考にした
twitter時間を日本時間に直すとき使った もいっこ時計型
python辞書型
時間の処理だけ参考にしたpython実装

'''
twitter
friends timeline get
'''

import urllib2
import json
import calendar
import time

toplevel_url = 'twitter.com'
target_url = 'twitter.com/statuses/friends_timeline/screen_name.json'
protocol = 'http://'
proxy = {'http':'http://hogehoge.com:8080/'}
username = 'hogehoge@gmail.com'
password = 'xxxxxxx'
proxy_handler = urllib2.ProxyHandler(proxy)

passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, toplevel_url, username, password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(proxy_handler, authhandler)
urllib2.install_opener(opener)
pagehandle = urllib2.urlopen(protocol + target_url)
json_contents = pagehandle.read()
contents = json.read(json_contents)

def twittertime2time(created_at):
unix_time = calendar.timegm(time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y'))
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime(unix_time))

for content in contents:
print twittertime2time(content['created_at']), content['user']['screen_name'], content['text']
# for k, v in content.iteritems():
# print k, v
# if k == 'user':
# for uk, uv in v.iteritems():
# print uk, uv

# print contents

驚くくらいjsonの解説が少なくて吃驚。ググり方が悪いのか。
また、twitter APIの戻り値(jsonで渡される中身の数々)に関しても、情報が無い。
取り敢えずcreated_atが作られた時間、userの中に入れ子で色々入ってて、textには本文が入ってる。
以下取れる情報を列挙しとこう。後日何が何かを調べよう。

favorited
truncated
text
created_at
source
in_reply_to_status_id
in_reply_to_user_id
id
user
name
url
profile_image_url
screen_name
followers_count
protected
location
id
description

とりあえず取れるのはこんなところ。

2008年6月27日金曜日

Google App エンジン AU対応!

こないだまで出来なかったけど、@ezweb宛にメール送ってくれるようになってる…
これで開発できるぞー

http://code.google.com/intl/ja/appengine/

この辺にドキュメントが。メール受けたり送ったりも出来るし、至れり尽くせり。
個人のWeb開発だと、もうこれ一本で十分だなあ。
http://code.google.com/appengine/docs/whatisgoogleappengine.html

この辺読みながら、ぼちぼちやってみよう。夏休み前までに一本データベース使うアプリ作りたいなあ。
http://code.google.com/intl/ja/appengine/docs/gettingstarted/

2008年4月30日水曜日

PythonでSQLiteを使う(データベースへの接続)

・データベースに接続する

 pysqliteを使う準備が出来てますね?まだなら前のステップへ。
 Pythonを対話モードで起動して、早速ライブラリーを使ってみましょう。インポートすれば使えます。(pysqliteは、いろんな系列やapiがありましたが、SQLiteバージョン3用になってpythonに同梱されてからは、pysqlite3で統一されました)インポートは、sqlite3という名前でします。

>>> import sqlite3

 これで、pysqliteを使う準備が出来ました。
 まず、作業用の新しいデータベースを作ってみましょう。作るには、コネクションオブジェクトをつくって、データベースファイル名を指定します。(もしデータベースファイルが存在しなければ作成され、存在すればそれをオープンします)

>>> connection = sqlite3.connect('test.db')

メモリ上に、一時的なデータベースを作ることも出来ます。

>>> memoryConnection = sqlite3.connect(':memory:')

コネクションオブジェクトを得たら、何かするためにカーソルオブジェクトを作らなければなりません。作るには、コネクションオブジェクトから、カーソルメソッドを呼びます。

>>> cursor = connection.cursor()


以後、このカーソルを使ってデータベースを操作します。
では次のステップではデータを書き込んでみましょう

PythonでSQLiteを使う(データベースのインストール)

 Python2.5でデータベースを使うときに真っ先に考えつくのがSQLite。(Python2.5に元々入ってるから何もしなくても使える)2.4までは入ってなかったので、情報が少ない。せっかくなので使い方の紹介をしようと思います。

 SQLiteは、Cの小さなライブラリで、データベースエンジンとして十分な機能を持っています。Pythonには、pysqliteというSQLiteのインタフェースとして使えるライブラリがあって、Python2.5からは標準ライブラリになっています。

 SQLiteは小さなデータベースエンジンで、アメリカでは結構な人気が(ちゃんとその人気に値する実力も)あります。SQLiteはスタンドアローンで動いて、依存関係はありません。データベースのデータは、単一のファイルに保存されます。煩わしい設定ファイルはいらないし、サイズは小さいし、多くのアプリに組み込めるし、結構早いです。さらにパブリックドメインでリリースされています。

 pysqliteでSQLiteを使うのは簡単です。実際にやってみましょう。簡単なサンプルを通して、SQL構文そのものに慣れ親しむことも出来ます。

・まず、ライブラリーを手に入れる。
Python2.5以降には、同梱されています。次のステップへ。

もしも、2.4.1までのPythonを使っている人が居たら、これを機に、Python2.5にするのをお薦めします:-)

いろんな理由でPython2.5に出来ない方は、以下のウェブサイトからライブラリーを入れましょう。
http://initd.org/tracker/pysqlite

Windowsユーザなら、ダウンロードしてインストールするだけで動きます。(SQLite本体も同梱されています)

Linuxユーザだと、ディストリビューション毎のソースを落としてきて入れるのにあわせて、SQLite本体も必要かもしれません。ただ、多くのディストリビューションでは、SQLiteは既に入っているはずです。チェックしてみてください。もし入っていなければ、SQLiteは以下のウェブサイトから得られるハズです。
http://sqlite.org/

他の多くのPythonライブラリーと同じように、このライブラリーもインストールできます。まずライブラリーをビルドします。

python setup.py build

次に、インストールしましょう。インストール権限があるかは確認しておいて下さい。

python setup.py install

もし全部出来たら、pysqliteはインストールされて、使えるようになっています。
では、次のステップへ行きましょう。

2008年4月11日金曜日

FFCCの収益予想(小さな王様と約束の国)

 Wiiは国内で400万台売れているらしい。そのうちネットに繋がっているのは200万台。感覚的にも半分くらいはネットに繋がっていない(半分はつなげている)というのは納得できる数値だと思う。じゃあこのうちお金を払ってVCを買う人はどのくらいだろう。半分は買わないだろうけど、10分の1くらいじゃないだろうか(仮定1)
 FFCCは1500円だから、おおよそWiiソフト1/3の値段だ。VCとしては高いけど、Wiiウェアという新作ソフトの値段としてはまあまあだと思う。RPGが好きな人ばかりではないだろうから、やっぱり1/10くらいの人が買うんじゃないだろうか(仮定2)
 すると、200万台 x 10% x 10% = 2万本くらいは売れてるんじゃないかなあと言う予想になる(予想1)
 どうやらWiiウェアの任天堂の取り分は、3割のようだ(仮定3)まあ流通だとかなんだとか考えたら、妥当なラインのような気がする。すると、2万本 x 1500円 x 70% = 2100万円となる。(予想2)

 なんかずいぶん少ない気がする。実験プロジェクトだから収益がとんとんでも構わないとする事も出来るけど、一回出しちゃったら同じ値段でしか売れない(高くなるのはどうなのよ)気がする。からちゃんと採算ベースに乗ってるのじゃないかな。人件費の10%の売り上げがあったら良しとするのはどうだろう。(仮定4)若手の育成かつ、ブランド認知でお金が稼げるなら御の字、とか。すると、1909万円 x 110% = 2100万円となるので、1909万円が人件費になる。(予想3)
 開発スタッフが色々と出てくるけど、まあまあ1人平均月30万円としてみる。(仮定5)だと、1909万円 / 30万円 = 63人月。(予想4)半年ぐらいのさっくり開発だってインタビューもあったから、だいたい10人で半年で作ったことになる。まあ、スタッフロールから推定できる(6ヶ月まるまる働いてる人は少ないだろうし)人数と近い気がする。(予想5)
 おおよそ、10人のスタッフが半年で、2万本の売り上げのソフトを作ることが目標だったんじゃないだろうか。

 さらに、追加ダウンロード販売(DLC)を考えてみよう。仮定した2万本の売り上げが正しいとして、ダウンロードするのはどのくらいの数だろう。100円~800円といっても(Wiiでは初めての追加課金だから)追加課金になれていない人が多いだろうし、元値が1500円のソフトに800円払えるかどうかはその人次第だ。面白いから良いと思う人であれば買うだろうし、嫌な気分になった人も居るだろう。これはじゃあ1/3ぐらいは何かしら買うとしよう(仮定6)
 すると、2万本 x 30% = 6000人がDLCをするという事になる。(予想6)
 中身によるけれども、FFCCの場合、新しいダンジョンの追加(300円)、種族の追加(セットで800円)がある。これはいくらの売り上げになるだろうか。たとえばダンジョンのみ買う人ばっかりだと、6000人 x 300円 x 70% = 126万円の売り上げになる。たいしたことはなさそうだけど、実は元々2100万円の売り上げ予想だったので、6%にあたる。300円のDLCを16本だすと、だいたい本体を売り上げたのと同じくらいの売り上げが見込める。ダンジョンの追加はデータ作成が楽だろうから、これはかなり人件費を引いても儲かるんじゃないだろうか。
 逆に、コスチュームチェンジの100円はどうだろう。これも1/3が買うとして、6000人 x 100円 x 70% = 42万円。これはだいぶ少ない。原画→モデリング→販売が1週間ぐらいのタスクだとして8万円ぐらい。1着34万円の売り上げ。けっこう稼ぐように見えるけど、全然小さい。会社の仕事じゃなくて個人的な趣味なら稼ぐ方なんだろうけど。会社の売り上げには貢献しないような気がする。

ただ、3つの仮定が非常に重要である。
1.「200万台 x 10% x 10% = 2万本」
2.「2万本 x 30% = 6000人」
3.「任天堂の取り分は3割」
これのどちらかが違うと、結果もかなり異なる。

 例えば、すごく売れるとする。200万台のうち、ダウンロード販売をするひとがほとんどで、そのほとんどがFFCCを買った(面白いから・評判がよいからとじわじわ売れる可能性はある。店頭と違って販売機会喪失は0に近いから)とする。すっごくうれて20万本売れたとする。これで2億円の売り上げだ。人件費が仮定通りだとすると、会社は1億8000万近く儲けた事になる。これは十分商売になる。コスチュームも充実してきて半分くらいの人が買うとする。10万 x 100円 x 70% = 700万円。これは例えば10着作れば半分くらいの人はどれか一着を買うという前提に立っても、まあまあ儲かる。1着10万円のタスクで100万円。600万円の売り上げなら、まあ継続的な商売になる。

 というわけで、普通に2万本くらい売れると、社員教育+経験+ブランド認知が出来るという事になる。(たとえば駆け出しのデザイナーとかモデラーを使っても、そんなに悪くないだろう)
 すごく売れて、20万本とかになると、会社は大もうけできる。
 これは、スクエアエニックスにとってプラスにはナリこそスレ、マイナスにはならない。(1万本しか売れないと足がでるんじゃないかな。5人で半年で作ってればやはりそれでも問題ないけど)

***

 また逆に、3人で3ヶ月で作るミニゲームなら何本売れればよいか、なんてのも計算できる。30万 x 3人 x 3ヶ月 = 270万円。任天堂の取り分を考えると、386万円の売り上げでとんとん。300円のゲームにしたら1万3000本売れればよい。こりゃきついかも。じゃあ600円なら?6500本でいい。これならまあ無理じゃないかも。面白そうならもっと売れるだろうし。
 たとえば、ワリオみたいなミニゲームを3人チームで1日1個つくれ!みたいな社内公募があって、100個で売りに出すとする。100個のミニゲームが600円なら、僕は買う。30個でも買うかもしれない。30個なら1ヶ月で出来るかも。なら300円でも儲かる。3人 x 1ヶ月 = 90万円, 300円 x 70% = 210円, 90万円 / 210円 = 4300本売れれば良い。300円で30個のミニゲームなら売れるだろう。

 結果、Wiiウェアだとちっちゃいゲームをクイックに安く提供することが勝利の鍵だというのが判る。5000円のゲームを1年書けて開発するより、300円のゲームを3週間で作る方が良い。また棲み分けが出来ているとも言える。Wiiウェアでは5000円のゲームを作るのは不合理だし、300円のゲームを作っても儲かる環境が出来てる。
 買う人も安く買える。作る方も楽に作れる。会社はゲームクリエイターに経験を積ませることができるし、ゲーマーも新しいゲームを結構な頻度で遊べる。300円なら、ちょっと毛色の違うのも遊んでみようかな、という気になるし。

 というわけで、Wiiウェアというのはなかなか面白い環境(売れれば儲かるし、Wiiウェアを買うマニアックな人が5000人も居れば市場として成り立つ)だと言える。

***
あとで追加すること
・400万台売れたとする資料にリンクすること
・200万台はネットに繋がってるとする資料にリンクすること
・3割が任天堂の取り分だとする噂にリンクすること
・開発期間のインタビュー記事にリンクすること
・販売本数とか数値があったら、探してリンクすること

2008年4月3日木曜日

帳票を作ってみた

申請書類をReportLabで作ってみた。そう難しくはない。
ただし、目的の申請書類専用のハードコーディングになる。データベースと連携させて自動で帳票を出力したいとか、印刷の見栄えを制御したいとかでなければ使わないかも。
Webサービスに組み込むのは印刷機能との連携で面白いかもしれない。HTMLの印刷制御って難しいし。(というか、自分のWebサービスには組み込む予定)

変換ツールは作るの面倒そうだから市販ソフト使った方が良い。ハナからpdfを作りたいならやっぱりそれ専用のツールが良いと思う。(あるとすれば自分のサーバに仕込んでおいて、出先で使うとか。便箋とかノートとかToDoリストを出先で印刷する機会があれば)
自分で作ったソフトで、なんか紙に出力する予定がある場合には覚えておくと良いかもしれない。

ReportLabはドキュメントじゃなくてソースを読め

結局、ドキュメントを探すよりソースを読むのが一番早かった…
Python25\Lib\site-packages\reportlab\libとかに入ってる、styles.pyとか読むとよくわかる。(結局ソース見ればわかる話だし、ドキュメントはいらないって事なのかな)
StyleSheet1()クラスは、

def __init__(self):
def __getitem__(self, key):
def has_key(self, key):
def add(self, style, alias=None):
def list(self):

てなメソッドを持ってる。辞書型じゃないのね。でもキーは拾えると。

getSampleStyleSheetで拾えるスタイルは、

'Normal', 'BodyText', 'Italic', 'Heading1', 'Title', 'Heading2', 'Heading3', 'Bullet', 'Definition', 'Code'

の10種類だった。結局こりゃサンプルだから、自分で定義して使えって事みたい。

イメージ的にはTeXが一番近いかな。残念ながら横着は出来ないという結果になりました。
(でもSampleのを書き換えて使う予定。楽なんだもの)

簡単なParagraphStyleの定義方法

よくよく調べると、parentを指定するとその内容を引き継げることが判った。


stylesheet.add(ParagraphStyle(name='BodyRightText',
parent=stylesheet['BodyText'],
alignment=TA_RIGHT) )

とかすると、BodyTextの内容を引き継いで、上書きすることが出来る。
もちろんParaStyle.fontName = "HeiseiMin-W3"とかってやり方もできる。直接書き換えてしまう。

でも、親を引き継いで新しく指定する方がスマートな気がする。
しかし、HeiseiMin-W3とHeiseiKakuGo-W5しか無いのがなあ。まあadobeがフリーで出してる言語パックだし仕方がないが…

ReportLabで使えるSampleStyleSheetのstyle名

結局、サンプルスタイルシートはサンプルでしかないのか。
自分で作れって事なのかもしれない。

from reportlab.lib.styles import getSampleStyleSheet
styles = getSampleStyleSheet()
TitleStyle = styles['Title']
HeaderStyle1 = styles['Heading1']
HeaderStyle2 = styles['Heading2']
HeaderStyle3 = styles['Heading3']
#HeaderStyle4 = styles['Heading4']
#HeaderStyle5 = styles['Heading5']
#HeaderStyle6 = styles['Heading6']

ParaStyle = styles['BodyText']
#ParaCenterStyle = styles['BodyCenterText']
#ParaRightStyle = styles['BodyRightText']
#IndentStyle = styles['Indent']
BulletStyle = styles['Bullet']
# new styles
#IndentIndentStyle = styles['IndentIndent']
#BulletIndentStyle = styles['BulletIndent']
PreStyle = styles['Code']

結局、'Title', 'Heading1', 'Heading2', 'Heading3', 'BodyText', 'Bullet', 'Code'sしか定義されてない。

     stylesheet.add(ParagraphStyle(name='BodyRightText',
parent=stylesheet['BodyText'],
alignment=TA_RIGHT) )


みたいな形で定義してやるしかないのかも。日本語だから結局そうなるんだけどね。
ただ、一回作ってやれば後々まで応用が利くので、暇なときに作り込むのも良いかもしれない。

ReportLabのStyleSheetについて

わーいHelloWorldかけたーじゃなくて、まともにpdfを作ろうとすると、ParagraphStyleを使いたくなる。
日本語だと、せっかく定義されてるParagraphStyleが使えないのは、前述の通り。
…そもそも、英文のParagraphStyleの一覧自体がreference.pdfに載っていないというとんでも具合。
reportlab-usersのMLアーカイブで見つけた。

platypus examples in version 1.2って書いてあるので古いんだろうけど。

styles = get_stylesheet()

TitleStyle = styles['Title']
HeaderStyle1 = styles['Heading1']
HeaderStyle2 = styles['Heading2']
HeaderStyle3 = styles['Heading3']
HeaderStyle4 = styles['Heading4']
HeaderStyle5 = styles['Heading5']
HeaderStyle6 = styles['Heading6']

ParaStyle = styles['BodyText']
ParaCenterStyle = styles['BodyCenterText']
ParaRightStyle = styles['BodyRightText']
IndentStyle = styles['Indent']
BulletStyle = styles['Bullet']
# new styles
IndentIndentStyle = styles['IndentIndent']
BulletIndentStyle = styles['BulletIndent']



PreStyle = styles['Code']

って事らしい。
もちょっと探してみよう。絶対リファレンスには載ってると思うんだがなあ。

2008年4月2日水曜日

ReportLabを使ってみる

pythonでpdfを作成しようとするとひっかかるReportLab
http://www.reportlab.org/

Reportというだけあって、英文であれば簡単にPDFのレポートが作成できそう。報告書とか見栄えを気にしないような書類を作成するのは楽ちん。
問題は日本語。「ReportLab Library is 2.1.」だと、特に問題なく日本語の作成までは通る。
Windowsでやってみてるから、「Precompiled DLLs」もダウンロードして使ってみた。Python2.5版を使った。
(ReportLab Toolkit Version 1もダウンロードできるけど、紛らわしいから止めて欲しい。それでハマった)
Acrobatのフォントを探してきて使えるようにしてくれる。Version 1はAcrobatの5までになってて、ハマりがち。Version2.1.だと、Acrobatの9まで自動で探すようになってる。
\Python25\Lib\site-packages\reportlabのrl_config.pyのなかの、~SearchPathでフォントを探してるので(CMapSearchPathとか)、そこを確認したら使えるかも。Acrobat10とか使う頃にはReportLabもヴァージョンアップしてるだろうけど:-)


from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.pdfbase import pdfmetrics

をインポートして
pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5'))
をセットしておくだけで、基本的には使える。
ただ、使えるだけじゃ意味がない。

from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Paragraph, SimpleDocTemplate
from reportlab.lib.pagesizes import letter
styles = getSampleStyleSheet()
styleN = styles['Normal']
styleH = styles['Heading1']
story = []
story.append(Paragraph("This is a Heading",styleH))
story.append(Paragraph("This is a paragraph in Normal style.", styleN))
doc = SimpleDocTemplate('mydoc.pdf',pagesize = letter)
doc.build(story)

とかで、英文であればあっさりそれっぽいPDFが作成できる。正直、グラフや表を使わない報告書ならこれで十分対応できる。

日本語だと

from reportlab.lib.styles import ParagraphStyle
styleJ = ParagraphStyle(name='Normal',
fontName='HeiseiKakuGo-W5',
alignment = 0, #or TA_LEFT, TA_CENTER, TA_RIGHT of 0, 1, 2
fontSize=10,
leading=12)

とかで、スタイルを定義してやる必要がある。仕方がないんだが面倒だなあ…
(定義してやれば、Paragraphでちゃんと書き出してくれる)

表組みを使うときも、英字であればちゃんと「右寄せ」とか「中央寄せ」とか通るのに日本語だと通らない。(Paragraphで右寄せ中央寄せは通る。だから、Paragraphで定義してやって表組みするのが正解)

pythonでなんか大量にpdfにしたいとかなら便利かも。ただ、通常はフリーソフトとか良いのがいっぱいあるし、そっち使うのが無難かと思う。組み込み向けかなあ。