トップ 最新 追記

ヨタの日々

2001|08|09|10|11|12|
2002|01|02|03|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|12|
2024|01|02|03|04|

2010-08-01 :-)

_ 読書

2010年7月19日 - 2010年7月25日の読書メーター
読んだ本の数:0冊
読んだページ数:0ページ


読書メーター

_ 朝ッ

0400 起床

_ チャリったー

なるほど曇りじゃねーの

img_1249.jpg

img_1251.jpg

_ [リッジレーサー7]リッジレーサー7 チームANS新メンバー

brother さん、KAI さんが新たにチームANSに加わりました。

今後ともヨロシク

_ 買い物

@PlayStation Store

未プレイなので買ってみた。1999年の作品か....

聖剣伝説 ~LEGEND OF MANA~

_ Distant World 犬耳家先行予約落選した

さて

_ [Rita]りたのじかん Rita's Hour 15 -wave of sound-

@晴れたら空に豆まいて

Rita はさっぱり馴染みがないのだけど前の前の上司が「 最近は霜月はるかじゃなくて Rita を聞くなどしている 」と言っていたのでせっかくだから申し込んでみたら当選した次第。Rita は関西人だった。

ライブでのアコギいいわあ。いやよく分からないけど。

本日のツッコミ(全6件) [ツッコミを入れる]

Before...

