/ 最近 .rdf 追記 設定 本棚

脳log[2010-04-01~]



2010年04月01日 (木) 3年前に買った本をまた買ってしまった。なんか知ってるエピソードが多いなと思いながらも最後まで読んでるし。素直に 2にしとけばよかった。

最終更新: 2010-04-17T12:02+0900

[無題]

 比例計算

 「全長200kmの道路があります。
 最初の100kmを時速50kmで、
 次の100kmを時速100kmで走りました。
 200kmの道路全体では時速何キロで走りましたか?」

 に非常によく似た問題があった。

 「(100km/h + 50km/h) ÷ 2 で 75km/h!!」

 とお客さまに答えそうになる馬鹿が出た…。
 (省略)

悲しいことに全然笑えない。100km(50km/hで走った距離)と 100km(100km/hで走った距離)を見比べて 1:1だから、足して 2で割って平均を出せばいいやと考えるのは仕方がないというか、頭の中で方程式は解けないからと目の前の数字に飛びついちゃったんだよね。(上の問題はただのたとえらしいけど)算数の問題って火曜サスペンスと同じで与えられる判断材料(数字)に過不足がないことが当たり前になってるから、それに慣れてると考えずに反射的に数字をこねくって答えを出してしまいがち例えばというのもありそう。

(馬鹿ですが)気を取り直して、この場合は走行距離でなく走行時間の比率を基にすれば暗算できたんだろうか。

「全長200kmの道路があります。
  200kmを走り終わったとき、
  2/3の時間を時速50kmで、
  1/3の時間を時速100kmで走っていました。
  道路全体では時速何キロで走りましたか?」

  50 × 2/3 + 100 × 1/3 = 66 (km/h)

ブコメを見た。水溶液濃度の話も出てた。そして最も簡単な考え方は「200km ÷ 3h = 66km/h」だった。ああなんて遠回り。

「調和平均だっけ」とも書かれていた。調和平均の定義を調べて計算したら「2×100×50÷(100+50)」なぜだか(自分の頭ではマジカル)答えが出た。でもこれだと走行距離が 95kmと 105kmだったときにどうすればいいかわからなくなりそう。

例えば 「100gの水に 5gの NaClを溶かしてできる食塩水の質量パーセント濃度は?」という問いに 5%と答えてしまうおバカな中学一年生でした。<<こねくってさえいなかった!


2010年03月31日 (水) (どこへともなくなく) 名詞は proposal...(調べたら propositonも)


2010年03月29日 (月) XRegExp-1.5.0がでている。

最終更新: 2010-04-04T07:43+0900

[正規表現] 正規表現の空の文字クラスのブラウザ実装 > 文字クラス(suika.fam.cx)

まとめはリンク先に任せるとして、最新の Opera(10.51)ではどうかね、と思ってアドレスバーに javascript……と打ち込んだら空の文字クラスのテストスクリプトと思しき、まさに今打ち込もうとしていたものが補完された。笑える(他に Operaの使い道はないのか)。このときの履歴だろう。さておき、結果は

// Opera10.51
/[]/.test("a") //=> false
/[^]/.test("a") //=> true

9.61のときとは違って一般に期待される結果になっているよう。次いで IE8の結果は……どちらもスクリプトエラー。

// IE8
/[]/.test("a") //=> "正規表現の中に ']' を指定してください。" (Perlと同じ。だけど IEのバージョンももう 8だよ)
/[^]/.test("a") //=> "正規表現の中に ']' を指定してください。" (Perlと同じ。だけど IEのバージョンももう 8だよ)

// このエラーが導くのは、パターンのこういう解釈と結果。
/[]]/.test("]") //=> true
/[^]]/.test("]") //=> false

変わっていない。ECMAScript3に準拠するならマッチ結果の食い違いはともかくエラーはないはずだけど。

