MojoMojo (CatalystベースのWiki)を入れてみた

MojoMojoというCatalystベースのWikiが気になったので手元のmacbookに入れてみた。

MojoMojo

なかなか便利そう。

MIME::Lite::HTMLで図書館の新着を追いかける

図書館も新着のRSSとか出すようにしたほうがいいと思うんだけどなぁ。良い本との出会いは心を豊かにするんだったら、出会う頻度をあげるような努力をするのもまぁ図書館の役割なんじゃないかなとか。

と、本当はそんなことはどうでもよくてMIME::Lite::HTMLってのを使えばURLを指定するだけで、HTMLをメールで送ってくれるってのが便利そうだったので、最近使い勝手の悪いサービスの中から適当なサンプルとして図書館の新着検索が選択されただけでした。

プルをプッシュに的な。

use MIME::Lite::HTML;
MIME::Lite::HTML->new(
         From        => 'kzfm@***.jp',
         To          => '***@gmail.com',
         HTMLCharset => 'utf8',
         Subject     => '図書館新着',
         Url         => 'http://library.fujishi.jp/opw/******');

検索結果のURLを渡してHTMLCharsetをきちんと指定すればOK。あとはcronに登録。

Chemistry::Mol

Chemistry::Molでちょっとはまった。

Can't call method "symbol" on an undefined value

というエラーでつまづいた。

my $mol2 = $mol->clone;

Makes a copy of a molecule. Note that this is a deep copy; if your molecule has a pointer to the rest of the universe, the entire universe will be cloned! my $mol2 = $mol->safe_clone;

Like clone, it makes a deep copy of a molecule. The difference is that the copy is not "exact" in that new molecule and its atoms and bonds get assigned new IDs. This makes it safe to combine cloned molecules. For example, this is an error:

    # XXX don't try this at home!
    my $mol2 = Chemistry::Mol->combine($mol1, $mol1);
    # the atoms in $mol1 will clash

But this is ok:

    # the "safe clone" of $mol1 will have new IDs
    my $mol2 = Chemistry::Mol->combine($mol1, $mol1->safe_clone);

肥大化するリスト

こんな感じで肥大化するリストをつくると(実際にやりたいことは実行途中のあるタイミングでリストの先頭に戻ってループさせながらリストを大きくしたい)

my @l = (0);

for my $n (@l) {
  push @l,$n+1;
  print $n,"\n";
}

数百万件のデータを処理したいので、これをDBIx::Classを使ってやろうと。

で、こんな風に書きました。

#!/usr/bin/perl

#-- tables
#
#create table compounds (
#    id         integer PRIMARY KEY not null,
#    num        integer not null
#);
#insert into compounds values(null,1);

package TestSchema;
use strict;
use base qw/DBIx::Class::Schema::Loader/;

__PACKAGE__->loader_options(
    debug => 1,
    exclude => qr/^sqlite_/,
);  

package Main;

my $schema = TestSchema->connect('dbi:SQLite:dbname=test.db');
my $rs = $schema->resultset('Compounds')->search;

while (my $row = $rs->next) {
  my $n = $row->num;
  $schema->resultset('Compounds')->create({num => $n+1});
  printf "* %s\n", $n;
}

この場合、データの行数が一つだとうまくいかない(next一回で終了してしまう。2個以上データが入っていればリストの時のコードの様に動く)。でも、初期データは一つしかないので困る。ダミーでなんか入れとけばいいのだけど、BFSっぽく繰り返したい場合ダミーのデータは邪魔だし、なんか無駄なことやっている気がする。

うまいやり方ないもんか。

「すぐわかる オブジェクト指向 Perl」を読んだ

いくつかあやふやな知識が解消されてよかった。

ProductName すぐわかる オブジェクト指向 Perl
深沢 千尋
技術評論社 / ¥ 3,780 ()
通常24時間以内に発送


続・初めてのPerlと一緒に読むか併せて読めばよいのではなかろうか?

ProductName 続・初めてのPerl 改訂版
Randal L. Schwartz,brian d foy,Tom Phoenix,吉川 英興,伊藤 直也,田中 慎司,株式会社ロングテール/長尾 高弘
オライリー・ジャパン / ¥ 3,360 ()
通常24時間以内に発送

CPAN Testerからメールが来た

CPANって地味に凄いなと。

An automated check of reports sent to CPAN Testers detected some issues with
your CPAN Testers configuration.  Please check your configuration and upgrade
out-of-date modules to help ensure your test reports are consistent with
the latest bug fixes and CPAN Testers standards.

