package HNS::Diary;
# $Id: Diary.pm,v 1.24 2000/07/30 03:53:57 kenji Exp $
################################################################
=head1 NAME
HNS::Diary - diary class
=head1 SYNOPSIS
use HNS::Diary;
my $diary = new HNS::Diary(filename=>'d19990331.hnf');
$diary->Read;
$diary->Print($reverse_sec);
=head1 DESCRIPTION
filename attributes must be set in new() or SetFilename()
=cut
################################################################
use strict vars;
use ObjectTemplate;
use DateTime::Date;
use CodeConv;
use HNS::Hnf::TreeBuilder;
use HNS::Hnf::UserVar;
use HNS::Hnf::Warning;
use HNS::Template;
use HNS::Status;
#require 'jcode.pl';
use vars qw(@ISA $Head $UserVar $Foot @WeekString);
@ISA = qw(ObjectTemplate);
=head1 MEMBER VARIABLES
filename
year,month,day
tree
user_var
last_modified
read_done
=cut
attributes qw(filename year month day tree user_var last_modified
read_done has_user_var);
# template
=head1 STATIC VARIABLES
$Head
$Foot
$UserVar
@WeekString
=cut
$Head = qq(
%year/%month/%day (%week) %user{TENKI}
\n);
$UserVar = qq(
%user{TENKI}%user{BASHO}%user{TAIJU}%user{TAION}%user{SUIMIN}%user{BGM}
%user{HOSU}
);
$Foot = qq(
\n);
#
@WeekString = ('Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat');
################################################################
sub initialize($)
{
my $self = shift;
$self->tree(new HNS::Hnf::TreeBuilder);
$self->user_var(new HNS::Hnf::UserVar);
$self->SetFilename($self->filename)
if ($self->filename);
$self->has_user_var(0);
}
=head2 $d->SetFilename($filename);
ファイル名をセットする
=cut
sub SetFilename($$)
{
my ($self, $filename) = @_;
my ($y, $m, $d) = $self->filename =~ /d(\d{4})(\d{2})(\d{2})\.hnf$/;
unless ($y && $m && $d){
die "not hnf file: " . $self->filename;
}
$self->year($y), $self->month($m), $self->day($d);
# set last_modified
$self->last_modified((stat($self->filename))[9]);
}
################################################################
=head2 $d->Read;
読み込む
=cut
sub Read($)
{
my $self = shift;
my $ok;
my $warning_message;
my ($year, $month, $day) = ($self->year, $self->month, $self->day);
my $xhnf = "$HNS::System::CacheDir/$year/$year$month$day.xhnf";
# xhnf checking
if ($HNS::System::Caching) {
# caching on
if (-f $xhnf) {
my $xhnf_lm = (stat($xhnf))[9];
if (($self->last_modified == $xhnf_lm)
|| ($HNS::System::AllowCacheOnly && ! -e $self->filename)) {
$self->read_done(1);
return;
}
}
}
# open the file and read
open (F, $self->filename) || die $self->filename;
while (){
# convert kanji charactor code to euc
CodeConv::toeuc(*_);
# convert to entity reference
s/&/&/g;
s/>/>/g;
s/</g;
# CR+LF to LF
s/\r$//;
# parse
if ($ok){ # body part
$self->tree->Parse($_);
} else { # head part
if (/^OK$/){ # line 'OK'
$ok = 1;
} elsif (/^([A-Z]+)\s(.*)$/){ # User Variable
unless ($self->user_var->Account($1, $2)){
$warning_message .=
&HNS::Hnf::Warning::Message('UndefinedUserVar', $1);
}
else {
$self->has_user_var(1);
}
} else { # illegal line in head part
$warning_message .= HNS::Hnf::Warning::Message('IllegalHeader');
}
}
}
close F;
$self->read_done(1) if $ok;
if ($ok && $warning_message){ # OK and warning exist
$self->tree->{top}->UnshiftContent($warning_message);
}
}
################################################################
=head2 $d->Print($revserse_sec);
表示する
$revserse_secがTRUEならセクションを逆順に表示する
=cut
sub Print($$)
{
my $self = shift;
my $reverse_sec = shift;
return unless $self->read_done;
my ($year, $month, $day) = ($self->year, $self->month, $self->day);
my $dateDayHi = int($day/10);
my $xhnf = "$HNS::System::CacheDir/$year/$year$month$day.xhnf";
my $date = new DateTime::Date(year=>$year, month=>$month, day=>$day);
my $templ = new HNS::Template;
my $abc;
if ($day < 11) {
$abc = "a";
}
elsif ($day < 21) {
$abc = "b";
}
else {
$abc = "c";
}
$templ->SetParamValues(year=>$year, month=>$month, day=>$day,
high=>int($day/10), abc=>$abc,
week=>$WeekString[$date->week]);
# xhnf checking
if ($HNS::System::Caching) {
# caching on
my $date_time = sprintf(qq(%s), $HNS::Status->date_time);
my $cache_file = "$HNS::System::DiaryDir/log/cache_log";
if (-f $xhnf) {
my $xhnf_lm = (stat($xhnf))[9];
# hit
if (($self->last_modified == $xhnf_lm)
|| ($HNS::System::AllowCacheOnly && ! -e $self->filename)) {
Display ($xhnf, $reverse_sec);
# hit logging
if ($HNS::System::CacheLog eq 'ON') {
my $cache_log = new SimpleDB::Append("$cache_file");
$cache_log->Append("$date_time $year$month$day hit\n");
}
#unlink $xhnf unless $HNS::System::Caching;
return;
}
}
else {
my $xhnf_dir = "$HNS::System::CacheDir/$year";
unless(-d $xhnf_dir) {
mkdir $xhnf_dir, 0755;
}
}
# miss logging
if ($HNS::System::CacheLog eq 'ON') {
my $cache_log = new SimpleDB::Append("$cache_file");
$cache_log->Append("$date_time $year$month$day miss\n");
}
}
else {
# caching off
$HNS::Diary::Hnf = "";
}
# head
my $head = $HNS::Diary::Head;
$head =~ s/%user{([A-Z]+)}/$self->user_var->Eval($1)/ge; # user var
$templ->SetTemplate($head);
if ($HNS::System::Caching) {
open (X, ">$xhnf") || die "can't write cache file, $xhnf";
eval 'flock(X, LOCK_EX)';
}
HnfPrint ($templ->Expand);
if ($self->has_user_var) {
my $user_var = $HNS::Diary::UserVar;
$user_var =~ s/%user{([A-Z]+)}/$self->user_var->Eval($1)/ge; # user var
$templ->SetTemplate($user_var);
HnfPrint ($templ->Expand);
}
# diarys
$self->tree->Print($self->year, $self->month, $self->day,
$HNS::Diary::section);
# foot
# xhnf control code
HnfPrint ("\n\n");
$templ->SetTemplate($HNS::Diary::Foot);
HnfPrint ($templ->Expand);
if ($HNS::System::Caching) {
close X;
}
utime($self->last_modified, $self->last_modified, $xhnf);
Display ($xhnf, $reverse_sec);
#unlink $xhnf unless $HNS::System::Caching;
}
# real display of diary
sub Display ($$) {
my $xhnf = shift;
my $reverse_sec = shift;
#print "xhnf: $xhnf
\n";
my %GRP_DB;
my ($tmp, $tmp2); # $tmp2 is not for writing to xhnf
if ($HNS::System::Caching) {
tie $tmp2, 'SimpleDB::Scalar', "$xhnf", 1;
$tmp = $tmp2;
}
else {
$tmp = $HNS::Diary::Hnf;
}
if ($HNS::Diary::section) { # one section display
my @section = split(//, $tmp);
my $last = @section - 1;
my $count = 1;
if ($HNS::Diary::section =~ /^G(\d+)/) { # is GRP section?
$HNS::Diary::section = $1;
while ($count <= $HNS::Diary::section) {
unless ($section[$count] =~ /^$/m) {
$HNS::Diary::section++;
}
$count++;
}
$section[$HNS::Diary::section] =~
s/^$//m;
my @grp = split (" ", $1);
unless (defined %GRP_DB){
tie %GRP_DB, 'SimpleDB::Hash',
"$HNS::System::DiaryDir/conf/group.txt", 1;
}
my $id = $HNS::Status->id;
$id = "XXXXXXXXXXXXXXXXX" if length($id) < 17;
foreach my $grp (@grp) {
unless ($GRP_DB{$grp} =~ /$id/) {
$section[$HNS::Diary::section] = "";
}
}
}
else { # normal section
while ($count <= $HNS::Diary::section) {
if ($section[$count] =~ /^$/m) {
$HNS::Diary::section++;
}
$count++;
}
}
print $section[0]; # day head
print $section[$HNS::Diary::section];
print $section[$last]; # day foot
}
else { # normal, not one section
my @grp_display;
while ($tmp =~ /^$/m) {
$tmp =~ s/^$//m;
my @grp = split (" ", $1);
#print "grp: @grp
\n";
unless (defined %GRP_DB){
tie %GRP_DB, 'SimpleDB::Hash',
"$HNS::System::DiaryDir/conf/group.txt", 1;
}
my $id = $HNS::Status->id;
$id = "XXXXXXXXXXXXXXXXX" if length($id) < 17;
my $display = 0;
foreach my $grp (@grp) {
if ($GRP_DB{$grp} =~ /$id/) {
$display = 1;
}
}
push (@grp_display, $display);
}
#print "grp_display: @grp_display
\n";
foreach my $flg (@grp_display) {
if ($flg) {
$tmp =~ s///s;
}
else {
$tmp =~ s/.*?//s;
}
}
if ($reverse_sec) {
my @out = split(/\