ちょっと前にニュースになった IE9 Preview版(IEBlog : About the Platform Preview)もせっかくだしインストールして試してみた。「IEBlog : The New JavaScript Engine in Internet Explorer 9」なんて記事も見つけたし。結果は /[]/.test("a") も /[^]/.test("a") もクラッシュ。残念至極。


2010年03月28日 (日)

最終更新: 2010-03-29T02:44+0900

[無題]

 Google画像検索についての続き。>前回

Alt+←で前のページに戻れるようになっている。余計な閲覧履歴がはさまって一回で戻れなかったりもしない一方ソニーは。ただ、一瞬前の画像に戻るような動作を見せてから前のページに移動するのが後付けっぽくてスマートでないし、まれにページ移動に失敗して前の画像に移動するだけのことがある。行き過ぎて前の画像に戻りたいこともあるだろうし、どの画像から第二のモードに入ったかを覚えておいたらいいと思うんだけどね。

一方ソニーは Cyber-shot DSC-HX5Vのページ<http://www.sony.jp/cyber-shot/products/DSC-HX5V/>を表示すると閲覧履歴に 4つのエントリが追加され、戻るボタンなど一つ前のページに移動する操作を連打しても抜け出すことができない蟻地獄。しかしそれが 5つのブラウザのうち Firefox3.6だけの現象となると Firefoxがいけてないだけかもね。


2010年03月26日 (金)

最終更新: 2010-03-28T06:40+0900

TSF関連再読

最初のリンク先の「余談その 1 - 誰がプリエディットを描画しているか?」で説明されているように、未確定文字列を IMEに表示してもらうアプリケーションと自分で描画するアプリケーションが存在する。メモ帳とサクラエディタは前者。ワードパッドと Firefoxは後者。全然意識してなかったけど、確かに Firefoxなどでは確定前の文字列によってその後ろの文字列が押し流されていく。また、テキストを選択した状態で日本語を入力し始めた場合の動作も異なっていて、Firefoxやワードパッドでは入力をキャンセルしたとしても最初に選択されていた文字列が消えてしまう。確定前の文字列がアプリケーションの状態を変更することがあるのに全然気づいてなかった。マウスクリックによって文字列の挿入位置を確定直前に変更することもできなくて、未確定文字列が確定されてしまうだけ。こんなにも使い勝手がちがうとは(全然気にしてなかったけど)。

 Google日本語入力

たなかゆう……で「田中優美清春香菜」「田中優美清秋香菜」が出てくるのが強みだねえ。2ch語や四字熟語のもじりなどが上位にきて間違いを助長されると困るけど。

Windows XP SP3 + Opera10.10 + Google日本語入力 = Operaクラッシュの件(Google日本語入力をインストールしたところ、Operaが起動できなくなりました。 - Google 日本語入力ヘルプ)で触れられていたが、Google日本語入力は TSFでいうところの Text Serviceとして動いていて IMM32に直接は対応していないらしいので、TSFベースの文脈依存変換のテストに使えるかと思ってインストールしたのだが Google日本語入力に文脈依存変換はないみたい。少なくとも(実装方法が似てそうな)再変換機能は確実にないらしく、いくつも要望があがっている。

再変換は使わないからいいんだけどこっちの方、「『半角/全角』で日本語入力をオフにした際、それまでの未確定文字を全て消したい - Google 日本語入力ヘルプ」「IMEをオフにしたとき、変換確定していない文字を消去できるようにして欲しい - Google 日本語入力ヘルプ」「変換確定前の半角/全角キー押下によるキャンセル動作 - Google 日本語入力ヘルプ」この一つの要望だけはかなえてもらわないと使えない。

 MSDN

Parameters

(省略)

acpEnd [in]
Specifies the ending character position. If this parameter is 1, then return all text in the text store.

(省略)

Remarks

(省略)

If acpEnd is -1, then it should be handled as if set at the end of the stream. Otherwise, it will be greater than or equal to zero.

