RIGHT:[[:t/検索]]
#contents
*流れ [#ob994459]
検索/フォーマット、検索/ソートは機能で。いくつでも何種類でも組み合わせて。
検索/フィルタリングが検索特有の処理。
検索/スコアリング、検索/フォーマット、検索/ソートは汎用の機能で。
検索/クエリーはページ/作成処理の一部。
**ページ生成時 [#l95b1a28]
+ページ(文字列)→ページ(オブジェクト)
保存。永続化。検索時に使えるようにするため。
#br
**検索時 [#x7261d2e]
+検索式→オブジェクト
検索式(文字列)→検索式(オブジェクト)
ページ(オブジェクト)と同じ型。比較するため。
++オブジェクト選択
比較時、検索/クエリー側のオブジェクト1つとページを構成するオブジェクト1つを選択しなければならない。
検索/クエリー側は評価順が静的に決まっている。
ページ側の順序はページが決めるので後回し。
検索/クエリー側は1回だけ走査。ページ側は検索/クエリーの要素数だけ繰り返し参照される。
++比較
同じクラスのオブジェクト同士の比較。
検索/クエリーのスコア算出処理にページ側のオブジェクトを渡す→検索/スコアリング
++スコア計算
検索/スコアリングの方法でページを構成するオブジェクトごとに計算。
計算方法は検索/クエリーに含まれる修飾句オブジェクト次第。
**検索時(オプション) [#p279b843]
検索以外にも使える機能で。
順序も組み合わせも自由。
+出力用データ生成
検索/フォーマットの機能で検索結果に含めるデータと、検索/ソートに渡すデータ生成。
ページ単位で結果を出すなら、ページごとにスコアを集計、ページごとにデータ生成。
+ソート
%%検索/ソートの機能で検索結果に含めるデータを並び替え。%%
→検索/ソートは機能/表に移す。
----
で、検索結果生成。
HTML化。これはページ/責務。正確にはページの下位にある検索用記法の責務。
※スコア加算、集計、ソートが分かれているのは繰り返しの単位や範囲が違うから。
※すべて検索/クエリーで作ったオブジェクトの機能で行う。
→[[プロトタイピング]]
*コード [#xd31fa4e]
→[[:i/検索/流れ/コード]]
* コード [#xd31fa4e]
package main;
use strict;
use Smart::Comments;
{
my @elements;
@elements = (Element::PlainText->new(' *** Sample sites ***'), Element::URI->new('http://1.com/3rd'), Element::URI->new('http://3.com/2nd/'), Element::URI->new('http://2.com/1st/'));
{
### not sorted, not filtered:
my $page = Page->new(@elements);
print $page->out();
}
print "\n--------\n";
{
### sorted:
my $page = Page->new(Element::Container::Sort->new(@elements));
print $page->out();
}
print "\n--------\n";
{
### link list:
my $page = Page->new(Element::Container::Filter->new(@elements));
print $page->out();
}
print "\n--------\n";
{
### link list sorted by label:
my $page = Page->new(Element::Container::Sort->new(Element::Container::Filter->new(@elements)));
print $page->out();
}
print "\n--------\n";
}
package Page;
sub new
{
my $class = shift;
bless { element => [@_] }, $class;
}
sub elements
{
my $self = shift;
map { $_->elements() } @{$self->{element}};
}
sub out
{
my $self = shift;
join "\n", map { $_->out() } $self->elements();
}
sub string
{
my $self = shift;
join '', map { $_->string() } $self->elements();
}
package Element::Container::Sort;
sub new
{
my $class = shift;
bless { element => [@_] }, $class;
}
sub elements
{
my $self = shift;
my @r;
foreach (@{$self->{element}}){
push @r, $_->elements();
}
sort { $a->string() cmp $b->string() } @r;
}
sub out
{
my $self = shift;
map { $_->out() } $self->elements();
}
sub string
{
my $self = shift;
join '', map { $_->string() } $self->elements();
}
package Element::Container::Filter;
sub new
{
my $class = shift;
bless { element => [@_] }, $class;
}
sub elements
{
my $self = shift;
my @r;
foreach (@{$self->{element}}){
push @r, map {
$_->fetch_by('label') =~ m%http://[^/]*/([^/]*)%;
ref($_)->new($_->fetch_by('uri'), $1);
}
grep {
$_->isa('Element::URI');
} $_->elements();
}
@r;
}
sub out
{
my $self = shift;
map { $_->out() } $self->elements();
}
sub string
{
my $self = shift;
join '', map { $_->string() } $self->elements();
}
package Element::URI;
sub new
{
my $class = shift;
my($uri, $label) = @_;
$label = $label ? $label : $uri;
bless { uri => $uri, label => $label }, $class;
}
sub elements
{
$_[0];
}
sub out
{
my $self = shift;
'<a href="'.$self->{uri}.'">'.$self->{label}.'</a>';
}
sub fetch_by
{
my $self = shift;
my($request) = @_;
my $r;
if ($request eq 'label'){
$r = $self->_label();
}
elsif ($request eq 'uri'){
$r = $self->_uri();
}
else {
$r = $self->string();
}
$r;
}
sub string
{
my $self = shift;
$self->{label};
}
sub _uri
{
my $self = shift;
$self->{uri};
}
sub _label
{
my $self = shift;
$self->{label};
}
package Element::PlainText;
sub new
{
my $class = shift;
bless { text => $_[0] }, $class;
}
sub elements
{
$_[0];
}
sub out
{
$_[0]->{text};
}
sub fetch_by
{
my $self = shift;
$self->string();
}
sub string
{
$_[0]->{text};
}
------------------------------------------------
### not sorted, not filtered:
*** Sample sites ***
<a href="http://1.com/3rd">http://1.com/3rd</a>
<a href="http://3.com/2nd/">http://3.com/2nd/</a>
<a href="http://2.com/1st/">http://2.com/1st/</a>
--------
### sorted:
*** Sample sites ***
<a href="http://1.com/3rd">http://1.com/3rd</a>
<a href="http://2.com/1st/">http://2.com/1st/</a>
<a href="http://3.com/2nd/">http://3.com/2nd/</a>
--------
### link list:
<a href="http://1.com/3rd">3rd</a>
<a href="http://3.com/2nd/">2nd</a>
<a href="http://2.com/1st/">1st</a>
--------
### link list sorted by label:
<a href="http://2.com/1st/">1st</a>
<a href="http://3.com/2nd/">2nd</a>
<a href="http://1.com/3rd">3rd</a>
--------