_ みわ [おお。ありがとうございます。e+の先行予約は今日からだったんですね。さっそく申し込みました。11/6のみですが ( ̄..]

_ ちくわん [LEGEND OF MANAはオヌヌメですのよ。 自由度高いから好きなように遊べます(^^]

_ みわ [自分でマップを作っていくんですねい わりとフリーシナリオの味があるのかしら]

_ ちちちくくくわわわ [なんといっても武器改造&モンスター育成ですな。 やり方によっては化け物じみた武器&モンスターになります。(^^]

_ みわ [さっぱり分からないけど「ラグナロク」「ドラゴンバスター」といった武器は生成できるとみた。]


2010-08-02 :-(

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

残業あわー

2030 退勤

_ id:youichi ( @yo_1 ) が「\茅原実里/」と言っている

私の周囲には訓練された茅原実里ファンが居るんだが私自身は属性持ってない。


2010-08-03 :-(

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

デモ第2弾準備

_ ,

茶太の歌声に胸キュンしてるので夏コミ周辺について眺めてみたんだが

夏コミ参加作品情報 - 茶太屋

案の定 多かった。

_ s/ラ・チャター/ラー・チャター/g

ガンダムシリーズの登場艦船及びその他の兵器一覧 - Wikipedia

クラップ級軽巡洋艦(宇宙巡洋艦)
クラップ、ラー・エルム、ラー・キェム(ラー・ギエム、ラー・ケイム)、ラー・ザイム(ラー・カイム)、ラー・チャター

間違えて覚えていた。

_ リッジレーサー7依存症

リッジレーサー7 を始めてから生活がリッジレーサー7漬けになった。あれは麻薬だ

_ [Template Method][Python][デザインパターン]Python でデザインパターン - Template Method

書き換え[ 20090508#p06 ]

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Head First デザインパターンを写経する - 8章 Template Method パターン - ヨタの日々(2009-05-08)
# http://www.area51.gr.jp/~rin/diary/?date=20090508#p06


class CaffeineBeverage:
  def prepareRecipe(self):
    self.boilWater()
    self.brew()
    self.pourInCup()
    self.addCondiments()

  def brew(self): pass

  def addCondiments(self): pass

  def boilWater(self):
    print "お湯を沸かします"

  def pourInCup(self):
    print "カップに注ぎます"

class Tea(CaffeineBeverage):
  def brew(self):
    print "紅茶を浸します"

  def addCondiments(self):
    print "レモンを追加します"

class Coffee(CaffeineBeverage):
  def brew(self):
    print "フィルタでコーヒーをドリップします"

  def addCondiments(self):
    print "砂糖とミルクを追加します"


def main():
  tea = Tea()
  coffee = Coffee()

  print "\n紅茶を作っています..."
  tea.prepareRecipe()

  print "\nコーヒーを作っています..."
  coffee.prepareRecipe()

main()
% python templatemethod.py

紅茶を作っています...
お湯を沸かします
紅茶を浸します
カップに注ぎます
レモンを追加します

コーヒーを作っています...
お湯を沸かします
フィルタでコーヒーをドリップします
カップに注ぎます
砂糖とミルクを追加します

2010-08-04 :-)

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

デモ準備

_ ,

@mizchi が居た聖剣伝説 LoM

_

いまなんじ?

_ [Python][デザインパターン][Iterator]Python でデザインパターン - Iterator

書き換え [ 20090512#p07 ]

Python で Iterator を実装するにはイテレータを使う方法とジェネレータを使う方法があるようだ。ジェネレータならば yield するだけなのでこれは Ruby に近い書き方になるのか。

イテレータ版

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Head First デザインパターンを写経する - 9章 Iterator パターン - ヨタの日々(2009-05-12)
# http://www.area51.gr.jp/~rin/diary/?date=20090512#p07

# イテレータ版

class Menu:
  def __init__(self, item):
    self.item = item
    self.count = len(item)

  def __iter__(self):
    return self

  def next(self):
    if self.count == 0:
      raise StopIteration
    i = len(self.item) - self.count
    self.count -= 1
    return self.item[i]


def main():
  menuItems = [ "K&Bのパンケーキ朝食", "通常のパンケーキ朝食", "ワッフル"]
  menu = Menu(menuItems)
  for n in menu:
    print n

main()

ジェネレータ版

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Head First デザインパターンを写経する - 9章 Iterator パターン - ヨタの日々(2009-05-12)
# http://www.area51.gr.jp/~rin/diary/?date=20090512#p07

# ジェネレータ版

def menu(item):
  for index in range(len(item)):
    yield item[index]


def main():
  menuItems = [ "K&Bのパンケーキ朝食", "通常のパンケーキ朝食", "ワッフル"]
  for n in menu(menuItems):
    print n

main()

実行結果は両方ともこう

K&Bのパンケーキ朝食
通常のパンケーキ朝食
ワッフル

ref.


2010-08-05 :-)

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

デモ

_ レキジョ

轢女

_ ,

dankogai dankogai という認識になっているのでもはや小飼弾と言われてもピンとこない。

_ ,

「髪切ったんだね」

「曜日ごとに髪型が違うんだね」

「整形したんだね 両親さえ分からないほど」

_ ,

s/バッファロー/バッキャロー/g

_ C言語のポインタ

ポインタで挫折すると言っても a->b くらいなら普通に使うよね挫折するとかワケワカンナイヨと思ってた時期がありました。

ときどきの雑記帖 めぐりあい電脳空間編 2010年月(旬)

463 デフォルトの名無しさん [sage] 2010/08/02(月) 23:02:44 ID: Be:
   (void)foo->super(foo)->hoge(foo->super(foo));
   (void)(*(*(*foo).super)(foo)).hoge)((*(*foo).super)(foo));
   一時変数使えよって感じだな

(´Д`;)

_ ,

お。soda さんだ

_ [NetBSD][翻訳]NetBSD Blog - Interview with S.P. Zeidler

S.P. Zeidler へのインタビュー

August 06, 2009 posted by Emile Heitor

Here's the third edition of the "discussions with a NetBSD developer" series. This time, we had the chance to talk to S.P. Zeidler, admin and member of pkgsrc-releng.

第3回「NetBSD 開発者に聞く」。今回は NetBSD admin と pkgsrc-releng のメンバーである S.P. Zeidler に話を聞くことができた。

NetBSDfr: For the readers who don't know you, can you shortly introduce yourself ?

spz: Hi, I'm S.P.Zeidler, call name Petra, also answers to spz or stargazer or Ophiuchi. I'm a member of the NetBSD admins team and of pkgsrc-releng. My archs are amiga, sparc64, amd64 and i386. In other news, I'm Bavarian, mid-fortyish, female, married, 2 cats, no kids.

NetBSDfr: あなたのことを知らない読者のために自己紹介をお願いします。

spz: S.P.Zeidler と言います。Petra と呼んでください。spz か stargazer か Ophiuchi でもいいよ。NetBSD admin チームと pkgsrc-releng チームのメンバーです( 訳: ???? )。持ってるアーキテクチャは amiga, sparc64, amd64 それと i386 です。あと私はバイエルン人で、中年( 訳: ???? )の女性、既婚で 2 匹の猫がいます。子供はいません。

NetBSDfr: Why did you choose to run NetBSD ? How long have you been using it ?

spz: It was the first free Unixoid system that ran on my Amiga, serpens, which has been running NetBSD since February 1995, i.e. since NetBSD 1.0.

NetBSDfr: どうして NetBSD を選んだのですか? NetBSD を使い始めてどれくらいですか?

spz: NetBSD は、手元の Amiga でいい感じに( 訳: serpens ???? )動いた最初の Unix 系 OS なんです。1995 年の NetBSD 1.0 のころから使ってます。

NetBSDfr: How did you become a NetBSD developer ?

spz: When the admins team was looking for more help, I got asked and didn't run away fast enough :-P

NetBSDfr: どうやって NetBSD 開発者になったのですか?

spz: admin チームがもっと人手を求めていたとき捕まり、逃げ出さなかったためです :-P ( 訳: わからん ???? )

NetBSDfr: Do you have an idea of the time you spend working on the NetBSD project daily, weekly, monthly ?

spz: Half an hour daily at least, but depending on things to do; running up 20 hours over the course of a weekend happens quite easily. Both admins and pkgsrc-releng are demand driven, you get requests and you handle them, security updates to servers need to be done as vulnerabilities become known, etc etc. I don't do much programming, if I commit something that's usually a bug fix where I sufficiently hated the bug to unpack the zapper myself instead of just whining about it.

NetBSDfr: NetBSD プロジェクトに携わる時間について何か決めていますか? 毎日? 毎週? 毎月?

spz: いろいろな制約があるけど毎日少なくとも 30 分くらい作業します。週末なら 20 時間以上作業することも楽勝です。admins と pkgsrc-releng チームは両方とも要求が来たときに作業します。vulnerabilities のようにサーバーに必要なセキュリティアップデートなどの作業が要求されたら作業します。プログラミングはあまりできないので、激しく嫌悪するようなバグを解決してフィックスしたらいつも the zapper myself instead of just whining about it してやります。( 訳: ?????? )

NetBSDfr: What is the job of a NetBSD admin ? How many admins are there ? How do you work alltogether ? How do you share the tasks you have to do ?

spz: In the abstract, keeping the servers of The NetBSD Foundation secure, up, and doing useful work. At a closer view, it's plain oldsystem administration with administration of services like eg mail thrown in.

There are currently 5 admins on admins rotation, which means doing a week of looking after user requests in turn, plus 6 more who do specialized tasks like site visits or do emergency repairs if a server or service acts up (like eg putting a stop to a mail loop). We have a ticketing system (RT) that user requests go into; whoever takes a ticket is responsible for resolving it.

For non-user requests, eg mail setup and mail-filtering is done by soda@, and tls@ is looking after hardware; I handle OS and package installation and upgrades.

NetBSDfr: NetBSD admin での作業はどういうことをやっていますか? admins には何人いますか? みんな一緒に作業するのですか? どうやってタスクを分担して作業してるのですか?

spz: おおざっぱにいうと、The NetBSD Foundation のサーバー群をセキュアにし、ちゃんと動作するように保ちます。実際のところはメールなどの古き良き管理サービスを管理しているだけです。現在は、ユーザーからのリクエストについては 5 人で回して作業してます。6 人目は、サーバー自身やサービスの調子が悪いときに復旧させるなど特殊なことをやってます( メールのループを停止したりすることです )。チケット管理システム( RT )を使っていて、ユーザーからの要求については誰でもチケットに着手し問題を解決するようにしています。

メールのセットアップやメールのフィルターなどユーザーからのリクエストではないものについては soda@ がおこなってくれましたし、ハードウェアは tls@ が面倒を見てくれてます。私は OS をいじったりパッケージをインストールしたりアップグレードなどしています。

NetBSDfr: What is the hardware infrastructure of the NetBSD project, in terms of hardware and software ? Where are they located ?

spz: We currently have two main sites, at ISC in Redwood City where the public servers are, and at Columbia University in New York where the TNF owned build cluster is. There is one lonely box in Sweden, hosted by the Lule Academic Computer Society, which provides data backup services.

The servers are a comparably boring bunch of rackmount servers (no fun retro archs at all, unless you count i386 ;), the newer ones amd64 arch and the older ones i386, and they run NetBSD-4 or NetBSD-5 at present, seeing that I am currently installing new servers instead of upgrading the remaining NetBSD-4 machines.

blog.NetBSD.org is a TNF system as of earlier today, and there will be a new ftp and due to reshuffling, new www and mail servers eventually too.

Thanks to everybody who donated funds and made the new machines possible, and of course also thanks to the organisations that host them.

NetBSDfr: NetBSD プロジェクトのインフラにはどのようなハードウェアやソフトウェアを使ってるのですか? それらはどこに設置されてますか?

spz: 現在はおもに 2 箇所のサイトがあります。公開用サーバーは Redwood の ISC にあり、New York の Columbia 大学には TNF 自身のビルドクラスターがあります。バックアップ用サービスが 1 つだけ Sweden の the Lule Academic Computer Society にホスティングされてます。

これらのサーバーはラックマウントのように詰まらないものです( i386 をカウントしないならば全部枯れたアーキテクチャです )( 訳: 古くてまったく面白みが無いアーキテクチャということ ????????? )、新しいものは amd64 から、古いものは i386 があるんですが、それらは NetBSD 4 または NetBSD 5 で動作してます。いま NetBSD 4 のマシンをアップグレードしてる最中です。

blog.NetBSD.org は TNF システムでは割りと新しいものです。いずれ ftp を刷新し、www と mail もそのうち新しくします。

寄付してくれたみなさんには感謝しています。おかげで新しいマシンを構築できました。もちろんホストさせてもらっている団体にも感謝します。

NetBSDfr: As part of the pkgsrc-releng team, can you tell us more about the way pkgsrc releases are organised ? How is a release tested / validated ?

spz: Unlike releng for the OS, the pkgsrc-releng team does not actually create the releases, it just maintains them. Pkgsrc releases are done roughly quarterly, give and take a week, and get 'cut' after one to two weeks of freeze period during which build and security issues of packages get fixed while the pkgsrc infrastructure itself is static. Build issues get found by the bulk builders, packages not working right get found by community input (if not by their maintainers, who usually use their packages themselves).

The main advantage of a maintained stable branch is that security issues get point fixes, ie you get to replace just the affected package and the rest stays at same version, which makes eg configuration incompatibilities a lot less likely. For production servers, using the stable branch of pkgsrc is definitely a good idea.

NetBSDfr: pkgsrc-releng チームについて聞きたいのですが、よろしければもう少し pkgsrc のリリース行程について聞かせてもらえませんか? テスト済みのものや認証済みのものはどうやってリリースするのですか?

spz: OS のリリースとは異なり、pkgsrc-releng チームは release を作成しません。ただメンテナンスするだけです。pkgsrc リリースはだいたい四半期ごとに 1 週間かけて作られ、その後 pkgsrc の更新を止め、2 週間かけてビルドしたり( 訳: ???? )パッケージのセキュリティホールを埋めたりし、凍結させ、cut します。( 訳: 「CVS のブランチを作る」などという意味? )。ビルドの問題については bulk builders が見つけてくれますし、パッケージが正常に動作するかどうかはコミュニティの知らせを見れば分かります( パッケージメンテナーによるものではない場合は彼ら自身がパッケージを使います )。( 訳: ?????????????? )

NetBSDfr: You told us there were no fun retro arch in the machines administered by the project. I'm wondering then how are pkgsrc releases built (if they are) for those retro archs ? Are the pkgsrc releases cross-compiled ? Provided by third-parties ? Not built ? Does it work the same way for NetBSD releases by themselves ? Are all the "fun retro" archs versions cross-compiled ?

spz: NetBSD proper can be cross compiled, the framework exists, and it's being used to provide binaries for all archs (see ftp.netbsd.orgs /pub/NetBSD-daily, we don't just build formal releases :).

pkgsrc has a few packages that have a cross compilation framework, but most don't, and there are several packages with a lot of dependants for which creating such a framework would mean ripping out the entire build system the package brings itself and redoing it, and redoing it for every new version that comes out after it, unless one gets buy-in by the people who create and maintain the software being packaged itself.

One of the headache packages in that space is perl, and it's interesting to see that there is now interest in a fully cross-compilable perl in the perl community itself.

So how do binary packages materialize? Developers who have the hardware bulk-build packages and upload them. You can read about the build reports on the mailing list pkgsrc-bulk.

NetBSDfr: あなたさは先ほど NetBSD プロジェクトには枯れたアーキテクチャのマシンが転がっていると言いました。不思議に思うんですが、どうやって pkgsrc のリリースをそれらのアーキテクチャ向けに( またはそれらのアーキテクチャ上で )ビルドしてるんですか? pkgsrc のリリースはクロスコンパイルしてるんですか? それともサードパーティから提供されるんですか? ほんとはビルドしてないとか? NetBSD のリリースでも同じことをやってるんでしょうか? 素敵なアーキテクチャもすべてクロスコンパイルしてるんでしょうか?

spz: NetBSD はすでにフレームワークが整っているのでクロスコンパイルは妥当ですし、全アーキテクチャのバイナリを提供するときにも使っています。( ftp.netbsd.orgs /pub/NetBSD-daily を見てください。リリースに限らずビルドされたものが置いてありますから :)

pkgsrc のいくつかのパッケージにはクロスコンパイルのフレームワークがありますが、ほとんどのパッケージにはありませんし、大量のパッケージに依存しているいくつかのパッケージについてフレームワークを使うように作成すると、ビルドシステム全体をビルドしなおすようなことになりますし、その後 新しいバージョンが登場するたびに同じ作業をおこなう羽目になり、one gets buy-in するひとたちが居ないならば、ソフトウェア自身によってパッケージされるように作成、保守されるようにすればいい。( 訳: ??????????? )

この辺りの話題については Perl が頭痛の種の 1 つで、面白いことに Perl コミュニティ自身の手によって完全なクロスコンパイル環境が構築されています。( 訳: おかしい。前半と後半の意味がつながらない )

で、どうやってバイナリパッケージを準備するか、でしたっけ? 開発者自身がパッケージの bulk-build するためのハードウェアを持っていて、それらをアップロードしています。pkgsrc-bulk のメーリングリストでビルド報告を見ることができます。

NetBSDfr : In your professional environment, do you work with NetBSD ? How do you think we should promote NetBSD for wider use within companies ?

spz: At my present job I don't work with NetBSB (yet); I'm currently not responsible for internal IT and the customers have existing servers to take care of, where a ninja change of OS is not entirely practical, if occasionally very much desired. :-7 There is lately some pkgsrc, at least.

In my experience, NetBSD gets used in general IT in companies where the sysadmins knew NetBSD previously and appreciated it as a "install - configure - runs" system of minimum ick factor. The more people know and appreciate NetBSD, and the more practical its use on production servers, the more use of that kind it will see. Of course, many companies use NetBSD and have no idea that they do so, since it's part of some "solution device" they use; these tend to be boring from my point of view though, since they tend to be rather black-box like. The makers of these devices will likely differ.

NetBSDfr: あなたは仕事では NetBSD を使って仕事してるんでしょうか? もっとたくさんの企業に NetBSD を促進するためにはどうしたらよいでしょうか?

spz: 仕事では NetBSD は使っていません( いまはまだね )。社内システム部門( 訳: internal IT )の担当ではないし、顧客が持ってる既存のサーバーの面倒を見るだけだし、a ninja change of OS is not entirely practical ですよ。ときどきものすごくそういう衝動に駆られますけどね :-7 まあ最近はいくつかの pkgsrc を使ってます。

私の経験では、一般的に、NetBSD を知ってるシステム管理者は仕事場でも NetBSD を使ってますし、あまりウンザリしなくて済む「インストールして、設定すれば走る」というのは評判が良いです。ほとんどのひとたちは NetBSD が良いものだということを知ってますし、サーバーとして実用できますし、ほかのことにもほどよく使えるでしょう。もちろん多くの企業が NetBSD を使っていますし、どう使うかという案は持ってないようです、彼らの問題を解決するための装置の一部という扱いだし、これらについては私が見てる限りではウンザリすることになるし、むしろブラックボックスとして扱われるようになります。装置メーカーはこの限りではないようですが。

NetBSDfr: As a conclusion, can you tell us how you forecast NetBSD future ?

spz: That's a hard one, especially as it depends a lot on 'chaotic' nature events of, eg, one developer pulling something out of their hat that proves to be a must have feature for an entire new class of device, or others banding together to make a form of use that is now possible but tedious to set up a snap drop-in; and in the long run, the question where computing is going is also unclear.

I can tell you what I am hoping for, and that is for a NetBSD that is small enough to allow the insertion of daring new ideas in -current, and large enough to mature -current into a rock solid release track system periodically; a project that generates ideas that may spread into the common pool and isn't just a me-too with slightly different wallpaper. That is why I'm spending my time on doing infrastructure, at least.

Oh, and I want cool ARM based netbooks with ridiculously long battery lifetime running NetBSD available soonish. The guilty parties will hopefully get a move on :-P

NetBSDfr: 最後に NetBSD が今後どのようになっていくかあなたの考えを聞かせてください。

spz: 難しいね。何が起きるか分らないし。たとえば、ある開発者は新しいデバイスクラス全体を機能させるためにいざこざを起こすかもしれないし、ほかの誰かは snap drop-in をセットアップするのに飽きて make a form を一緒くたにしてしまうかもしれないし、結局コンピューティングの将来が不明なのと同じだよね。

希望を言えば、NetBSD は -current に奇抜な試み導入できるくらいはじゅうぶん小さくなってほしいし、成熟した -current がリリースごとに定期的にシステムを追えるほど堅固になるくらいじゅうぶん大きくなってほしいし、NetBSD プロジェクトが common pool の範囲内でアイデアを作ってほしいし、私だけに限らないけど少しずつ違った壁紙がほしい。少なくとも、それが、なぜ私がインフラに時間をかけてるかの答えです。

ああ、あと、NetBSD を乗せて長時間バッテリー駆動する ARM のネットブックが欲しいです。これは急務です :-P

Many thanks to Guillaume Lasmayous from NetBSDfr for his hard work in preparing, conducting and translating this interview.

Guillaume Lasmayous は前準備や運営やインタビュー記事を送ってくれて感謝する。

_ [Python][デザインパターン][Adapter]Python でデザインパターン - Adapter

書き換え[ 20090508#p04 ]

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Head First デザインパターンを写経する - 7章 Adapter パターン - ヨタの日々(2009-05-08)
# http://www.area51.gr.jp/~rin/diary/?date=20090508#p04


class Duck:
  def quack(self): pass

  def fly(self): pass

class MallardDuck(Duck):

  def quack(self):
    print "ガーガー"

  def fly(self):
    print "飛んでいます"

class Turkey:
  def gobble(self): pass

  def fly(self): pass

class WildTurkey(Turkey):

  def gobble(self):
    print "ゴロゴロ"

  def fly(self):
    print "短い距離を飛んでいます"

class TurkeyAdapter(Duck):

  def __init__(self, turkey):
    self.turkey = turkey

  def quack(self):
    self.turkey.gobble()

  def fly(self):
    for i in range(5):
      self.turkey.fly()

def main():
  duck = MallardDuck()
  turkey = WildTurkey()
  turkeyAdapter = TurkeyAdapter(turkey)

  print "Turky の出力..."
  turkey.gobble()
  turkey.fly()

  print "\nDuck の出力..."
  testDuck(duck)

  print "\nTurkeyAdapter の出力..."
  testDuck(turkeyAdapter)

def testDuck(duck):
  duck.quack()
  duck.fly()

main()

出力

% python adapter.py
Turky の出力...
ゴロゴロ
短い距離を飛んでいます

Duck の出力...
ガーガー
飛んでいます

TurkeyAdapter の出力...
ゴロゴロ
短い距離を飛んでいます
短い距離を飛んでいます
短い距離を飛んでいます
短い距離を飛んでいます
短い距離を飛んでいます

2010-08-06 :-(

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

_ CR2 と JPEG ファイルを異なるディレクトリに配置することにした

( ※ CR2: Canon EOS 系 RAW ファイル )

いままで CR2 と JPEG を同じディレクトリに置いてた。

そうすると PS3 Media Server で画像を見るとき CR2 と JPEG の両方とも区別なく表示してくれちゃうのでいろいろ不都合が無くは無いのだけど面倒くさいのでそのうちやろうと思っててずーっと放置してたんだが、いつの間にか iTunes が iPod touch へ CR2 も転送するようになったので( これまでは CR2 は除外されてた ) 結局 CR2 と JPEG ファイルを別のディレクトリに配置するようにした。16GB iPod touch に CR2 を転送されたらタマッタモノジャナイ。

ということで Python の練習。日付ごとにディレクトリを作ってそこにファイルをコピーしてく。というか EOS Utility などでカメラから計算機へ画像を転送したときのようなディレクトリ構成にしたいだけ。移動じゃなくてコピーなのはまあ削除したければ find などすればいい。

#!/usr/bin/python
# -*- coding:utf8 -*-

# CR2 をコピーする

import sys
import os
import time
import shutil
from stat import *

prog = sys.argv[0]
if len(sys.argv) < 2:
  print "%s SRCDIR DSTDIR" %(prog)
  sys.exit()

srcrootdir = sys.argv[1]
dstrootdir = sys.argv[2]

if os.path.exists(srcrootdir) == False:
  print "%s not found" % (srcrootdir)
  sys.exit()

for root, dirs, files in os.walk(srcrootdir):
    for file in files:
        filename = os.path.join(root, file)
        if filename.lower().find(".cr2") == -1:
            continue
#        print filename
        stat = os.stat(filename)
        timestamp = time.strftime("%Y/%m/%d", time.localtime(stat[ST_MTIME]))
#        print timestamp

        dstdir = os.path.join(dstrootdir, timestamp)
#        print dstdir
        if os.path.isdir(dstdir) == False:
            os.makedirs(dstdir)

        print "copy %s to %s" % (file, dstdir)
        shutil.copy2(filename, dstdir)

_ サマーウォーズ実況タイムライン

お前ら楽しそうだな (※ 一部卑猥な post が混ざってます )


2010-08-07 :-)

_ 朝っ

0900 起床

_ [Python][デザインパターン][Decorator]Python でデザインパターン - Decorator

書き換え[ 20090505#p06 ]

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Head First デザインパターンを写経する - 3章 Decorator パターン - ヨタの日々(2009-05-05)
# http://www.area51.gr.jp/~rin/diary/?date=20090505#p06


class Beverage:

  def __init__(self):
    self.description = "不明な飲み物"

  def getDescription(self):
    return self.description;

  def cost(self): pass

class CondimentDecorator(Beverage):
  def getDescription(self): pass

class Espresso(Beverage):
  def __init__(self):
    self.description = "エスプレッソ"

  def cost(self):
    return 1.99


class HouseBlend(Beverage):
  def __init__(self):
    self.description = "ハウスブレンド"

  def cost(self):
    return 0.89

class DarkRoast(Beverage):
  def __init__(self):
    self.description = "ダークロースト"

  def cost(self):
    return 0.99

class Decaf(Beverage):
  def __init__(self):
    self.description = "カフェイン抜き"

  def cost(self):
    return 1.05

class Mocha(CondimentDecorator):

  def __init__(self, b):
    self.beverage = b

  def getDescription(self):
    return self.beverage.getDescription() + "、モカ"

  def cost(self):
    return 0.20 + self.beverage.cost()

class Whip(CondimentDecorator):

  def __init__(self, b):
    self.beverage = b

  def getDescription(self):
    return self.beverage.getDescription() + "、ホイップ"

  def cost(self):
    return 0.10 + self.beverage.cost()

class Soy(CondimentDecorator):

  def __init__(self, b):
    self.beverage = b

  def getDescription(self):
    return self.beverage.getDescription() + "、豆乳"

  def cost(self):
    return 0.15 + self.beverage.cost()

def main():
  beverage = Espresso()
  print "%s %s" % (beverage.getDescription(), beverage.cost())

  beverage2 = DarkRoast()
  beverage2 = Mocha( beverage2 )
  beverage2 = Mocha( beverage2 )
  beverage2 = Whip( beverage2 )
  print "%s %s" % (beverage2.getDescription(), beverage2.cost())

  beverage3 = HouseBlend()
  beverage3 = Soy( beverage3 )
  beverage3 = Mocha( beverage3 )
  beverage3 = Whip( beverage3 )
  print "%s %s" % (beverage3.getDescription(), beverage3.cost())

main()
% python decorator.py
エスプレッソ 1.99
ダークロースト、モカ、モカ、ホイップ 1.49
ハウスブレンド、豆乳、モカ、ホイップ 1.34

_ [ドラゴンクエストの世界]第24回ファミリークラシックコンサート ~ドラゴンクエストの世界~ 交響組曲「ドラゴンクエスト IX」 星空の守り人

@東京芸術劇場・大ホール

第一部

  1. 序曲IX
  2. 天の祈り
  3. 宿命~悲壮なるプロローグ
  4. 王宮のオーボエ
  5. 来たれわが街へ~夢みるわが街~酒場のポルカ~来たれわが街へ
  6. 野を越え山を越え~仲間とともに~箱舟に乗って~野を越え山を越え
  7. 陽だまりの村~村の夕べ
  8. 負けるものか~渦巻く欲望

第二部

  1. 暗闇の魔窟~洞窟のワルツ~そびえ立つ死の気配
  2. 集え、者たち~祈りの詩~せつなき思い
  3. サンディのテーマ~サンディの泪~サンディのテーマ
  4. 運命に導かれ~主なき神殿
  5. 決戦の時
  6. 星空へ~星空の守り人

アンコール

  1. 時の子守唄( DQ6 )
  2. 序曲IX

すぎやまこういちさんのお話

「ドラゴンクエストシリーズの王宮の曲は何か 1 つ楽器をもとにした曲があります。王宮のトランペット(5) 王宮のホルン(6) など。そのなかで『これだけはやりたくないなあ』という楽器は『王宮のブブゼラ』です :-) 」

「というわけで次の 2 曲。『王宮のオーボエ』から..... あ゛ 話す順番間違えた。『王宮のオーボエ』じゃなくて『天の祈り』です 」

とかいろいろ

_ [今日は一日ゲーム音楽三昧]NHK FM 今日は一日ゲーム音楽三昧

昼から録音しながら聞いていた。んだがツールの使い方がフガホゲであり途中 録音失敗している。

ドラクエコンサートのため外出したのだけど、その間にドラクエ、ときメモ、FFタイムがあったらしい。愛しの植松伸夫は私が帰宅する直前まで出演していたとか。くう

菊田裕樹さんが無かったり浜渦正志さんが無かったり崎元仁さんたちベイシスケイプの曲( オウガバトルとか! 蒼穹紅蓮隊リクエストしたのに )が無かったりと全体的に物足りないんだが、まあ仕方ない。ゲームは多すぎる。ジャンル別に分割などして今後も何度か放送してほしいなー。

最後の曲はこういうことらしい。

多分、ラジオで最後にギャラガが流れた理由がわからない人ってたくさんいると思う。実はね、さっきの曲は、世の中で一番最初に発売されたゲームミュージックのサントラの、一番最後の曲なんだよ。 #gamemusiczanmai (dfk_ohnuma)

あと大久保博さんのコメント

細野さんがVGM出してくれなかったらゲーム音楽の世界はこんなに盛り上がってなかったわけで。原点のレコードのラストトラックで締めるという狙いは、いい時代のNHKっぽくて好き。ボクも予約して買った思い出がよみがえった。(ookubon)

曲リスト→今日は一日 ○○三昧(ざんまい)


2010-08-08 :-)

_ 読書

2010年7月26日 - 2010年8月1日の読書メーター
読んだ本の数:0冊
読んだページ数:0ページ


読書メーター

_ 朝ッ

0900 起床

_ [Python][デザインパターン][Factory]Python でデザインパターン - Factory

書き換え[ 20090506#p04 ]

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Head First デザインパターンを写経する - 4章 Factory パターン - ヨタの日々(2009-05-06)
# http://www.area51.gr.jp/~rin/diary/?date=20090506#p04

class PizzaStore:
  def orderPizza(self, _type):
    self.pizza = self.createPizza(_type)
    self.pizza.prepare()
    self.pizza.bake()
    self.pizza.cut()
    self.pizza.box()
    return self.pizza

  def createPizza(self, _type): pass

class NYPizzaStore(PizzaStore):
  def createPizza(self, item):
    if item == "チーズ":
      return NYStyleCheesePizza()
##    elif item == "野菜":
##      return NYStyleVeggiePizza()
##    elif item == "クラム":
##      return NYStyleClamPizza()
##    elif item == "ペパロニ":
##      return NYStylePepperoniPizza()
    else:
      return None

class ChicagoPizzaStore(PizzaStore):
  def createPizza(self, item):
    if item == "チーズ":
      return ChicagoStyleCheesePizza()
##    elif item == "野菜":
##      return ChicagoStyleVeggiePizza()
##    elif item == "クラム":
##      return ChicagoStyleClamPizza()
##    elif item == "ペパロニ":
##      return ChicagoStylePepperoniPizza()
    else:
      return None

class CaliforniaPizzaStore(PizzaStore):
  def createPizza(self, item):
    if item == "チーズ":
      return CaliforniaStyleCheesePizza()
##    elif item == "野菜":
##      return CaliforniaStyleVeggiePizza()
##    elif item == "クラム":
##      return CaliforniaStyleClamPizza()
##    elif item == "ペパロニ":
##      return CaliforniaStylePepperoniPizza()
    else:
      return None


class Pizza:
  def __init__(self):
    self.name = None
    self.dough = None
    self.sauce = None
    self.toppings = None

  def prepare(self):
    print "%s を下処理" % (self.name)
    print "生地をこねる..."
    print "ソースを追加..."
    print "トッピングを追加:"
    for t in self.toppings:
      print " %s" % (t)

  def bake(self):
    print "350度で25分間焼く"

  def cut(self):
    print "ピザを扇形に切り分ける"

  def box(self):
    print "PizzaStore の正式な箱にピザを入れる"

  def getName(self):
    return self.name

class NYStyleCheesePizza(Pizza):
  def __init__(self):
    self.name = "ニューヨークスタイルのソース&チーズピザ"
    self.dough = "薄いクラスト生地"
    self.sauce = "マリナラソース"
    self.toppings = []
    self.toppings.append("粉レッジャーノチーズ")

class ChicagoStyleCheesePizza(Pizza):
  def __init__(self):
    self.name = "シカゴスタイルのディープディッシュチーズピザ"
    self.dough = "極厚クラスト生地"
    self.sauce = "プラムトマトソース"
    self.toppings = []
    self.toppings.append("刻んだモッツァレラチーズ")

  def cut(self):
    print "ピザを四角形に切り分ける"

def main():
  nyStore = NYPizzaStore()
  chicagoStore = ChicagoPizzaStore()
  pizza = nyStore.orderPizza("チーズ")
  print "イーサンの注文は %s" % (pizza.getName())
  pizza = chicagoStore.orderPizza("チーズ")
  print "ジョエルの注文は %s" % (pizza.getName())

main()
% python factory.py
ニューヨークスタイルのソース&チーズピザ を下処理
生地をこねる...
ソースを追加...
トッピングを追加:
 粉レッジャーノチーズ
350度で25分間焼く
ピザを扇形に切り分ける
PizzaStore の正式な箱にピザを入れる
イーサンの注文は ニューヨークスタイルのソース&チーズピザ
シカゴスタイルのディープディッシュチーズピザ を下処理
生地をこねる...
ソースを追加...
トッピングを追加:
 刻んだモッツァレラチーズ
350度で25分間焼く
ピザを四角形に切り分ける
PizzaStore の正式な箱にピザを入れる
ジョエルの注文は シカゴスタイルのディープディッシュチーズピザ

_ [Python][デザインパターン][State]Python でデザインパターン - State

書き換え[ 20090531#p06 ]

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Head First デザインパターンを写経する - 10章 State パターン - ヨタの日々(2009-05-31)
# http://www.area51.gr.jp/~rin/diary/?date=20090531#p06

class State:
  def insertQuarter(self): pass

  def ejectQuarter(self): pass

  def turnCrank(self): pass

  def dispense(self): pass


class HasQuarterState(State):

  def __init__(self, gumballMachine):
    self.gumballMachine = gumballMachine

  def insertQuarter(self):
    print "もう一度25セントを投入することはできません"

  def ejectQuarter(self):
    print "25セントを返却します"
    self.gumballMachine.setState(self.gumballMachine.getNoQuarterState())

  def turnCrank(self):
    print "クランクを回しました..."
    self.gumballMachine.setState(self.gumballMachine.getSoldState())

  def dispense(self):
    print "販売するガムボールはありません"

  def __str__(self):
    return "waiting for turn of crank"

class NoQuarterState(State):

  def __init__(self, gumballMachine):
    self.gumballMachine = gumballMachine


  def insertQuarter(self):
    print "25セントを投入しました"
    self.gumballMachine.setState( self.gumballMachine.getHasQuarterState())

  def ejectQuarter(self):
    print "25セントを投入していません"

  def turnCrank(self):
    print "クランクを回しましたが、25セントを投入していません"

  def dispense(self):
    print "まず支払いをする必要があります"

  def __str__(self):
    return "25セントが投入されるのを待っています"

class SoldOutState(State):

  def __init__(self, gumballMachine):
    self.gumballMachine = gumballMachine

  def insertQuarter(self):
    print "25セントを投入することはできません。このマシンは売り切れです"

  def ejectQuarter(self):
    print "返金できません。まだ25セントを投入していません"

  def turnCrank(self):
    print "クランクを回しましたが、ガムボールがありません"

  def dispense(self):
    print "販売するガムボールはありません"

  def __str__(self):
    return "売り切れです"

class SoldState(State):

  def __init__(self, gumballMachine):
    self.gumballMachine = gumballMachine

  def insertQuarter(self):
    print "お待ちください。すでにガムボールを出しています"

  def ejectQuarter(self):
    print "申し訳ありません。すでにクランクを回しています"

  def turnCrank(self):
    print "2回回してもガムボールをもう1つ入手することはできません!"

  def dispense(self):
    self.gumballMachine.releaseBall
    if self.gumballMachine.getCount() > 0:
      self.gumballMachine.setState(self.gumballMachine.getNoQuarterState())
    else:
      print "おっと、ガムボールがなくなりました!"
      self.gumballMachine.setState(self.gumballMachine.getSoldOutState())

  def __str__(self):
    "dispensing a gumball"

class GumballMachine:
  def __init__(self, numberGumballs):
    self.soldOutState = SoldOutState( self )
    self.noQuarterState = NoQuarterState( self )
    self.hasQuarterState = HasQuarterState( self )
    self.soldState = SoldState( self )
    self.state = self.soldOutState

    self.count = numberGumballs
    if  numberGumballs > 0:
      self.state = self.noQuarterState

  def insertQuarter(self):
    self.state.insertQuarter()

  def ejectQuarter(self):
    self.state.ejectQuarter()

  def turnCrank(self):
    self.state.turnCrank()
    self.state.dispense()

  def setState(self, state):
    self.state = state

  def releaseBall(self):
    print "ガムボールがスロットから転がり出てきます"
    if self.count != 0:
      self.count = self.count - 1

  def getCount(self):
    return self.count

  def refill(self, count):
    self.count = count
    self.state = self.noQuarterState

  def getState(self):
    return self.state

  def getSoldOutState(self):
    return self.soldOutState

  def getNoQuarterState(self):
    return self.noQuarterState

  def getHasQuarterState(self):
    return self.hasQuarterState

  def getSoldState(self):
    return self.soldState

  def __str__(self):
    result = ""
    result += "\nMighty Gumball, Inc."
    result += "\nJava対応据付型ガムボール モデル #2004"
    result += "\n在庫: #{self.count} 個のガムボール"
    result += "\nマシンは%s" % (self.state)
    return result


def main():

    gumballMachine = GumballMachine( 5 )
    print gumballMachine

    gumballMachine.insertQuarter()
    gumballMachine.turnCrank()
    print gumballMachine

    gumballMachine.insertQuarter()
    gumballMachine.turnCrank()
    gumballMachine.insertQuarter()
    gumballMachine.turnCrank()
    print gumballMachine

main()
% python state.py

Mighty Gumball, Inc.
Java対応据付型ガムボール モデル #2004
在庫: #{self.count} 個のガムボール
マシンは25セントが投入されるのを待っています
25セントを投入しました
クランクを回しました...

Mighty Gumball, Inc.
Java対応据付型ガムボール モデル #2004
在庫: #{self.count} 個のガムボール
マシンは25セントが投入されるのを待っています
25セントを投入しました
クランクを回しました...
25セントを投入しました
クランクを回しました...

Mighty Gumball, Inc.
Java対応据付型ガムボール モデル #2004
在庫: #{self.count} 個のガムボール
マシンは25セントが投入されるのを待っています

_ ウマシカ

  • オカルト学院
  • 屍鬼
  • サマーウォーズ

サマーウォーズ録画しといたので見始めたんだが 10 分で挫けた【お察しください】

_ 盛り上がるネタ

  • ベストなテキストエディタはなんですか?
  • おすすめのプログラミング言語はなんですか?
  • Linux って Windows よりショボイんでしょ?
  • ○○されるほうが悪い( ○○には犯罪の名前が入る )
  • 処女厨

_ ,

ベイシスケイプ分がまったく不足しているのでトレジャーハンターGを聞くなどしている。

_ sizeof

CentOS 64bit な環境でリベンジ [ 20100502#p02 ]

#include <stdio.h>

int main( int ac, char** av )
{
  printf( "%d\n", sizeof( int ) );
  printf( "%d\n", sizeof( long ) );
  printf( "%d\n", sizeof( void* ) );
  return 0;

}
$ gcc size.c && ./a.out
4
8
8

フォカヌポウ

_ LPIC って自慢になるの?

周囲には趣味で LPIC 出題範囲内くらいのことをおこなっているひとはゴロゴロいるし自分でもやってるので( 自宅にサーバー設置して Linux でも *BSD でもいいからテキトーな計算機にテキトーにオペレーティングシステムをインストールして DNS 設定して Postfix などを運用しメーリングリストなどを使えるようにしておけば LPIC レベル 2 まではイケル ) LPIC 取得した程度で自慢になるのかどうか分からん。

本日のツッコミ(全2件) [ツッコミを入れる]

_ うさだー [LPIC、自己満足のためだったら意味はないといっておこう。 業務を割り当てるときの能力を示す指標で使うものだから、 ..]

_ みわ [業務ではまったく使わないし、会社からおカネもらえるのでやってるだよ]


2010-08-09 :-)

_ にっちゅう!!

0900 起床

1000 掃除

1030 おひる

1200 だらだら

1400 散歩

1500 コーヒーる

猫撮れない

IMG_4925

_ きゅうけい!!

LPIC 202 模擬試験 56 点

フォカヌポウ


2010-08-10 :-)

_ ,

agumon さんがレースネタを構想している

_ [NetBSD][PDP-11][翻訳]hubertf's NetBSD blog - Of course it runs ... 2.11BSD (or: PDP-11 in a FPGA)

It's about time NetBSD gets the PDP11 port done: the PDP-11/70 CPU core is now available as implementation on a FPGA-board, and there's need for a newer operating system than 2.11BSD! Citing from the homepage:

NetBSD への PDP11 移植がようやく終わった。PDP-11/70 CPU core が FPGA ボードで実装されたのだ。2.11BSD より新しいオペレーティングシステムならば動くんだぜ!homepage より引用:

``The project contains a complete PDP-11 system: a 11/70 CPU with memory management unit, but without floating point unit, a basic set of UNIBUS peripherals (DL11, LP11, PC11, RK11/RK05), and last but not least a cache and memory controllers for SRAM and PSRAM. The design is FPGA proven, runs currently on Digilent S3BOARD and NEXYS2 boards and boots 5th Edition UNIX and 2.11BSD UNIX. ''

このプロジェクトの目的には PDP-11 を完全に実装することがある: 11/70 CPU でメモリマネージメントユニット( ただし浮動小数点演算ユニットは除く )、基本的な UNIBUS ペリフェラル(DL11, LP11, PC11, RK11/RK05) のセット、そして最後に、これが重要なのだが SRAM と PSRAM のキャッシュコントローラーとメモリーコントローラーだ。この設計で Digilent S3BOARD と NEXYS2 ボード FPGA で実装できたし、5th Edition UNIX と 2.11BSD UNIX で起動できた。

_ ,

うーさーのひとってたしか 10 年くらい前に獣姦ビデオ鑑賞オフなどというものをおこなってブルーになってたひとじゃなかったっけ

_ HTML の a href= で指定したファイル名を小文字に変えたいだけなんだよ

gsub イッパツというわけにはいかないのか。

#!/usr/pkg/bin/ruby

while gets
        if $_ =~ /(.*)(<a href=")(.*)(">)(.*)/
                puts "#{$1}#{$2}#{$3.downcase}#{$4}#{$5}"
  else
                puts $_
  end
end

_ ファイル名メンテナンス

メモ に置いてあるファイル自体の名前をすべて小文字にしてしまった割りに index.html に書いてあるファイル名はそのまま大文字小文字混在だったので書き直すなど。

_ 散歩

広角で遊ぶなど

IMG_4935

_ [リッジレーサー7]リッジレーサー7

オンラインバトルなど。B2ェ....

  • 走行距離 97318 km
  • RSGP 進行度 100.0 %
  • 名声 24885 FP
  • オンラインバトル勝利数 929/3387

_ [QuickML][コードリーディング][Ruby]QuickML を読む - 概要

QuickML とは、高林哲さんが書いたメーリングリストシステムである。うちでも使っている。ありがたいことである。

横着プログラミング 第5回: QuickML: 超お手軽なメーリングリスト

QuickMLは

  • メーリングリストを作るのが面倒
  • メーリングリストを管理するのが面倒
  • コマンドメールを覚えるのが面倒
  • Web上のフォームにあれこれ記入するのが面倒

といった面倒さを解決し、いつでも、どこでも、誰でもお手軽にメーリングリストを活用できるシステムである。

ソースコードはこちら→ quickmlサーバ: 超お手軽なメーリングリストシステム

なお手前味噌ながら作業ログはこちら 同一ホスト上で qmail と QuickML を動かす手順 同一ホスト上で Postfix と QuickML を動かす手順

_ [QuickML][コードリーディング][Ruby]QuickML を読む - quickml-ctl

QuickML の起動処理について読んでいく。

ソースコードをダウンロードし、展開すると configure や Makefile.in などがあることが分かる。QuickML のインストールは ./configure && make && make install すればよい。

起動させるときは quickml-ctl を実行する。quickml-ctl を読んでみる。

#! /bin/sh
start() {
        echo -n "Starting QuickML services: "
        /usr/local/sbin/quickml
        echo
}

stop() {
        echo -n "Stopping QuickML services: "
        kill `cat /var/run/quickml.pid`
        echo
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        sleep 1
        start
        ;;
  *)
        echo "Usage: quickml-ctl {start|stop|restart}"
        exit 1
esac

exit 0

起動だけでなく終了、最起動するときも quickml-ctl を使う。quickml-ctl start、quickml-ctl stop などして実行する。

quickml-ctl に渡された start, stop, restart に応じて各々処理する。

quickml-ctl start すると /usr/local/sbin/quickml を実行し、quickml を開始する。/usr/local/sbin/quickml の場所は configure したときに決まるのでこの PATH ではない場合もある。

_ [QuickML][コードリーディング][Ruby]QuickML を読む - quickml

/usr/local/sbin/quickml を読んでみる。

まずはスクリプト冒頭。

$KCODE = "e"
require 'quickml'

require 'quickml' で lib/quickml.rb を読み込んでいる。lib/quickml.rb はこうなっている。lib/quickml/* のファイルを読み込んでいる。

require 'quickml/utils'
require 'quickml/config'
require 'quickml/core'
require 'quickml/gettext'
require 'quickml/logger'
require 'quickml/mail'
require 'quickml/server'
require 'quickml/sweeper'
require 'quickml/version'

/usr/local/sbin/quickml に戻る。main() を読む。

def main (argv)
  config_file = if argv.length == 1 then
                  argv.first
                else
                  File.join("/usr/local/etc", "quickmlrc")
                end
  config = QuickML::Config::load(config_file)
  check_directory(config.data_dir)

argv には Ruby 定数 ARGV がそのまま入る。quickml-ctl を使った場合 ARGV は空である。よって config_file は /usr/local/etc/quickmlrc になる。/usr/local/sbin/quickml hogehoge.rc などとすれば別の設定ファイルを読み込ませることができる。

その /usr/local/etc/quickmlrc を QuickML::Config::load(config_file) により読み込み、config を作成している。config については後述する。

config.data_dir を check_directory() でチェックしている。check_directory() はこう。

def check_directory (dir)
  error("#{dir}: No such directory") unless File.directory?(dir)
  error("#{dir}: is not writable")   unless File.writable?(dir)
end

dir がディレクトリでないか、または書き込み可能でない場合は error() を呼んでいる。error() はこう。

def error (msg)
  STDERR.puts "#{$0}: #{msg}"
  exit(1)
end

標準エラー出力にプログラム名とメッセージを印字し、終了する。$0 は現在のプログラム名を表す Ruby 変数である。

check_directory() の次は be_daemon() と be_secure() を呼ぶ。

  be_daemon
  be_secure(config)

be_daemon() を見る。

def be_daemon
  exit!(0) if fork
  Process::setsid
  exit!(0) if fork
  Dir::chdir("/")
  File::umask(022)
  STDIN.reopen("/dev/null",  "r+")
  STDOUT.reopen("/dev/null", "r+")
  STDERR.reopen("/dev/null", "r+")
end

プログラム自身をデーモン化させる処理である。デーモン化させる手順は一般的にはこう。

デーモン ‐ 通信用語の基礎知識

1. fork()して、親プロセスを終了させる。こうすると、シェルに制御が戻る。
2. setsid()により、プロセスグループとセッショングループのリーダーになる。
3. 再びfork()し、親プロセス(セッショングループリーダー)を終了させる。
4. chdir("/")し、どのディレクトリも使用中でないことを明確にする。これを忘れると、ファイルシステムのアンマウントが出来なくなることがある。
5. umask(0)して、以降作成されるあらゆるファイルを支配下に置く。
6. ファイルディスクリプタの0、1、2をclose()する。親プロセスから引き継いだ、リダイレクト先不明の標準入出力は使用しない。
7. stdin、stdout、stderrは、自分で新しいディスクリプタとしてopen()する。

詳しいことは詳解 UNIX プログラミングを読むなどするとよい。

なお、Ruby 1.9 には Process.daemon が実装させているのでたんにこれを呼べばよい。

次に be_secure() を見てみる。

def be_secure (config)
  return unless Process.uid == 0
  uid = Etc::getpwnam(config.user).uid
  gid = Etc::getgrnam(config.group).gid
  touch(config.pid_file)
  touch(config.log_file)
  File.chown(uid, gid, config.data_dir)
  File.chown(uid, gid, config.pid_file)
  File.chown(uid, gid, config.log_file)
  Process.uid  = uid
  Process.gid  = gid
  Process.euid = uid
end

関連するファイルの UID と GID と 実効UID を config で設定した user と group に設定している。config については後述。

main() の最後。

  server  = QuickML::Server.new(config)
  sweeper = QuickML::Sweeper.new(config)

ここで server と sweeper を起動している。server は QuickML のメーリングリストとしての動作を請け負う。sweeper はメーリングリストの有無やユーザーの有無などを処理する。

  trap(:TERM) { server.shutdown; sweeper.shutdown }
  trap(:INT)  { server.shutdown; sweeper.shutdown }
  trap(:HUP)  { config.logger.reopen }

プログラムに TERM シグナルまたは INT シグナルが送られたときは server と sweeper を終了させ、HUP が送られたときは logger を reopen する。この辺りは後述。

  t = Thread.new { sweeper.start }
  t.abort_on_exception = true
  server.start

sweeper スレッドを生成し、server も開始させる。abort_on_exception は以下のように働く。

真の時は、いずれかのスレッドが例外によって終了した時に、インタプリタ全体を中断させます。デフォルトは偽、すなわち、通常あるスレッドで起こった例外は、Thread#join などで検出されない限りそのスレッドだけをなにも警告を出さずに終了させます。


2010-08-11 :-)

_ 朝ッ

1030 起床

_ [コードリーディング][Ruby][QuickML]QuickML を読む - config

QuickML の設定ファイルを管理するクラス。

/usr/local/sbin/quickml で QuickML::Config::load(config_file) としていたので、initialize() が最初に呼ばれるのではなく load が呼ばれる。

    def self.load (filename)
      self.new(eval(File.safe_open(filename).read))
    end

load() の中で new() している。どうして load() 経由で呼んでいるのかは分からない。誰か教えて。def self.ナントカ とするとクラスメソッドとして定義することになる。どうしてクラスメソッドにしておくのかというと、インスタンスを生成する手間を省きたいからじゃないでしょうか。たぶん

new() に渡している引数を見ていく。以下のような順番で処理される。

  1. File.safe_open(filename)
  2. それを read()
  3. それを eval()
  4. それを new() に渡す

File.safe_open() は lib/quickml/utils.rb の中で定義している。

class File
  def self.safe_open (filename, mode = "r")
    begin
      f = File.open(filename, mode)
      if block_given?
        yield(f)
        f.close
      else
        return f
      end
    rescue => e
      STDERR.printf "%s: %s\n", $0, e.message
      exit(1)
    end
  end
end

block_given? とはなんぞや

block_given?
メソッドにブロックが与えられている時には真、そうでない時に偽を返します。

つまり、以下のように呼ぶと block_given? は真

File.safe_open(hogehoge) {|f|
  何かの処理
}

以下のように呼ぶと block_given? は偽となる。

f = File.safe_open(hogehoge)

self.load では File.safe_open(filename) と、ブロックを渡していないので File.safe_open() では File オブジェクトが返る。

次に、その File オブジェクトの read() を呼ぶ。quickmlrc の全て読み込んでいる。

File.safe_open(filename).read

quickmlrc の内容はこう。Ruby のハッシュである。ここではまだハッシュオブジェクトではなく、たんなる文字列になっている。

# -*- mode: ruby -*-
Config = {
  :user => "quickml",
  :group => "quickml",
  :port => 10025,
  :bind_address => "0.0.0.0",

  :smtp_host => '127.0.0.1',
  :smtp_port => 25,
  :domain => 'qml.area51.gr.jp',
  :postmaster => "rin@maaya.jp",
  :info_url => "http://QuickML.com/",

  :data_dir => '/usr/local/var/quickml',
  :pid_file => '/var/run/quickml.pid',
  :log_file => '/var/log/quickml.log',

  :verbose_mode => true,
  :max_members => 100,
  :max_mail_length => 100 * 1024,
  :ml_life_time => 86400 * 31,
  :ml_alert_time => 86400 * 30,
  :auto_unsubscribe_count => 5,

  :sweep_interval => 3600,
  :max_threads => 10,
  :timeout => 120,
  :use_qmail_verp => false,

  :confirm_ml_creation => false, # for confirming ML creation. (experimental)

  # :message_catalog => nil  # for English messages
  :message_catalog => '/usr/local/share/messages.ja',
}

次に、ここで読み込んだ Config を eval() する。

eval(File.safe_open(filename).read))

eval() してようやく Config はハッシュオブジェクトとして生成されたことになる。

その Config を self.new() に渡す。

new() を呼ぶと initialize() が呼ばれるので initialize() を見てみる。長いので省略

    def initialize (config = {})
      @data_dir = config[:data_dir]
      @smtp_host = config[:smtp_host]
      @domain = config[:domain]

      raise ArgumentError if @data_dir.nil?
      raise ArgumentError if @smtp_host.nil?
      raise ArgumentError if @domain.nil?

      @pid_file = (config[:pid_file] or "/var/run/quickml.pid")
      @max_members = (config[:max_members] or 100)
      @max_mail_length = (config[:max_mail_length] or 100 * 1024) # 100KB
        :

見たとおりに config にあるキーから値を取得などしている。

(config[:pid_file] or "/var/run/quickml.pid") という処理は config[:pid_file] が nil ならば "/var/run/quickml.pid" を設定するということを意味している。つまり quickmlrc に pid_file が定義されていなければ "/var/run/quickml.pid" を使う。いわゆるデフォルト値になる。

initialize() の最後に注目。

      instance_variables.each {|name|
        self.class.class_eval { attr_reader name.delete('@') }
      }

instance_variables とはなんぞや

instance_variables
オブジェクトのインスタンス変数名を文字列の配列として返します。

obj = Object.new
obj.instance_eval { @foo, @bar = nil }
p obj.instance_variables

# => ["@foo", "@bar"]

これで

["@data_dir", "@smtp_host", "@domain" ...]

といった配列が返る。それを each する。

self.class.class_eval { attr_reader name.delete('@') } を 1 つずつ見ていく。

self.class はつまり自分自身のクラス。

class_eval とはなんぞや。これは結局 module_eval である。

module_eval とはなんぞや。

ブロックが与えられた場合にはそのブロックをモジュールのコンテキストで評価してその結果を返します。ブロックの引数 mod には self が渡されます。

モジュールのコンテキストで評価するとは、実行中そのモジュールが self になるということです。つまり、そのモジュールの定義文の中にあるかのように実行されます。

ええと、つまり @data_dir などに attr_reader 属性を付加していることになるらしい。へー

_ また処女か

「処女」かどうかと「乙女チック」「乙女心」「清純」などというものは別の問題なので、そこをゴチャゴチャすると話にならない。

前者はたんに肉体の問題であり、後者は精神、立ち居振る舞いの問題である。

処女厨が叩かれるのは「処女イコール清純」という前提になってるからであろうよ。

だと思うんだよね。

_ [QuickML][Ruby][コードリーディング]QuickML を読む - logger

ログを印字する処理。同期に対して注意している。

require 'quickml/utils'
require 'thread'

module QuickML
  class Logger
    def initialize (log_filename, verbose_mode = nil)
      @mutex = Mutex.new
      @log_file = File.safe_open(log_filename, "a")
      @log_file.sync = true
      @verbose_mode = verbose_mode
    end

log_file.sync は結局 IO の sync を設定している。

sync
現在の出力同期モードを真偽値で返します。同期モードが真の時は出力関数の呼出毎にバッファがフラッシュされます。

そのまま。

    private
    def puts_log (msg)
      @mutex.synchronize {
        time = Time.now.strftime("%Y-%m-%dT%H:%M:%S")
        @log_file.puts "#{time}: #{msg}"
      }
    end

    public
    def log (msg)
      puts_log(msg)
    end

    def vlog (msg)
      puts_log(msg) if @verbose_mode
    end

外部には log() と vlog() を公開しておき、結局各々 puts_log() を呼んでいる。puts_log() では RFC 3339 ぽい日付時間フォーマットに整形している(ref. RFC3339 インターネット上の日付と時間:タイムスタンプ )。( タイムオフセットが無いよね? )

    def reopen
      @mutex.synchronize {
        log_filename = @log_file.path
              @log_file.close
              @log_file = File.safe_open(log_filename, "a")
      }
    end

同期を気にしつつファイルを一度閉じて開いている。reopen() は HUP を貰ったときに実行される。

 trap(:HUP)  { config.logger.reopen }

_ ,

結局個体差なので「処女だから云々」というのはつまり主語が大きいんである。

_ 散歩

広角で遊ぶ

IMG_4971

_ 買い物

@紀伊国屋

ラノベ分が枯渇した

4044748187

4094511539

4086305577

4840131627

4840134049

4840124019

4840126003

4044740046

4044740054

4044740062

4044740070


2010-08-12 :-)

_ 朝ッ

0400 起床

_ ちゃりったー

朝日っておる

img_1252.jpg

img_1253.jpg

img_1254.jpg

img_1256.jpg

img_1257.jpg

img_1258.jpg

img_1261.jpg

img_1262.jpg

img_1264.jpg

img_1265.jpg

img_1267.jpg

_ [QuickML][コードリーディング][Ruby]QuickML を読む - server 起動

あとまわしにしていた server の処理を読む。起動のところだけ。

ファイルは lib/quickml/server.rb

Server クラスの処理。

   def initialize (config)
     @config = config
     @status = :stop
     @logger = @config.logger
     @server = TCPServer.new(@config.bind_address, @config.port)
   end

initialize() で内部の状態を設定などしている。server は Ruby の TCPServer をラップしている。

initialize() したら start() が呼ばれる。start() はこう。

   def start
     raise "server already started" if @status != :stop
     write_pid_file
     @logger.log sprintf("Server started at %s:%d [%d]",
                         "localhost", @config.port, Process.pid)
     accept
     @logger.log "Server exited [#{Process.pid}]"
     remove_pid_file
   end

状態をチェックし、起動済みならば例外を発生させる。

write_pid_file() では QuickML のプロセスID が書かれたファイルを作成している。Unix では伝統的な pid ファイルである。このファイルは quickml-ctl の stop() で以下のように使われる。

stop() {
        echo -n "Stopping QuickML services: "
        kill `cat /var/run/quickml.pid`
        echo
}

次に accept() する。名前の通り接続待ちになる。accept() はこう。

   def accept
     running_sessions = []
     @status = :running
     while @status == :running
       begin
         t = Thread.new(@server.accept) {|s|
           process_session(s)
         }
         t.abort_on_exception = true
         running_sessions.push(t)
       rescue Errno::ECONNABORTED # caused by @server.shutdown
       rescue Errno::EINVAL
       end
       running_sessions.delete_if {|t| t.status == false }
       if running_sessions.length >= @config.max_threads
         ThreadsWait.new(running_sessions).next_wait
       end
     end
     running_sessions.each {|t| t.join }
   end

実際の受け入れ処理は TCPServer の @server.accept がおこなっている。ブロックに渡される s は TCPSocket である。つまりソケット。

そして running_sessions には確立したセッションのスレッドが格納されていく。

セッションを処理している process_session() を見てみる。

   def process_session (socket)
     begin
       session = Session.new(@config, socket)
       session.start
     rescue Exception => e
       @logger.log "Unknown Session Error: #{e.class}: #{e.message}"
       @logger.log e.backtrace
     end
   end

Session を生成し、開始している。

Session はこう。

 class Session
   include GetText::GetText
   def initialize (config, socket)
     @socket = socket
     @config = config
     @command_table = [:helo, :ehlo, :noop, :quit, :rset, :rcpt, :mail, :data]
     @hello_host = "hello.host.invalid"
     @protocol = nil
     @peer_hostname = @socket.hostname
     @peer_address = @socket.address
     @remote_host = (@peer_hostname or @peer_address)
     @logger = @config.logger
     @catalog = @config.catalog
     @data_finished = false
     @my_hostname = if @config.port == 25 then
                      Socket.gethostname
                    else
                      "localhost"
                    end
     @message_charset = nil
   end

名前のとおり、接続ごとの処理を請け負う。

command_table に格納しているのは SMTP のコマンドである。

initialize() の次は start() である。

class Session
 :
    public
   def start
     start_time = Time.now
     _start
     elapsed = Time.now - start_time
     @logger.vlog "Session finished: #{elapsed} sec."
   end

_start() を見る。

class Session
 :
   def _start
     begin
       connect
       timeout(@config.timeout) {
         process
       }
     rescue TimeoutError
       @logger.vlog "Timeout: #{@remote_host}"
     ensure
       close
     end
   end

connect() して process() している。connect() を見る。

   def connect
     def @socket.puts(*objs)
       objs.each {|x|
         begin
           self.print x.xchomp, "\r\n"
         rescue Errno::EPIPE
         end
       }
     end
     @socket.puts "220 #{@my_hostname} ESMTP QuickML"
     @logger.vlog "Connect: #{@remote_host}"
   end

ここで、def @socket.puts(*objs) することによりこのスコープでのみ @socket の puts() をオーバーライドしている。*objs は渡された引数を表す。self.print で @socket.print を呼び出している。x には渡された引数、つまり文字列 String になる。xchomp() は lib/quickml/util.rb で定義している。

class String
 :
 def xchomp
    self.chomp("\n").chomp("\r")
  end
end

そしてさらに "\r\n" を追加している。つまり渡された文字列から \n \r を削除し、そのあとに \r\n を追加している。

のだと思う。

@socket がリモートから受け取った文字列に対して処理するならば分かるんだが、@socket.puts() はすぐ下の @socket.puts "220.... で使っているだけなのだろうけど、\r \n を削除するのはなぜなんだ。


2010-08-13 :-)

_ 朝ッ

0930 起床

だる

ねむ

_ [首都圏外郭放水路見学]首都圏外郭放水路見学

行ってきた。

オレが本当に欲しかったのは明るい広角レンズだということが分かった。

F4 では暗すぎたんだ...

IMG_5038

管理室というのはどこもそう変わらないんだなあとか

IMG_5012

「首都圏外郭放水路 超厚水路で 歌手、声優として活躍中の水樹奈々さんの "WILD EYES" MUSIC CLIP撮影が行われました」

IMG_5015

_ [QuickML][コードリーディング][Ruby]QuickML を読む - メーリングリストの作成と参加

メーリングリストの作成と参加の一連の処理を見てみる。

メーリングリストの作成方法はこう。

横着プログラミング 第5回: QuickML: 超お手軽なメーリングリスト

○○○@quickml.com のような任意のアドレスにいきなりメールを送るだけで、新しいメーリングリストを作成できる。たとえば宴会のメーリングリストを作るには enkai@quickml.com にメールを送ればいい。このとき、 From: と Cc: のアドレスがメーリングリストに登録される。

Subject: 宴会メーリングリスト
To: enkai@quickml.com                ← 作りたいMLのアドレス
From: satoru@namazu.org              ← 自分のアドレス
Cc: masui@pitecan.com                ← 参加者リスト

突然ですが、宴会好きのメーリング     ← 本文
リストを作ってみました。

では先ほどの続きで、 process() を見る。

class Session
 :
    def process
      until @socket.closed?
        begin
          mail = Mail.new
          receive_mail(mail)
          if mail.valid?
            processor = Processor.new(@config, mail)
            processor.process
          end
        rescue TooLargeMail
          cleanup_connection
          report_too_large_mail(mail) if mail.valid?
          @logger.log "Too Large Mail: #{mail.from}"
        rescue TooLongLine
          cleanup_connection
          @logger.log "Too Long Line: #{mail.from}"
        end
      end
    end

Mail を生成し、mail を受け取り、processor に渡している。

Mail を見る。

Mail クラスは lib/quickml/mail.rb に定義されている。

 class Mail
   def initialize
     @mail_from = nil
     @recipients = []
     @header = []
     @body = ""
     @charset = nil
     @content_type = nil
     @bare = nil
   end

メールそのものだ。

receive_mail() を見る。

lib/quickml/server.rb に戻る。

class Session
 :
    def receive_mail (mail)
      while line = @socket.safe_gets
        line.xchomp!
        command, arg = line.split(/\s+/, 2)
        command = command.downcase.intern  # "HELO" => :helo
        if @command_table.include?(command)
          @logger.vlog "Command: #{line}"
          send(command, mail, arg)
        else
          @logger.vlog "Unknown SMTP Command: #{command} #{arg}"
          @socket.puts "502 Error: command not implemented"
        end
        break if command == :quit or command == :data
      end
    end

ソケットから 1 行ずつ読み取り、メールを処理する。

ここの処理は SMTP のコマンドを想像すると分かりやすい。

send(command, mail, arg)

send() はこれ。

オブジェクトのメソッド name を、引数に args を渡して呼び出し、メソッドの実行結果を返します。

つまり rcpt, data などのコマンド名をそのままメソッド名として解釈させ、受け取った SMTP コマンドごとの該当するメソッドを呼んでいる。

ML に参加する手順では、from() で参加したいひとのメールアドレス、rcpt() でメーリングリストのアドレスを処理することになる。

from() を見てみる。

   def from
     address = if not self["From"].empty?
                 collect_address(self["From"]).first
               else
                 @mail_from
               end
     address = "unknown" if address.nil? or address.empty?
     normalize_address(address)
   end

collect_address() はこう。addresses にメールアドレスを追加していく。

   def collect_address (field)
     address_regex =
       /(("?)[-0-9a-zA-Z_.+?\/]+\2@[-0-9a-zA-Z]+\.[-0-9a-zA-Z.]+)/ #/
     addresses = []
     parts = remove_comment_in_field(field).split(',')
     parts.each {|part|
       if (/<(.*?)>/ =~ part) or (address_regex =~ part)
         addresses.push(normalize_address($1))
       end
     }
     addresses.uniq
   end

次に rcpt() を見てみる。

class Session
 :
    def rcpt (mail, arg)
      if mail.mail_from.nil?
        @socket.puts "503 Error: need MAIL command"
      elsif /^To:\s*<(.*)>/i =~ arg or /^To:\s*(.*)/i =~ arg
        address = $1
        if Mail.address_of_domain?(address, @config.domain)
          mail.add_recipient(address)
          @socket.puts "250 ok"
        else
          @socket.puts "554 <#{address}>: Recipient address rejected"
          @logger.vlog "Unacceptable RCPT TO:<#{address}>"
        end
      else
        @socket.puts "501 Syntax: RCPT TO: <address>"
      end
    end

ドメインの有無チェックなどがあるが、ようするに add_recipient() してメーリングリストのメールアドレスを追加していく。

 class Mail
  :
     def add_recipient (address)
       @recipients.push(normalize_address(address))
     end

recipients にひたすら追加している。

受け取ったメールアドレスを格納していったので、次にそれを処理するための Processor を見る。Processor.process() で処理している。

ファイルは lib/quickml/core.rb

 class Processor
 :
    public
   def process
     mail_log
     if @mail.looping?
       @logger.log "Looping Mail: from #{@mail.from}"
       return
     end
     @mail.recipients.each {|recipient|
       process_recipient(recipient)
     }
   end

溜め込んだメーリングリストのメールアドレス recipients を処理していく。

process_recipient() を見る。

 class Processor
 :
    def process_recipient (recipient)
     mladdress = recipient
     if to_return_address?(mladdress)
       handler = ErrorMailHandler.new(@config, @message_charset)
       handler.handle(@mail)
     elsif @config.confirm_ml_creation and
         to_confirmation_address?(mladdress)
       validate_confirmation(mladdress)
     else
       begin
         @config.ml_mutex(mladdress).synchronize {
           ml = QuickML.new(@config, mladdress, @mail.from, @message_charset)
           @message_charset = (@message_charset or ml.charset)
           (unsubscribe(ml); return) if unsubscribe_requested?
           submit(ml)
         }
       rescue InvalidMLName
         report_invalid_mladdress(mladdress)
       end
     end
   end

QuickML.new() からがその処理。QuickML クラスはメーリングリストを管理する。

submit() はこう。

 class Processor
 :
    def submit (ml)
     if ml.exclude?(@mail.from)
       @logger.log "Invalid From Address: #{@mail.from}"
     elsif ml.forward?
       @logger.log "Forward Address: #{ml.address}"
       ml.submit(@mail)
     elsif confirmation_required?(ml)
       ml.prepare_confirmation(@mail)
     elsif acceptable_submission?(ml)
       submit_article(ml)
     else
       report_rejection(ml)
     end
   end

quickmlrc で confirm_ml_creation を true にしていなければ( デフォルト False )、submit_article() が呼ばれる。

submit_article() を見てみる。

 class Processor
 :
    def submit_article (ml)
     @unadded_addresses = []
     if ml_address_in_to?(ml)
       add_member(ml, @mail.from)
       @mail.collect_cc.each {|address|
         add_member(ml, address)
       }
     end
     unless @unadded_addresses.empty?
       report_too_many_members(ml, @unadded_addresses)
     end
     ml.submit(@mail)
   end

ここで、指定したメーリングリストが新規作成される場合は ml.submit(@mail) のみが呼ばれる。メーリングリストがすでに存在しておりそのメーリングリストにメンバーを追加する場合は from で格納したメールアドレスを add_member() で登録する。

add_member() はこう。

 class Processor
 :
    def add_member (ml, address)
     begin
       ml.add_member(address)
     rescue TooManyMembers
       @unadded_addresses.push(address)
     end
   end

ml.add_member() はこう。

 class QuickML
 :
   def add_member (address)
     if exclude?(address)
       @logger.vlog "Excluded: #{address}"
       return
     end
     return if @active_members.include?(address)
     raise TooManyMembers if too_many_members?
     @former_members.delete(address)
     @active_members.push(address)
     save_member_file
     @logger.log "[#{@name}]: Add: #{address}"
     @added_members.push(address)
     @member_added_p = true
   end

メーリングリストにメールアドレスを追加などし、メーリングリストの管理用のファイルを書き込んでいる。

ml.submit() は結局これが呼ばれる。

 class QuickML
 :
    def _submit (mail)
     inc_count
     save_charset
     remove_alertedp_file

     subject = Mail.rewrite_subject(mail["Subject"], @short_name, @count)
     body = rewrite_body(mail)
     header = []
     mail.each_field {|key, value|
       k = key.downcase
       next if k == "subject" or k == "reply-to"
       header.push([key, value])
     }
     header.push(["Subject",        subject],
                 ["Reply-To",        @address],
                 ["X-Mail-Count",@count])
     header.concat(quickml_fields)
     Mail.send_mail(@config.smtp_host, @config.smtp_port, @logger,
                    :mail_from => @return_address,
                    :recipients => @active_members,
                    :header => header,
                    :body => body)
   end

メールを組み立て Mail.send_mail() を呼ぶ。

これ。特異クラスとなっている。

   class << self
     def send_mail (smtp_host, smtp_port, logger, optional = {})
       mail_from = optional[:mail_from]
       recipients = optional[:recipients]
       header = optional[:header]
       body = optional[:body]
       if optional[:recipient]
         raise unless optional[:recipient].kind_of?(String)
         recipients = [optional[:recipient]]
       end
       raise if mail_from.nil? or recipients.nil? or
         body.nil? or header.nil?

       contents = ""
       header.each {|field|
         key = field.first; value = field.last
         contents << "#{key}: #{value}\n" if key.kind_of?(String)
       }
       contents << "\n"
       contents << body
       begin
         sender = MailSender.new(smtp_host, smtp_port, true)
         sender.send(contents, mail_from, recipients)
       rescue => e
         logger.log "Error: Unable to send mail: #{e.class}: #{e.message}"
       end
     end

sender.send() でメール送信する。

これ。

 class MailSender
 :
   def send (message, mail_from, recipients)
     recipients = [recipients] if recipients.kind_of?(String)
     s = TCPSocket.open(@smtp_host, @smtp_port)
     send_command(s, nil, 220)
     send_command(s, "EHLO #{Socket.gethostname}", 250)
     if @use_xverp and @xverp_available and (not mail_from.empty?)
       send_command(s, "MAIL FROM: <#{mail_from}> XVERP===", 250)
     else
       send_command(s, "MAIL FROM: <#{mail_from}>", 250)
     end
     recipients.each {|recipient|
       send_command(s, "RCPT TO: <#{recipient}>", 250)
     }
     send_command(s, "DATA", 354)
     message.each_line {|line|
       line.sub!(/\r?\n/, '')
       line.sub!(/^\./, "..")
       line << "\r\n"
       s.print(line)
     }
     send_command(s, ".", 250)
     send_command(s, "QUIT", 221)
     s.close
   end

SMTP をしゃべっている。

どうして Net::SMTP などを使わずに自力でしゃべっているのか。

ChangeLog を見てみる。

2003-01-17  Satoru Takabayashi  <satoru@namazu.org>

	* lib/quickml/utils.rb (Net::NetPrivate::SMTPCommand): Removed.

	* lib/quickml/mail.rb (QuickML::Mail::send_mail): Use MailSender
	instead of Net::SMTP.

	* lib/quickml/server.rb (QuickML::Session::report_too_large_mail):
	Change the recipient address: @mail.envelope_from => @mail.from

	* lib/quickml/mail.rb (QuickML::MailSender): New class.

うーん

MailSender で use_xverp しているので....

module QuickML

 class MailSender
   def initialize (smtp_host, smtp_port, use_xverp = false)
     @smtp_port = smtp_port
     @smtp_host = smtp_host
     @use_xverp = use_xverp
     @xverp_available = false
   end

XVERP 関連の処理を描き直したかったのかしら。


2010-08-14

_ 朝ッ

0900 起床

_ [コミックマーケット][コミケ]コミックマーケット78 2日目

いつものところなど。菊田裕樹さんから「がんばってくださいw」などと逆に声をかけられたり、そして細江慎治さんはぐったりしていた。

Megalomachia のために東 4 5 6 に行ったんだが東方サークルをまったく警戒していなかった。東4 5 6 には近づくべきではなかったのだ....。

img_1269s.jpg


2010-08-15 :-)

_ 読書

2010年8月2日 - 2010年8月8日の読書メーター
読んだ本の数:0冊
読んだページ数:0ページ


読書メーター

_ 朝ッ

0500 起床

_ コミックマーケット78 3日目

Namiki サークルが人手不足ということでなんだかんだでサークルとして入場したのであった。せっかくだからオレは最後までつきあった。やはりコミケは楽しいのう。

img_1270.jpg


2010-08-16 :-(

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

_ ,

それが役立つというのであれば役立つのであろう。お前んなかではな。

_ RR7

TA で走ったあとに kn さんのリプレイ動画を見るとあまりにも華麗な走りに感動すら覚える。むしろ感動する。洞窟コース順走の直線の直前でトリプル溜まらない。


2010-08-17 :-(

_ ,

冷房を 30℃に設定して発動させながら寝てみた。

_ ,

家の中よりも外のほうが涼しい

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

_ ルーチンワーク

携帯百景 を眺めているひとには「三輪はいつも同じような飯を作っているではないか」と思うひとが居るかもしれない( いないだろうなあ )、それは正しくて、三輪は飯を作る作業をルーチンワークにしているのでいつも同じ飯を作るハメになっている。id:kennak のように豊富なレシピを持ち合わせていればいいんだが、まあ持ってなくてもクックパッドで検索すればザクザク表示されるんだけど、その手間もなんだか面倒くさくなってしまったので、とりあえず作り方を覚えてしまった飯を作るだけの簡単なお仕事と化することによりルーチンワークにしておいた。ルーチンワーク化させて残りの時間をどうしてるのかというとまあリッジレーサー7 やってるわけですが。

_ インターネットはエロのおかげで発展した

学生のころ インターネットヒストリー を読むなどし、インターネットは技術者にとって夢の場所なのだ、インターネットは性善説でできているなど純真なポリシーを患い、そのまま社会人になったものだから、当時先輩から「インターネットはエロのおかげで発展した」という言葉を聞いて「違う! インターネットはそんな俗なものではない! インターネットはもっと高貴なものなのである! 」と食ってかかったんだが、いま思うと「まあそうかもしれない」と思える。年とったなあ

_ [NetBSD][翻訳][コアチーム]hubertf's NetBSD blog - New NetBSD Core Team announced

新しいコアチームの案内

NetBSD's core team is responsible for technical steering of the project. In the past the group was five people, and it was increased to seven people now. Read more in Alistair Crooks' announcement:

NetBSD コアチームは NetBSD プロジェクトの技術面の管理を担当する。以前は 5 名だったが、現在は 7 名に増えている。詳細を Alistair Crooks' announcement より:

We take great pleasure in announcing that the NetBSD core team, responsible for technical management within the NetBSD project, has increased its numbers to seven. This is to help in the running of a project with an ever-growing source base and developer community, and mirrors a similar change made to the board of directors, which has worked extremely well.

NetBSD プロジェクトの技術管理を担当する NetBSD コアチームが 7 名に増えた。これを告知できることをうれしく思う。NetBSD コアチームは成長し続けるソースコードと開発者コミュニティを持続させることを手助けし、ボードメンバーのようにうまく機能する。

To help with the running of the project, we have asked Antti Kantee (pooka%NetBSD.org@localhost) and Chuck Silvers (chs%NetBSD.org@localhost), and they have very kindly agreed to join the core team. Antti is well known to many both inside and outside the project, and has contributed many new and exciting ideas, the most memorable and useful of these being the rump kernel architecture. Chuck is also well-known in NetBSD circles - his work on UBC, and his recent update of the Linux emulation code are just two examples of his contributions.

NetBSD プロジェクトの持続を助けるために、Antti Kantee (pooka%NetBSD.org@localhost) と Chuck Silvers (chs%NetBSD.org@localhost) に訊ね、彼らは NetBSD コアチームに加わることを快く引き受けてくれた。Antti は NetBSD プロジェクトの内外で有名で、とてもたくさんの素晴らしくエキサイティングなアイデアを提案してくれた。もっとも印象的だったのは rump カーネルアーキテクチャだ。Chuck も NetBSD 界隈では有名で、UBC の作業と最近の Linux エミュレーションのコードの作業の 2 つは彼の貢献を表している例だ。

We therefore thank them both for their outstanding work to date, and to their joining the core team to lead and guide progress in the future.

だから我々は彼らのすぐれた活動と、今後も進路を導くためにコアチームに加わってくれたことに感謝する。

For the current core team:

現在のコアチームメンバー:

  • Alistair Crooks -- agc%NetBSD.org@localhost
  • Matt Green -- mrg%NetBSD.org@localhost
  • Antti Kantee -- pooka%NetBSD.org@localhost
  • Chuck Silvers -- chs%NetBSD.org@localhost
  • Yamamoto Takashi -- yamt%NetBSD.org@localhost
  • Matt Thomas -- matt%NetBSD.org@localhost
  • Christos Zoulas -- christos%NetBSD.org@localhost
本日のツッコミ(全8件) [ツッコミを入れる]

Before...

_ みわ [NNTPなんてgopherと同じくらいまったく知らぬ存ぜぬ。やはりエロは世界を救うか...]

_ けなく [レパートリーは少ないですよ! ご飯は、基本的な調理法?とか下ごしらえとかを覚えとくと楽です!多分! 鶏肉安いなー、半..]

_ みわ [( ゜皿゜) キャベツの切り方から覚えることにします]

_ うさだー [いえ、材料の揃え方から覚えてください]

_ みわ [材料を揃えるための服が無い]


2010-08-18 :-(

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

全体がつねに current でありインクリメンタルなので unstable なドッグフードを喰い続けているのである。

ようやく現状を整理できた。

_ 免罪符

「初心者なのですが云々」

「バカですが云々」

「思い上がりかもしれませんが云々」 ←new!


2010-08-19 :-(

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

ぐったり

_ ,

バンドメンバー紹介時に自分を紹介し忘れるのは國府田マリ子もよくやってたなあ

_ ,

近所に家庭菜園しているオッサンを見るんだが、そのひとの家の前には「パソコン教室」という看板があり、そこを通るたびに私は「パソコン教室と言いつつこのひとはきっと超ウィザード級ハッカー(※)であり いつもどこからか私のことを『|e・)』などとウォッチしているに違いない #followme ! 」などと妄想している。今日も暑いですぬ。

攻殻機動隊 STAND ALONE COMPLEX Solid State Society - Wikipedia


2010-08-20 :-)

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

バグ発見

_ 頭が痛い

二日酔いかー

50 度ウィスキーおそろしあ


2010-08-21 :-)

_ [佐渡裕][シエナウインドオーケストラ]佐渡裕指揮 シエナウインドオーケストラコンサート

@河口湖ステラシアター

ohguchi にチケットを確保してもらい、行ってきたった。車乗るぜー超乗るぜー

途中渋滞しており往路 2 時間くらいのつもりが 4 時間かかった。うどん食えなかった (>'A`)>

プレコンサートの開演時間 14:30 には間に合ったのでちんたら見る。森山良子が「この広い野原いっぱい」を歌っていた。このひとが歌ってたのかー。プレコンサートでは複数の中学校のブラスバンド部の少年少女たちが合同で演奏していた。この音楽祭の間は合宿状態になり演奏しておったそうだ。

他校のひとたちと一緒に泊まりがけで富士山麓で野外のコンサートを聞いたりするなどといったことは けいおんの連中も夏フェスに行っていたけど こういうのを見るとけいおん部の気持ちが分かるなあ。もう文化祭のノリだよね。これは楽しい。

写真など

足柄PA でインディカーなんぞ飾ってあった図

IMG_5085

河口湖ステラシアターなのよ。

IMG_5106

そして帰路は渋滞が無くかなりサクサク帰れた。

他の写真 シエナ・ウインド・オーケストラ河口湖ステラシアター 2010-08-21 - a set on Flickr


2010-08-22 :-)

_ 読書

2010年8月9日 - 2010年8月15日の読書メーター
読んだ本の数:1冊
読んだページ数:263ページ

機動戦士ガンダムUC(5)  ラプラスの亡霊 (角川スニーカー文庫 0-105)機動戦士ガンダムUC(5) ラプラスの亡霊 (角川スニーカー文庫 0-105)
死亡フラグ回収しすぎ
読了日:08月13日 著者:福井 晴敏

読書メーター

_ w

暑いのでなんとなく uptime してみたら 3 users と言われて驚いたんだが

rin@hitomi[~]% uptime
12:55PM  up 59 days, 18:08, 3 users, load averages: 0.04, 0.10, 0.08

screen で 3 つセッション作れば 端末が 3 つになるのだからまあそりゃそうか。そうか

rin@hitomi[~]% w
 1:01PM  up 59 days, 18:14, 3 users, load averages: 0.45, 0.22, 0.13
USER     TTY     FROM              LOGIN@  IDLE WHAT
rin      pts/1   192.168.0.14:S.0 27Jun10     7 -/usr/pkg/bin/zsh
rin      pts/2   192.168.0.14:S.1 27Jun10     7 -/usr/pkg/bin/zsh
rin      pts/3   192.168.0.14:S.2 12:53PM     0 w

_ TIME TO COUNTDOWN

getter getter

setter setter

_ RR7 ARC葉月GP延期のお知らせ

PSN障害発生中らしくPSNにサインインできない状態であります。なので本日予定していたレースは延期します。新しい日程についてはまた連絡します。

PlayStation.com(Japan) - PlayStation®Network - 障害・メンテナンス情報

●“PlayStation Network”障害のお知らせ

ただいま、“PlayStation Network”(“PlayStation Store”を含む)へ繋がりにくい障害が発生しております。
調査及び復旧作業を行っておりますので、いましばらくお待ちいただけますようお願いいたします。
お客様には大変ご迷惑をおかけしておりますことをお詫び申しあげます。

【発生日時】2010年8月22日(日) 20:30 ~
【障害内容】“PlayStation Network”へのアクセスができない場合があります。


2010-08-23 :-)

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

_ 大地讃頌

大地讃頌(だいちさんしょう)を中学生のころ合唱したときは何も考えずに歌ってたけどあらためて聴くと「褒めよ称えよ」ばかり連呼していてとてもキモイよな「筑後川の河口」のようにせめて情景の描写があってほしんだがきっと外国のどこかの宗教の歌なんだろうなあ

土の歌 - Wikipedia

混声合唱とオーケストラのためのカンタータ「土の歌」(こんせいがっしょう - つちのうた)は、大木惇夫が作詞、佐藤眞が作曲したカンタータ

日本だったのか

本日のツッコミ(全2件) [ツッコミを入れる]

_ けやきん [今度伴奏やるよ大地讃頌 “だいち”君がいじられまくる曲だよね]

_ みわ [うちのクラスにも「大地」君がいたわー (ノω`)]


2010-08-24 :-)

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

_ この aptitude にはスーパー牛さんパワーなどはありません。

牛さんって?

使用方法: aptitude [-S ファイル名] [-u|-i]
       aptitude [オプション] <アクション> ...
  アクション (指定がない場合、Aptitude はインタラクティブモードで起動します):

:

 --with(out)-recommends 推奨パッケージを強い依存関係として扱うか否かを指定しま
                   す。
 -S <ファイル名> : <ファイル名> から aptitude の拡張状態情報を読み込みます。
 -u              : 起動時に新しいパッケージ一覧をダウンロードします。
 -i             : 起動時にインストールを行います。

                  この aptitude にはスーパー牛さんパワーなどはありません。

_ ほげ

  • ubuntu に rails をインストールしよう
  • rubygems がない
  • aptitude install rubygems
  • gem install rails
  • 302 エラーって言われた
  • ググる
  • つ 最新版
  • ソースからインストール
  • rdoc が無いって
  • sudo apt-get install irb libopenssl-ruby libreadline-ruby libruby rdoc ri ruby ruby1.8-dev ( ref. ubuntuでrails環境構築~ubuntu9.10改訂版~ )
  • gem install rails
  • sudo aptitude install libsqlite3-dev
  • sudo gem install sqlite3-ruby
  • 3.6.x を使えと言われた

?('A`)

$ aptitude show libsqlite3-dev
パッケージ: libsqlite3-dev
状態: インストール済み
自動的にインストールされた: はい(yes)
バージョン: 3.4.2-2

(>'A`)>

_ RR7

TAでHIJACKで遊んでいたらPapoさんに招待されたのでrossoさんの部屋に入ったらカテ3だった。あいかわらず速いなあ


2010-08-25 :-(

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

_ ,

あれ?三菱電機インフォメーションシステムズって

_ [訃報][RIP][今敏]今 敏 永眠のお知らせ - KON'S TONE

今敏の監督作品はこれだけ見た。

今敏 最後の言葉 さようなら - KON'S TONE

_ PERFECT BLUE

1998 年のころ「岩男潤子と荘口彰久のスーパーアニメガヒットTOP10」というラジオ番組があって、当時は岩男潤子が誰なのかすら知らなかったんだが昔からアニメ好きだった私はこっそりと番組を聞いていた。するとなにやら「ダブルバインド THE LOOKING GLASS OF PERFECT BLUE」などといったラジオドラマが放送されており( 内容は猟奇殺人事件を扱ったものなので描写がグロイ )、さらに劇場版も公開開始され、舞台挨拶もあるという。そのことを聞いたときはまったく興味なかったので頭のスミに記憶にとどめておく程度だった。

ある日 「コンピュータ総合学園HAL」( 現在の HAL )でゲーム開発学科だかの体験入学だったか何かがあり、そのイベントに参加し( セガサターンのバーニングレンジャーをプレイしてきた )、その帰りに「そういえばパーフェクトブルーの劇場公開されてるんだったか」と思い出し、ふらふらと渋谷パルコ3 に向かった。映画チケットを購入し、そこそこの長蛇の列が出来上がっていて「まあ劇場公開 間もないころだから混んでるんだろう」と気にしてなかったんだが、中に入ったらなんと舞台挨拶が始まった。それで混んでたのか。舞台挨拶には今敏、荘口彰久、岩男潤子が出演(?)していた。何を語ったのかさっぱり覚えてないんだが、パーフェクトブルーを見たあとにブルーになったこと( 精神的な意味で )は覚えている。

_ ,

どうでもいいが 1998 年の上半期はまだ日記を書いてなかった。学生仲間とメールを頻繁にやり取りしてたはずなんだが、もはやそんなメールは消失した。


2010-08-26 :-)

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

gdbするほうが早いっていう

_ ,

「まさかず」という名前のひとはよくひとから「まさかず」と呼ばれる傾向がある。サンプル数 2


2010-08-27 :-)

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

評価じゃなくてデバッグ

_ ,

ああいけね IRC をどうにかするためにその前に ssh どうにかするために管理人に連絡しないと


2010-08-28 :-)

_ 朝ッ

0700 NHKニュースで佐渡裕特集をやっていたように見えたがすぐに二度寝した

1100 起床

_ にっちゅう!!

1200 ビデオ消化

1300 買い物

1400 コーヒーる

1500 もしドラを読むなど

_ ,

書いてないことを読み取らないでください

_ 24hテレビ

俺が、俺達がAKB48だ

_ chrome

なんとなく Google chrome を日常生活で使おうと思ったんだが Firefox に馴染んだ指には chrome の生活を覚えるには少々面倒くさい。これが老害か

_ [リッジレーサー7]リッジレーサー7 ARC 2010 葉月GP

結果

  1. ANSΩB2マンタレイ 146
  2. Locus 145
  3. emotion21 140
  4. OWA 108
  5. CONTI4X 84
  6. knhtymh 78
  7. ANSΩ三嶋出雲 66
  8. 桜上水すずめ 62
  9. ちゃぶマッ 47
  10. のきあ 31
  11. agumon11 30
  12. ANSΩマリアナブルー 29
  13. ANSΩmiwarin 25
  14. 八雲藍 19

B2さんは最後のレースはまた回線不調により不参加。しかしそれでも 1 位になるあたりはもはやその走りは鬼神のごとく。

今回 emotion21 さん、のきあさんが初参加。emotion21 さん速いなあ。

knhtymh さん、agumon さんは途中から参加。

人数に余裕があったから KAI さん呼べたかな...

そしてマリアナさんは毎度のように回線不調。むう....

本日のツッコミ(全2件) [ツッコミを入れる]

_ キノピオ [そういえばぼくの勝利数が299に近くなった!もしかしたら僕の300勝阻止やる予定です!]

_ みわ [やりましたね。わたしはもう少しがんばれば1000勝になるんだけど、最近さっぱり勝てない (>'A`)>]


2010-08-29 :-)

_ 読書

2010年8月16日 - 2010年8月22日の読書メーター
読んだ本の数:6冊
読んだページ数:1733ページ

放課後の魔術師  (4)ワンサイド・サマーゲーム (角川スニーカー文庫)放課後の魔術師 (4)ワンサイド・サマーゲーム (角川スニーカー文庫)
短編集。ボードゲーム三昧だった。魔法少女ベルがかわいい。そして安芸はあいかわらず酷い朴念仁ぶりw
読了日:08月22日 著者:土屋 つかさ
緋弾のアリア〈2〉燃える銀氷(ダイヤモンドダスト) (MF文庫J)緋弾のアリア〈2〉燃える銀氷(ダイヤモンドダスト) (MF文庫J)
白雪の巻。ハーレムが増えていくなあ。カンピオーネ!みたいだ。次あたりレキが加わるか?
読了日:08月19日 著者:赤松 中学
緋弾のアリア (MF文庫J)緋弾のアリア (MF文庫J)
武器などは具体的な名前が登場するのでミリオタには嬉しいかしら。描写がざっくりしてるのでサクサク読める。
読了日:08月18日 著者:赤松 中学
剣の女王と烙印の仔 5 (MF文庫J)剣の女王と烙印の仔 5 (MF文庫J)
ミネルヴァとシルヴィアのチート的な力が明らかになり物語は収束へ向かうかと思ったらさらにアンゴーラ帝国が登場しカオス。神の力についてはスタンドくらいにありふれてるものだと思うことにした
読了日:08月17日 著者:杉井 光
剣の女王と烙印の仔〈4〉 (MF文庫J)剣の女王と烙印の仔〈4〉 (MF文庫J)
銀卵騎士団はなんだかんだで繋がってる。ニコロもきっと戻ってくるんだろう/カーラ先生の声は脳内で津田匠子の声で再生しておく
読了日:08月16日 著者:杉井 光
カンピオーネ! 7 斉天大聖 (集英社スーパーダッシュ文庫)カンピオーネ! 7 斉天大聖 (集英社スーパーダッシュ文庫)
乳尻ふともも/次々と「最強」が登場するけど今後どうすんだ
読了日:08月16日 著者:丈月 城

読書メーター

_ にっちゅう!!

0930 起床

1000 髪を切った

1100 おひる

1200 だらだら

1500 散歩る

1600 コーヒーる

猫に睨まれた

IMG_5132

_ 日笠陽子

「処女で何が悪い!」などと叫んでいたり 24h テレビのナレーションやってたり。役者はさすがだ

_ [題名のない音楽会]題名のない音楽会 マリオ・ドラクエ・FF~大人気ゲーム音楽SP を見た

たぶんそのうちここにバックナンバーができる http://www.tv-asahi.co.jp/daimei/contents/onair/100829.html

「ファイナルファンタジー」はあいかわらず 7, 8, 9 版だし( オーケストラアレンジしやすいのか? )、植松伸夫とか桜井政博がトークし、錦織健と高橋織子が歌うなどし、すごく... PRESS START でした....

すぎやまこういちによるドラクエ曲は 3 無双だった。おっさんホイホイ


2010-08-30 :-)

_ 朝ッ

0520 起床

_ 仕事

0830 出勤

_ ,

「USBのメモリ」が「ブルースリーのメモリ」に聞こえた。聴くのではない、感じるのだ。

_ ARC 2010 総合得点

B2 無双 ARC2010 - リッジレーサー7

_ photos

contact の写真を眺めてると、私の写真はまったく味わいが無いことを実感する http://www.flickr.com/photos/miwarin/friends/

_ [題名のない音楽会]『題名のない音楽会』ゲーム音楽特集のアレ

helen さんが「感想投げるといいよ」と言っていた( 『題名のない音楽会』ゲーム音楽特集を見たレポート/ぜひ第二弾も・・・! )ので投げてみた。まあこの辺をもう少しキモくなるようにアピールしただけ。

植松伸夫もすぎやまこういちも佐渡裕もオーケストラをもっと親しみやすくしたいと考えてて、彼らが同じ舞台に立ったことは有意義だと思うなのよ (miwarin)


2010-08-31 :-)

_ [CEDEC]CEDEC 2010 - CESA Developers Conference 1日目

オープニングと基調講演は CEDEC の存在意義を確認するものだった。

オープニングスピーチ

  • 和田洋一(CESA会長)
  • 日本ヤバいとよく聞かれるけど日,米,欧,アジアと比較するとそれほどでもない
    • でも違いはある
    • ディスカッションする場があるか無いか
    • 日本には無い
  • 情報や知恵は自分から与えたぶんだけ返ってくる
    • 「このひとに話しておけばもっと教えてくれそう」
  • クリエイターは 0 から 1 を創りだす、と思われている
    • そうじゃない
    • まったく 0 というものはもはや無い
    • 知恵の積み重ねだ
  • なにを what どうやって how 作るのか
    • what は自分の中にだけあるもの
    • how をみんなで共有すればいい

CEDECとは? −そのもたらす価値の追求−

  • 松原健二(CEDECフェロー)

「CEDEC を身近に感じてほしい」

  • 元エンジニア
  • 1980 - 1990
    • IT 業界にいた
    • ( マイクロプロセッサを作ってたということだから {N, F, T, H}か )
    • 当時 日本はメインプレイヤーに成り損ねた
    • もともとメインプレイヤーじゃなかったけど
  • 欠けていたもの 3 つ
    • 危機感の欠如
      • 「日本はこれまでうまくやってきたから大丈夫!」大丈夫じゃない
    • 戦略の欠如
      • 全体が「トップを追え」という姿勢だった
      • トップ = IBM
      • みんな IBM を追いかけていた
      • そんなではトップになれるわけがない
    • 課題共有の欠如
      • 持ってる課題はみんなだいたい同じ
      • でも顕在化できてなかった
      • 海外は課題共有が盛ん
      • そーいうのは全部 hp から学んだ
  • 開発者がやること
    • 進化の確認
    • 危機感の共有
    • 進むべき方向性の確認
  • 自分を高めるのは自分だけ
  • CEDEC とはなんぞや
    • ゲームに関わるひとたちのためのイベント
    • プログラマがプログラミングスキルを上げるだけではない
  • ゲームは開発者のマスターベーションではない
    • ビジネスとして考えよう
    • 売れなきゃ話にならない

ゲームサウンドにおける理想的なサラウンド体験提供への挑戦~技術交流の取り組み事例~

  • 藤澤森茂(ヤマハ)
  • 大橋紀幸(ヤマハ)
  • 矢島友宏(スクウェア・エニックス)
  • 土田善紀(スクウェア・エニックス)

スクウェアのひとからの「RPG の音楽は上下の音を削りまくって圧縮してるんだが FF13 を作るときにそれが不満だった、どうにか出来ないかヤマハさん」という愚痴により始まった技術交流。ソフトウェア担当とハードウェア担当のひとが実現したいことを実現するために妥協点を探す、という取り組みの紹介だった。家庭用の環境向けにチューニングしてイイ感じに出力できるアンプを作ってみました。ということで FF13 をプレイしながらその効果を紹介していた。んだが、違いがあまりよく分からなかった。

抽象化すると:

入力→処理(アンプ)→出力

こんだけっていう

Dub the future of game sound! ~ゲームサウンドの歴史と将来ビジョン~

田中宏和さんに近藤広明さんがインタビューしていく、という形式で進んでいった。途中は会話が途切れそうになったりしてハラハラしたんだがそれでもやはり伝説的なひとの話題なのでけっこう盛り上がった。

田中「横井軍平からの遺言『初対面のひとと ラブテスター すること』ということなのでラブテスターやりましょう近藤さん」

  • 田中宏和の歴史
    • 最初は任天堂でプログラマやってた
    • 音源を設計したり
    • そのうち作曲するようになった
    • 2000 年にクリーチャーズ作った
  • よく「ゲーム音楽のひと」とか「音楽のひと」と言われるけど「サービス業」なんです
    • エンターテイメント、娯楽、サービス業。そーいったことをやってるんです
  • Dub
    • レゲエの Dub
    • 完成させずに音を 1 つ 2 つ抽出して音楽を作る(?)
  • ゲーム音楽専門なわけじゃない
    • ゲームがあっての音楽
    • ゲームすべてを 1 人で作ってたころからの人間なので、まずゲームありきで考えている
  • ネタ帳
    • つねに(エンターテイメントの)ネタを考えている
    • 1 曲作るために 20 曲をボツにするくらい
    • パッと 1 曲だけ作れる、というわけじゃない
    • 背景にたくさんの曲があり、それらを積み重ねて 1 曲を作る
    • こういう姿勢を続けていきたい
  • 自分が変化していないと見えないものがある
    • 走ってるときの風景と止まっているときの風景が異なるように
  • 自分がエンターテイメント、娯楽、サービス業をやるために自分は右往左往しておく

質疑応答

  • 任天堂時代の印象的なひとは誰?
    • 「宮本さん」( 宮本茂 - Wikipedia )
    • とにかく徹底している
    • 四六時中ゲームのことを考えている。あのひとはおかしい :-)
  • 横井軍平との仕事
    • 「仕事は遊び」について
    • ムダと思えることでも省かなかった
    • 仕事のうち 2, 3 割りはムダなことをやっていた
    • でもそれがよかった
    • ( デマルコの「ゆとりの法則」か )
    • それが維持できてるときはうまくいっている
  • BGMとSEの作り方
  • BGM
    • 最初にテーマを 3 つ決める。それから着手する
    • 例: めざせポケモンマスター の場合
      • 好きなコード進行
        • 「アニソンは自分にとって初めての仕事。初めて好きになったコード進行をここで使ってみた」
      • 転調
      • あともう 1 つ。言葉で表現できない
  • SE
    • ユーモアを持たせる
  • 場面と音楽があってる、ぐっときた音楽は?
    • 初期のナムコ作品。ディグダグ等
    • ゲームと音楽とのバランスが絶妙だった
    • 20 歳のころ仕事始めたときの環境は印象に残るものだ
    • 宮本さんも一目置いていた、と思う
  • MOTHER2 の音楽ではメモリなど開発者とモメたか?
    • モメてない
    • 自分が偉そうにしてたので文句言われなかった :-)
  • 自分は自分のイヤな部分から出来ている
    • 任天堂は任天堂のイヤな部分から出来ている
    • ガンコとか、強さとか。そーいうのが特徴を作る
  • どうなるか分からない状況に飛び込め
    • 未知のことが起きるときはチャンス
    • これまでの経験がまったく役立たない状況を楽しめ
    • それは岐路だ。重要な岐路に差し掛かっている