なんで 1?最初の一文字を取得したいときはどうすれば?と思ったけど、-1の間違いだよね。びっくりさせる。


2010年03月25日 (木) マリア様がみてるが実写映画化。小説は全部楽しんで読んでるけど、実写はギャグか痛いものにしかならんでしょうよ。平成の日本や日本人では舞台が成立しないよ。ギャグと紙一重>『[単行本] 加藤 ゑみ子【お嬢さまことば速修講座 (midi hard)】 ディスカヴァー・トゥエンティワン』省略しないだとかゆっくり話すだとかまねしたい内容もあるけど、大部分は浮世離れした遠い世界のお話で面白おかしい。


2010年03月24日 (水)

最終更新: 2010-03-25T02:39+0900

5月12日発売 [CD] 【BKK to NRT】 キングレコード

BKK to NRT BKK to NRT
Neko Jump
キングレコード
¥ 2,940

1stアルバム『[DVD Audio] 【Neko Jump (初回限定版)】 bmi』を再販売してくれるほうが嬉しいけどね。


2010年03月21日 (日) [リーンベル] チョイポリスで詰まってる。放置してクリアもできるんだけど難易度が上がる二周目ではさらに不利になるから今なんとかしたい。レベルを上げて力押しでなんとかなるゲームではない。レベルアップの効果は装備可能重量の増加と HPアップとダメージ微増だけど、装備可能重量は LV80を超えたら十分(ていうか武器レベル上限(100)を前にしてもう増えない)。HPはあほほど多いか 1のどちらかがいいから、もはやレベルアップしたくないというのが本当のところ。アイテムを駆使してダメージをおさえる必要があるんだけど攻撃は最大の防御でがんがん突っ込んでいきたい。それができなくて面白くない。爽快感なし、ターミナル利用不可ではそれまでのゲーム性の否定ですよ。(おまけだからそれも許されるとは思うけど)


2010年03月19日 (金)

最終更新: 2010-03-27T22:03+0900

[CB100] 届いた。

怖くてヘリの電源は入れていない。パーツの細いところはシャーペンの芯ほどの太さしかないよ。

 モード1からモード2へ

備考欄に書き忘れてモード1のプロポ(WK-2402)が届いてしまった。エレベーターとエルロンが 1つのスティックにまとまっているモード2に変更したい。WK-2402はモード1から 4まで選ぶことができるんだけど、モードを 1から 2にするとスロットルスティックが右から左に移動する。スロットルだけは自動でニュートラルポジションに戻らないものらしいから、その機械的仕組みも左右で入れ替える必要があって、ケースを開けなければいけない。でもねじの頭が六角形のくぼみだった。自転車のブレーキのバネ調節用のサイズが使えるかもしれないが試せてない試した

画面に表示される設定を見てみると、モード(1)、スロットル(normal)、ラダー(reverse)、エレベーター(reverse)、エルロン(reverse)だった。ほとんど reverseなんだけどそういうもんだろうか。

1.5V×8本(=12V)でも 1.2V×8本(=9.6V)でも使えるって書いてある。8本も直列だしどうなのかと思ったが充電池可。

 誤字

電源を入れてないから、できるのは観察とマニュアル読みだけなわけで。CB100 User Handbookと WK-2402 User Manualの誤字拾い。