Issues are listed in YAML format with number of occurrences by architecture and
Perl version since the last notification.  If you upgraded recently, this list
may cover reports since the notice, but prior to your upgrade.  If so, please
disregard those items.

---
i386-linux:
 5.8.8:
   CPAN::Reporter out-of-date (1.08 < 1.17): 1
   Test::Reporter out-of-date (1.38 < 1.5): 1

早速アップデート

setuidされたCGIを実行するためのperl

ごくたまにこんなことやりたかったりすることありますよね。

use File::Tail;

sub get_ip{
  my $line = File::Tail->new(name => "/var/log/httpd/access_log", tail => 1)->read();
  my ($ip) = split / /, $line;
  return $ip;
}

print "Content-Type: text/plain\n\n", get_ip();

rootじゃないとアクセスできないのでsetuidする必要がありますが、それだけだとエラー吐いてうごかないので、fedora8もそれ用のperlが必要。

yum install perl-suidperl

スクリプトも

#!/usr/bin/suidperl

ではじめる必要がある。

参考 - Perl でsetuid されたCGIの実行

Web::Scraperではてブスクレイピング

自分のブログをブックマークしたひとのはてダをLDRで購読する事が多いので、scrapeしてURLを表示させてみる

use URI;
use Web::Scraper;
use List::MoreUtils qw/uniq/;

my $uri = URI->new('http://b.hatena.ne.jp/bookmarklist?url=http://blog.kzfmix.com');

my $scraper = scraper {
  process 'dt.bookmarker a',
    'users[]'=> '@href';
};

my $res = $scraper->scrape($uri);

print join "\n", map { s/b.hatena/d.hatena/;$_} uniq(@{$res->{users}});

あとはこの結果をGmailに送ればよいような。

Imagerでlomo風に

lomo風にしてみたくなった。

sample

NK705で撮ったサンプルをlomo風味に。

sample_lomo

コード

use Imager;

my $source = shift;
my $lsat = 0.0;
my $usat = 0.2;
my $contrast = 1.5;
my $scale = 1.5;

my $img = Imager->new();

$img->read(file => $source);

my ($halfwidth, $halfheight)  = ($img->getwidth/2, $img->getheight/2);
my ($endx, $endy);

if($img->getwidth > $img->getheight){
  $endx = $img->getwidth;
  $endy = $halfheight;
}
else {
  $endx = $halfwidth;
  $endy = $img->getheight;
}

# contrast & sat
$img->filter(type=>"contrast", intensity=>$contrast);
$img->filter(type=>"autolevels", lsat=>$lsat, usat=>$usat);

# fountain
my $overexpo = $img->copy;
$overexpo->filter(type     => "fountain",
        ftype    => 'radial',
        channels => 2,
        xa       => $halfwidth,
        ya       => $halfheight,
        xb       => $endx,
        yb       => $endy);

my $vignette = $overexpo->scale(
                scalefactor=>$scale
                   )->crop(
                       left=>($scale-1)*$halfwidth,
                       top=>($scale-1)*$halfheight,
                       width=>$img->getwidth,
                       height=>$img->getheight
                      );

$img->compose(src=>$nradial,tx=>0,ty=>0,opacity=>0.6,combine=>"mult");
$img->compose(src=>$overexpo,tx=>0,ty=>0,opacity=>0.4,combine=>"subtract");


$img->write(file => "lomonized.png");

こんな感じのレイヤーを重ねたイメージ。

sample_lomo

GIMP Lomo Pluginのソースを見ながらつくったのだけど、Imagerのアルファチャンネルの使い方がよくわからなかったのでちょっとさぼってる。そのせいで白のあたりが飛んでしまうのが気に入らない。

Chart::Clicker

Chart::Clickerを試してみた

use Chart::Clicker;
use Chart::Clicker::Data::Series;
use Chart::Clicker::Data::DataSet;

my $cc = Chart::Clicker->new;

my $series = Chart::Clicker::Data::Series->new(
     keys    => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
     values  => [ 42, 25, 86, 23, 2, 19, 103, 12, 54, 9 ],
                          );

my $series2 = Chart::Clicker::Data::Series->new(
     keys    => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
     values  => [ 67, 15, 6, 90, 11, 45, 83, 11, 9, 101 ],
                           );

my $ds = Chart::Clicker::Data::DataSet->new(series => [ $series, $series2 ]);

$cc->add_to_datasets($ds);

$cc->draw;
$cc->write('foo.png')

Cairoベースなので結構きれい。

sample chart

最近はグラフはもっぱらmatplotlibなんですが、使い分けられればいいかもしれない。