セガ社も認めた静的解析 − ゲーム開発からバグを取り除く方法 

  • 節政暁生(セガ)
  • 内田洋一(セガ)
  • 安竹由起夫(コベリティ)

PR トラックなので Coverity のひとが最初に製品紹介。そのあとにセガのひとが事例紹介。静的解析は私も以前客先でやってたんだが、お客によるとやはり最初はみんなあまり乗り気じゃなく、しかしそれでも解析しておくとそれなりに効果あったらしい。

  • Coverity紹介
  • よくある警告
    • バッファオーバーラン
    • 変数の未初期化
    • 未到達コード。論理演算を誤っている
  • 単純ミスはコード流用時に多い
  • セガ事例
    • 2006 - 2007 開発が大規模化。静的解析やろうぜ
    • 携帯、自動車、組み込み業界では割りと使われている
  • PSU( ファンタシースターユニバース )で実践してみた
    • すでに運営してるのである程度動的解析は出来ている
    • 再現性が低いバグがある
    • 静的解析してみたら発見できた
  • 自動化のメリット
    • 人に言われるとムカつくけど機械に言われるとムカつかない :-)
    • 毎日実行
    • チェックチームは機能チェックに時間を割けるようになった
  • 社外開発にも適用
    • 最初は「面倒くさい」「ほんとに効果あんの?」と懐疑的だったが実際にやってみせると納得してもらえる
  • ライブラリ、ミドルウェアにはよくバグがある
  • 運用実績
    • PC, Xbox360, PS3, PSP....
    • アミューズメントにも使い始めた