ページメモ
CB100 UH4ページ。表の 6番目Gyro sensitivity adjustment knod~knob
5ページ。一番下Gyro turning knob~tuning~6ページには「gyro tuning knob」という語が登場する。knodでも turningでもなく、おそらくこれが正解。
11ページ。8.5.1(2) If the two blades are even during rotating.Check if~if節だけで文が終わってしまっている。(1)とそろえるなら Check whether~で。
13ページ。2.Move the elevator trim down if the helicopter flies down during takeoff; otherwise move it up.~flies forward~離陸と下方に飛ぶのを同時に行うのは無理だと思います。※downがどちらを意味するのかは同文書内で既に定義済み。
WK-2402 UM左側の(笑) 1ページ。Party two: Function SetupPart two~
右側の 1ページ。1.2 Satety Needing AttentionSafety~
5ページ。図Fixing Scew~Screw
8ページ。5.3.1 Right-hand throttle swtiched to left-hand throttle~switched~
10ページ。5.4A. Stick tention adjustment of~~tension~
10ページ。5.4B. Stick tention adjustment of~~tension~
12ページ。Party two: Function SetupPart two~
12ページ。, teh buzzer rings, and 4 trims bars begining to make stream-like movements. After the ID binding is both buzzering and trim bars stream-like movements stop,, the buzzer~begin to~the ID binding is finished, both buzzing and trim bars' stream-like~全く同じ文章が CB100 User Handbookにあるのでそれにならって、beginningでなく beginに訂正する。4 trims barsというのも 4 trim-barsとかにできんかな。buzzingも CB100 UHにならった。アポストロフィ・エスは必要な気がしたけどどうだろう。これは CB100 UHの方にもなかった。
不明不明-j--i-単語の中の iが jに化けていた。

CB100の User Handbook(pdf)に CB100Dというのが載っている。レシーバーとモーターが違う。ブラシレスじゃないとか?

メインローターの固定が想像よりずっと緩くてぷらぷらしてるんだけど、これもこういうもんなんだろうか。

メインローターとテイルローターの回転数は連動してるんだろうか? 上昇・下降するたびにラダートリムをカチカチするものなんだろうか。

 @2010-03-20: まわしてみた。

メインローターは上から見て時計回り。テイルローターは右側から見て反時計回り。メインローターが回り始める閾値がわりと高い。そろりそろりあけていくといきなり勢いよく回り出してびっくりする。そこからスロットルを戻すと恐くない回転数まで落ちる。テイルローターの動き出すスロットルの位置はメインローターよりも上。そのくせメインローターが回転を止めてからもまだ回っていたりする。右ラダーで回転数が上がる(尾部を左に押す)のがわかるけど左ラダーが何を制御しているのかわからない。こんなんで飛ばせるのかなあ。

 @2010-03-21: まだ飛んでない

六角レンチ(インチとミリのセットがあって、ミリの方で間に合った)と小さいドライバーを買ってきてプロポをモード2へ。ラダーを動かすときにスロットルがずれると嫌だからとラダーのバネをゆるめたらその調節ネジがケースに当たってスロットルが 30%までしか下がらなくなり、いっそネジがないのが一番緩いんではと思ってそうするとバネが外れてしまって、それを元に戻すのに苦労したり。奥の様子を確認するために明かり(携帯電話のフラッシュ)を用意したりバネを引っ張るためにひもを用意したり、するのがいいだろうなと思いながら横着してエイヤっで引っ掛けようとしてもダメで、急がば回れ。

 @2010-03-27: 1バッテリー。2バッテリー。

1バッテリー目はひたすら、一瞬浮いてはスロットルオフの繰り返し。だってまっすぐ浮いてくれないから。メインローターの反トルクに負けて尾部が右を向くからとラダートリムを調整したら、テイルローターに押されて今度は全体が左へ流れる。それをエルロンで調節する。ゆっくり浮かぶと一瞬遅れる尾部が布団に引っかかったままでラダーと関係なく機体が左を向くので離陸も素早く行わなければいけない。ということを体に覚えてもらっていた。2バッテリー目でようやく浮かんでからエルロンを操作する暇を見つけられるようになって、滞空時間が 5秒くらいに。ラダーとスロットルが留守だから機体の向きは制御できないし天井にも何度かぶつかった。