社外事例としてファンタシースターポータブルでのアルファシステムとの開発事例。こんな感じだった。アルファシステムからセガへソースコードをコミットして、セガ社内で解析して解析結果を保存しておく。アルファシステムからセガ社内の解析結果をブラウズする。

img_1271.jpg

It's a showtime!! -DISSIDIA FINAL FANTASYのAI設計-

  • 下田翔大(スクウェア・エニックス)

DISSIDIA FINAL FANTASY

AI と言っても学習させていくようなもんじゃなくて、条件 => アクションの組み合わせなのね( awk のように )

  • AIの要件
    • 短時間のバトルで特徴、味を出す
    • 対 AI 戦はショーである
    • FF キャラらしさを醸しだす
  • 性格とスキル
    • 性格
      • 時間、場面ごとにアピールすることを明確にする
      • 朝、昼、晩など。デートを想定してみよう
    • スキル
      • スキル発動の要因は単純にしておく
      • いろいろな要素をからめると分かりづらくなる
    • 性格とスキルをタイムラインに当てはめる
      • 弱いAIはこういうアルゴリズムを適用させない
移動(性格)
  ↓
攻防(スキル)
  ↓
反撃(性格)
  ↓
移動(性格)
  ↓
攻防(スキル)
  • データとプログラム
    • キャラにはデータ 4 つのみ持たせる
      • 射程距離
      • 避け方
      • 攻撃の間合い
      • あとなにか
    • プログラム
      • 移動の仕方は共通
      • 相手のベクトルの手前に向かう
      • 曲線を描く
      • タイミングによってはエアダッシュ
    • これによりプレイヤーと AI が様子をうかがいあうということが出来るようになった
    • 人間くささを演出する
  • アルゴリズム実例
    • 全体構成
      • 自分と相手の HP などの組み合わせごとの行動を決める
      • 基本アルゴリズムを組み合わせて行動セットを作る
      • 攻撃の基本は移動して攻防するだけ
      • 他はエラー、例外処理
    • 反応型にはバグがあった
      • 学習させることにした
      • プレイヤーの攻撃を回避 or ガードの成功率によって行動させる
      • バトル開始後から学習させる
      • (ファイルに保存させずメモリに持つのみということか。そりゃそうか)

質疑応答

  • 参考にしたものは何?
    • スマッシュブラザーズ
    • プレイヤーキャラをまったく動かさずに AI の動きを観察するなど
    • 他に参考にできるゲームがあまり無いのでみんなどんどん発表しようず
  • ワークフロー
    • プログラマの隣で作業
    • AI の仕様( Excel で組み合わせの表を作る )をひたすら作る
    • 実装
  • ゲーム中での強さの設定
    • ゲーム中に設定画面はあるけど、設定させるために仕様を作ったわけじゃない
    • せっかくの仕様があるからプレイヤーに見せよう、ということになった

_ とあるナントカ

社内勉強会ネタとしてスライドをこんなタイトルにしたのも思いで。

これ → とある櫻花の画像生成(ジェネレーター)- とある風画像を自動生成