試した さらに 2つ小さいサイズだった。軸があまりに細くてまわすとねじれる。普通のサイズのプラスネジでいいじゃない。スロットルスティックがもどらないのはバネじかけのバネが元に戻る力をネジで止めてるからなんだけど、このネジを回すプラスドライバーが今度はない。小さくてありものではなめてしまう。明日(21日)こそは飛ばしたい。その前にラダーの操作を逆(右に倒すと左を向く)にするかどうか決めないといけないが。


2010年03月17日 (水)

最終更新: 2010-03-19T03:37+0900

[無題]

 ダイソンのわっか扇風機。

ヘリコプターには、テイルローター部分にプロペラ(地面に近いから人に当たりやすい)ではなく空気の排出口を設けて、メインローターから吹き下ろしてくる風の流れをコアンダ効果でコントロールして左右方向の機体制御に用いるものがあるらしい。(すべて Wikipedia:ヘリコプターからの受け売り)

コアンダ効果で、なぜか、思い出したのがダイソンの"羽根なし"扇風機。この連想の根拠を検索で探してみたけど、動画の紹介やこうしたらこうなった的な解説がほとんどだったので、ようやく見つけた数少ない読める記事へのリンクをはる。(※コアンダ効果は関係ありません)

 グレート ジャバ

Javaの良いところは、String#substring, split, replace, +, +=, equalsだけ知っていれば処理時間がグレートなコードが書けることだ。

このあと頭の悪そうな(そう見える。「牛刀をもって鶏を割く」ような)コードが例示されているから"グレート"は皮肉なのかと思ったんだけど、Javaのコンパイラが"グレート"な可能性も捨てきれないでいる。最後に

もっと処理時間をグレートにするにはどうすればよいだろうか?

なんてあるから、グレートな処理時間はコンパイラでなくコードに由来するものらしく、やっぱり皮肉なのかなとも思うけど……。


2010年03月16日 (火) ドロッセルお嬢様をプログラムしたいな。

最終更新: 2010-04-11T06:16+0900

[][CB100] Walkera HM CB100

超小型電動ヘリコプターCB100(調整済) 超小型電動ヘリコプターCB100(調整済)

Walkera
¥ 27,300

プログラムできる USB接続のガジェットを物色していたはずが、ロボットを経由してなぜかなぜなのか電動ヘリへ。

最終的にはメインローターが可変ピッチの Walkera 4G3を飛ばしたいものだけど、あっといまに墜落させるのが目に見えているので、その前に浮かび上がれるのかどうかも怪しいずぶの素人なので、最初は超安定と噂される CB100。それでも 4ch シングルローターなのは、誰かが評していたように「電動竹とんぼ」を飛ばす程度の気楽さではすぐ飽きるだろうし、上向きのテイルローターによって前(後)進するものは何か違う気がする。細長い機体の両側にローターがあったり反対回転するローターが同じ軸の上下に付いているものも合理的なんだろうけど正統ではない気がするので。

CB100カテゴリを用意したけど、あれを壊したこれを壊したという報告ばかりが続く予感。

初めて買った Interface誌(2010年1月号)の特集がモーターでいろいろな種類が比較とともに紹介されていたが、ブラシレスモーターのありがたみやデメリットが電動ヘリでよくわかる。

FSXにはヘリのデータも収録されていたはずだから、そちらで十分に墜落させておく手もある。

国内の通販で頼んだんだけど、「モード1から 2に変更できます。備考に書いておいてね」という注意書きを見落としていて、気付いたときには当然のようにモード1で発送された後だった。まだなんの癖もついてないからモード1でも 2でも関係ないんだけど、何を操作するのかを考えたときに、エレベーターとエルロンが右スティックにまとまっているモード2の方がわかりやすい(スロットルとラダーは残った左スティックを共用することになる)。

原状回復のためにデジカメが必要。やっとこさ GPSと電子コンパス内蔵モデルが手に入るようになったけどマクロ機能も欲しい。(絵と関係ない)スペックにこだわるくせに全然使うつもりがないので一万円台がなんとか出せるレベル。操作は物理的なスイッチやダイヤルがいいですよ、手になじむ(視認する必要がない)ので。借り物だったらタッチの方がいいかもしれんけど。

なぜなのか LEDが点灯するようなのよりは運動系の出力がいい。無線でコントロールできるとなお良い。見た目って大事。アイディアも技術もないのでキットあるいは完成品を。という経過をたどった。


2010年03月10日 (水) 自転車とイヤフォンの組み合わせってノイズキャンセリング関係なく敵視されるけど、窓を閉め切った自動車やフルフェイスヘルメットをかぶってエンジンの真上に頭が来る自動二輪を運転するよりは断然外界の音が聞こえている。エンジン回してる人は耳に頼った運転しないでしょう(ハンズフリーなら電話しててもいいわけだし)。自転車だって同じ。だから NWD-W202(なにが「だから」だ)。Bluetoothも考えたけどあれもこれも充電するのは面倒だし、レシーバーが結局ちょっとした MP3プレイヤーなみの大きさになるので汎用的に使う意図がなければ不必要。


2010年03月08日 (月) obsoleteって形容詞だと思うんだけど推測辞書に obsoletedや obsoletingが含まれてるんだよね(辞書には載っていないが)。obsoleted - Wiktionaryによれば nonstandardだけど一部の分野で使われている、ということらしい。

最終更新: 2014-12-05T17:23+0900

[tDiary] spam絨毯爆撃対策

送信元が限られてるのかワンパターンだったので、これまでは </a> を NGワードにしてほとんどの spamを防いでいたんだけど、今日は手ひどくやられた。

フィルタはインストール方法がよくわからない。Comment-key Filterを tdiary/filter/ に設置したがエラーが出るので、とりあえず最新の 2.3.3.20091124にアップデートした。そうすると plugin/60sf.rbが有効になっているはずなので misc/filter/ にフィルタスクリプトを、misc/filter/plugin/ にフィルタに関連する設定などを表示するプラグインスクリプトを、misc/filter/plugin/ja/ などにプラグインの言語リソースをインストールし、設定画面でフィルタを有効にするといずれのスクリプトも読み込まれるようになる。

 スパムフィルタ1: Comment-key Filter & Plugin version 0.5.0

コメントフォームにキー文字列を埋め込み、コメントが HTMLフォームを通して投稿されたことを確認する。キーは日記設置者の決めた文字列と日記の日付によって一意に決められるので、ある日のキー文字列を一度取得すればその日には何件でも機械的に投稿することができる。GETして HTMLを切り刻む手間をかければ最初から機械的に投稿することもできる。そんなのは防げない。

tDiary-2.3.3.20091124にインストールするのなら key.rbを misc/filter/key.rbへ、comment_key.rbを misc/filter/plugin/key.rbへ、ja/comment_key.rbを misc/filter/plugin/ja/key.rbへコピーすれば良い。key.rbというファイル名と KeyFilterというクラス名は対応しているので、key.rbから comment_key.rbへの改名はやめたほうがいい。コピー後にフィルタを有効にし、キー文字列を設定する。

 スパムフィルタ2: limit_freq.rb

連投対策。同じ IPアドレスからの連続する投稿をはじく。30分につき 3件までしか許可しない、など。

# coding: utf-8
#
# limit_freq.rb: 
#
#  a spam-filtering plugin of tDiary
#  rejects frequent comments posted from an IP address.

module TDiary::Filter
	class LimitFreqFilter < Filter

		def comment_filter( diary, comment )
			now = Time.now.to_i
			comment_i = Comment_t.new( now, @cgi.remote_addr )

			# 数値形式の日時と文字列形式の IPアドレスの二要素
			# 配列の配列を、日時をもとに昇順にソートしたもの。
			# log = [[123456, "1.2.3.4"], [234567, "5.6.7.8"],...]
			log = []

			require 'pstore'
			ps = PStore.new( cache_path )
			ps.transaction( false ) { |db|
				log = db.fetch( DBRoot, log )

				# 新しいコメントを logに追加する。
				log.insert( ArrayExtension.lower_bound(log){|pair| pair.first - comment_i.time }, [comment_i.time, comment_i.ipaddr] )

				# 古い logを捨てる。
				oldest = now - time_span
				log.slice!( 0 ... ArrayExtension.lower_bound(log){|pair| pair.first - oldest } )

				db[DBRoot] = log
				db.commit
			}

			# 残った logに投稿者の IPアドレスがいくつ含まれるか数え、
			# その数が閾値を超えていないか確かめる。
			count = 0
			if log.all?{|pair|
				count += 1 if pair.last == comment_i.ipaddr
				count < threshold
			} then
				return this_is_not_a_spam( comment )
			else
				debug("limit_freq.rb: spam: the # of comments posted from #{comment_i.ipaddr} exceeds threshold:#{threshold} within the last #{time_span.to_i}seconds.")
				return this_is_a_spam( comment )
			end
		rescue
			debug("limit_freq.rb: BUG: #{$!}")
			return this_is_not_a_spam( comment )
		end

	private
		DBRoot = 'LimitFreqLog'
		Comment_t = Struct.new(:time, :ipaddr)

		def cache_path
			return File.join( (@conf.cache_path || "#{@conf.data_path}cache"), 'limit_freq.data' )
		end

		# どれだけの期間(秒単位)、コメントの投稿頻度の判定に
		# 利用するログ(日時とIPアドレスのペア)を保存するか。 
		def time_span
			30 * 60
		end

		# time_span当たり、何件目の投稿からを拒否するか。
		def threshold
			4
		end

		module ArrayExtension
			# ソート済みだという前提を活かしていない!
			def lower_bound( arr, &block )
				index = 0
				arr.length.times{
					return index if 0 <= yield( arr[index] )
					index += 1
				}
				return index
			end
			module_function :lower_bound
		end
	end
end

やめればいいのに本体もちょろちょろと変更。

  • 設定画面における [セキュリティ]>[spamフィルタ]>「spamの扱い spamと判定されたツッコミを{非表示にする|捨てる}」という項目は tdiary/filter/spam.rbに固有の設定らしいのだが、そんなこととは夢にも思わないので、最初は自作のフィルタでスパム判定したコメントが捨てられることに困惑した。設定を本体に取り込んで他のフィルタからも利用しやすくした。
  • limit_freq.rbや limit-freq.rbや limit_--_freq.rb というフィルタに対しては LimitFreqFilterという名前のクラスを要求するようにした。(これらのファイルが複数存在するときは困るなあ。読み込み順で最終定義が変わりそう)
  • どういうわけか無名クラスの下に定義された TDiary::Filter定数を参照してエラーになるので ::TDiary::Filterとした。
Index: core/tdiary.rb
===================================================================
--- core/tdiary.rb	(リビジョン 44436)
+++ core/tdiary.rb	(作業コピー)
@@ -342,6 +342,22 @@
 
 				@logger.info("#{@cgi.remote_addr}->#{(@cgi.params['date'][0] || 'no date').dump}: #{msg}")
 			end
+
+		private
+			# config: hide or drop spam comment
+			def hide_spam?
+				return @conf.options.include?('spamfilter.filter_mode') && @conf.options['spamfilter.filter_mode']
+			end
+
+			def this_is_a_spam( comment )
+				comment.show = false
+				return hide_spam?
+			rescue
+				return false # comment could be a String(@cgi.referer).
+			end
+			def this_is_not_a_spam( comment )
+				return true
+			end
 		end
 	end
 
@@ -1303,7 +1319,7 @@
 			filter_path = @conf.filter_path || "#{PATH}/tdiary/filter"
 			Dir::glob( "#{filter_path}/*.rb" ).sort.each do |file|
 				require file.untaint
-				@filters << TDiary::Filter::const_get( "#{File::basename( file, '.rb' ).capitalize}Filter" )::new( @cgi, @conf, @logger )
+				@filters << TDiary::Filter::const_get( "#{File::basename( file, '.rb' ).split(/[-_]+/).map{|x|x.capitalize}.join('')}Filter" )::new( @cgi, @conf, @logger )
 			end
 		end
 
Index: core/plugin/60sf.rb
===================================================================
--- core/plugin/60sf.rb	(リビジョン 44436)
+++ core/plugin/60sf.rb	(作業コピー)
@@ -4,10 +4,9 @@
 # Modified by KURODA Hiraku.
 
 SF_PREFIX = 'sf'
-@sf_path = ( @conf["#{SF_PREFIX}.path"] || "#{::TDiary::PATH}/misc/filter" ).to_a
-@sf_path = @sf_path.collect do |path|
-	/\/$/ =~ path ? path.chop : path
-end
+@sf_path = ( @conf["#{SF_PREFIX}.path"] || "#{::TDiary::PATH}/misc/filter" ).to_a.map{|path|
+	path.chomp('/')
+}
 
 # get plugin option
 def sf_option( key )
@@ -128,7 +127,7 @@
 			if File.readable?( path ) then
 				begin
 					require path
-					@sf_filters << TDiary::Filter::const_get("#{File::basename(filename, ".rb").capitalize}Filter")::new(@cgi, @conf, @logger)
+					@sf_filters << ::TDiary::Filter::const_get("#{File::basename(filename, ".rb").split(/[-_]+/).map{|x|x.capitalize}.join('')}Filter")::new(@cgi, @conf, @logger)
 					plugin_path = "#{dir}/plugin/#{filename}"
 					load_plugin(plugin_path) if File.readable?(plugin_path)
 				rescue Exception

 @2010-03-09: IPアドレスブロック

一件二件すり抜けるぐらいはいいかと思っていたがここ数日は毎日なのでいいかげん腹が立つ。なによりアクセスログを見たらヒット数、転送量トップが spammerだというのが決定的に許せない。節度を知れ。iptablesはいじれないので .htaccessで Apacheに拒否してもらう。


 @2010-03-11: 対応が早いね

spamコメントがくる月っていうのは、いつもの決まった 2、3か国からのアクセスではなく 10近い国から少数ずつアクセスがあるもんだけど、日単位では固定の IPアドレスから数十件の spamがくるのが常だった。でも今日は一件一件みごとに IPアドレスが異なっている。IPアドレスブロックで次のステージに進んでしまったのか。

spamコメントの目的が特定の URLへの誘導であるかぎりは、コメントに含まれる URLのドメインが白か黒かを判定する方法が有効でしょうね。外部に問い合わせるのは避けたかったんだけど、spamコメントの内容が URLも含めてワンパターンだから実際の問い合わせはごくごく限られた回数にできそうだし、悪くないかな。

 CodeRepos

ここで上記の comment-keyフィルタも含めてスパムフィルタの最新版が管理されていた。 >http://coderepos.org/share/browser/platform/tdiary/filter


 こぼれ話: rel="true"

plugin/00default.rbに含まれるメソッド navi_itemを自分でも使っていたのだけど、tDiaryをアップデートしたら三番目の引数が真偽値からリンクの rel属性文字列へと変更されているせいで rel="true" なるリンクができていた。こうする。

def navi_item( link, label, rel = nil )
	rel = "nofollow" if rel == true # backward compatibility

 @2010-03-09: 日記の編集もキャッシュベース?

スパムコメント一掃のために YYYYMM.tdcを削除したけど日記の編集画面からコメントが消えない。YYYYMM.parserを開くとコメントが含まれていたし、これを削除すると編集画面からもコメントが消えた。原因はデータファイルを直接削除するというイレギュラーな操作だけど、日記の編集はマスターデータに対して行いたい気もする。