summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/VNDB/Handler/VNPage.pm635
1 files changed, 227 insertions, 408 deletions
diff --git a/lib/VNDB/Handler/VNPage.pm b/lib/VNDB/Handler/VNPage.pm
index 183d56a4..ea7bdbdf 100644
--- a/lib/VNDB/Handler/VNPage.pm
+++ b/lib/VNDB/Handler/VNPage.pm
@@ -45,6 +45,147 @@ sub rg {
$self->htmlFooter;
}
+
+# Description of each column, field:
+# id: Identifier used in URLs
+# sort_field: Name of the field when sorting
+# what: Required dbReleaseGet 'what' flag
+# column_string: String to use as column header
+# column_width: Maximum width (in pixels) of the column in 'restricted width' mode
+# button_string: String to use for the hide/unhide button
+# na_for_patch: When the field is N/A for patch releases
+# default: Set when it's visible by default
+# has_data: Subroutine called with a release object, should return true if the release has data for the column
+# draw: Subroutine called with a release object, should draw its column contents
+my @rel_cols = (
+ { # Title
+ id => 'tit',
+ sort_field => 'title',
+ column_string => '_relinfo_title',
+ draw => sub { a href => "/r$_[0]{id}", shorten $_[0]{title}, 60 },
+ }, { # Type
+ id => 'typ',
+ sort_field => 'type',
+ button_string => '_relinfo_type',
+ default => 1,
+ draw => sub { cssicon "rt$_[0]{type}", mt "_rtype_$_[0]{type}"; txt mt '_vnpage_rel_patch' if $_[0]{patch} },
+ }, { # Languages
+ id => 'lan',
+ button_string => '_relinfo_lang',
+ default => 1,
+ has_data => sub { !!@{$_[0]{languages}} },
+ draw => sub {
+ for(@{$_[0]{languages}}) {
+ cssicon "lang $_", mt "_lang_$_";
+ br if $_ ne $_[0]{languages}[$#{$_[0]{languages}}];
+ }
+ },
+ }, { # Publication
+ id => 'pub',
+ sort_field => 'publication',
+ column_string => '_relinfo_publication',
+ column_width => 70,
+ button_string => '_relinfo_publication',
+ default => 1,
+ what => 'extended',
+ draw => sub { txt mt $_[0]{patch} ? '_relinfo_pub_patch' : '_relinfo_pub_nopatch', $_[0]{freeware}?0:1, $_[0]{doujin}?0:1 },
+ }, { # Platforms
+ id => 'pla',
+ button_string => '_redit_form_platforms',
+ default => 1,
+ what => 'platforms',
+ has_data => sub { !!@{$_[0]{platforms}} },
+ draw => sub {
+ for(@{$_[0]{platforms}}) {
+ cssicon $_, mt "_plat_$_";
+ br if $_ ne $_[0]{platforms}[$#{$_[0]{platforms}}];
+ }
+ txt mt '_unknown' if !@{$_[0]{platforms}};
+ },
+ }, { # Media
+ id => 'med',
+ column_string => '_redit_form_media',
+ button_string => '_redit_form_media',
+ what => 'media',
+ has_data => sub { !!@{$_[0]{media}} },
+ draw => sub {
+ for(@{$_[0]{media}}) {
+ txt $TUWF::OBJ->{media}{$_->{medium}} ? $_->{qty}.' '.mt("_med_$_->{medium}", $_->{qty}) : mt("_med_$_->{medium}",1);
+ br if $_ ne $_[0]{platforms}[$#{$_[0]{platforms}}];
+ }
+ txt mt '_unknown' if !@{$_[0]{media}};
+ },
+ }, { # Resolution
+ id => 'res',
+ sort_field => 'resolution',
+ column_string => '_relinfo_resolution',
+ button_string => '_relinfo_resolution',
+ na_for_patch => 1,
+ default => 1,
+ what => 'extended',
+ has_data => sub { !!$_[0]{resolution} },
+ draw => sub {
+ if($_[0]{resolution}) {
+ my $res = $TUWF::OBJ->{resolutions}[$_[0]{resolution}][0];
+ txt $res =~ /^_/ ? mt $res : $res;
+ } else {
+ txt mt '_unknown';
+ }
+ },
+ }, { # Voiced
+ id => 'voi',
+ sort_field => 'voiced',
+ column_string => '_relinfo_voiced',
+ column_width => 70,
+ button_string => '_relinfo_voiced',
+ na_for_patch => 1,
+ default => 1,
+ what => 'extended',
+ has_data => sub { !!$_[0]{voiced} },
+ draw => sub { txt mtvoiced $_[0]{voiced} },
+ }, { # Animation
+ id => 'ani',
+ sort_field => 'animation',
+ column_string => '_relinfo_ani',
+ column_width => 110,
+ button_string => '_relinfo_ani',
+ na_for_patch => '1',
+ what => 'extended',
+ has_data => sub { !!($_[0]{ani_story} || $_[0]{ani_ero}) },
+ draw => sub {
+ txt join ', ',
+ $_[0]{ani_story} ? mt('_relinfo_ani_story', mtani $_[0]{ani_story}):(),
+ $_[0]{ani_ero} ? mt('_relinfo_ani_ero', mtani $_[0]{ani_ero} ):();
+ txt mt '_unknown' if !$_[0]{ani_story} && !$_[0]{ani_ero};
+ },
+ }, { # Released
+ id => 'rel',
+ sort_field => 'released',
+ column_string => '_relinfo_released',
+ button_string => '_relinfo_released',
+ default => 1,
+ draw => sub { lit $TUWF::OBJ->{l10n}->datestr($_[0]{released}) },
+ }, { # Age rating
+ id => 'min',
+ sort_field => 'minage',
+ button_string => '_relinfo_minage',
+ default => 1,
+ has_data => sub { $_[0]{minage} != -1 },
+ draw => sub { txt minage $_[0]{minage} },
+ }, { # Notes
+ id => 'not',
+ sort_field => 'notes',
+ column_string => '_redit_form_notes',
+ column_width => 400,
+ button_string => '_redit_form_notes',
+ default => 1,
+ what => 'extended',
+ has_data => sub { !!$_[0]{notes} },
+ draw => sub { lit bb2html $_[0]{notes} },
+ }
+);
+
+
sub releases {
my($self, $vid) = @_;
@@ -54,460 +195,138 @@ sub releases {
my $title = mt('_vnpage_rel_title', $v->{title});
$self->htmlHeader(title => $title);
-
$self->htmlMainTabs('v', $v, 'releases');
- # the order of buttons and columns
- my @columb_list = ( 'type',
- 'languages',
- 'publication',
- 'platforms',
- 'media',
- 'resolution',
- 'voiced',
- 'ani_ero',
- 'released',
- 'minage',
- 'notes');
-
- # All data specific to the individual columns
- my %c = (
- 'title' => { column_string => '_relinfo_title',
- },
- 'type' => { button_string => '_relinfo_type',
- },
- 'languages' => { button_string => '_relinfo_lang',
- unsortable => 'true',
- },
- 'publication' => { column_string => '_relinfo_publication',
- column_width => 'max-width: 70px',
- button_string => '_relinfo_publication',
- },
- 'platforms' => { button_string => '_redit_form_platforms',
- unsortable => 'true',
- },
- 'media' => { column_string => '_redit_form_media',
- button_string => '_redit_form_media',
- unsortable => 'true',
- },
- 'resolution' => { column_string => '_relinfo_resolution',
- button_string => '_relinfo_resolution',
- na_for_patch => '1',
- },
- 'voiced' => { column_string => '_relinfo_voiced',
- column_width => 'max-width: 70px',
- button_string => '_relinfo_voiced',
- na_for_patch => '1',
- },
- 'ani_ero' => { column_string => '_relinfo_ani',
- column_width => 'max-width: 110px',
- button_string => '_relinfo_ani',
- na_for_patch => '1',
- },
- 'released' => { column_string => '_relinfo_released',
- button_string => '_relinfo_released',
- },
- 'minage' => { button_string => '_relinfo_minage',
- },
- 'notes' => { column_string => '_redit_form_notes',
- column_width => 'max-width: 400px',
- button_string => '_redit_form_notes',
- },
- 'legend' => { unsortable => 'true',
- },
- );
-
my $f = $self->formValidate(
- { get => 'typ', required => 0, default => '1', enum => [ '0', '1' ] }, # type
- { get => 'lan', required => 0, default => '1', enum => [ '0', '1' ] }, # language
- { get => 'pub', required => 0, default => '1', enum => [ '0', '1' ] }, # publication
- { get => 'pla', required => 0, default => '1', enum => [ '0', '1' ] }, # platform
- { get => 'med', required => 0, default => '0', enum => [ '0', '1' ] }, # media
- { get => 'res', required => 0, default => '1', enum => [ '0', '1' ] }, # resolution
- { get => 'voi', required => 0, default => '1', enum => [ '0', '1' ] }, # voiced
- { get => 'ani', required => 0, default => '0', enum => [ '0', '1' ] }, # animation
- { get => 'rel', required => 0, default => '1', enum => [ '0', '1' ] }, # released
- { get => 'min', required => 0, default => '1', enum => [ '0', '1' ] }, # min age
- { get => 'not', required => 0, default => '1', enum => [ '0', '1' ] }, # notes
- { get => 'cw', required => 0, default => '0', enum => [ '0', '1' ] }, # restrict column width
- { get => 'o', required => 0, default => '0', enum => [ '0', '1' ] }, # sort order
- { get => 's', required => 0, default => 'released', enum => [ grep !$c{$_}{unsortable}, keys %c ]}, # sort by column
- { get => 'os', required => 0, default => 'all', enum => [ 'all', @{$self->{platforms}} ] }, # filter by os
- { get => 'lang', required => 0, default => 'all', enum => [ 'all', @{$self->{languages}} ] }, # filter by language
+ map({ get => $_->{id}, required => 0, default => $_->{default}||0, enum => [0,1] }, grep $_->{button_string}, @rel_cols),
+ { get => 'cw', required => 0, default => 0, enum => [0,1] },
+ { get => 'o', required => 0, default => 0, enum => [0,1] },
+ { get => 's', required => 0, default => 'released', enum => [ map $_->{sort_field}, grep $_->{sort_field}, @rel_cols ]},
+ { get => 'os', required => 0, default => 'all', enum => [ 'all', @{$self->{platforms}} ] },
+ { get => 'lang', required => 0, default => 'all', enum => [ 'all', @{$self->{languages}} ] },
);
return $self->resNotFound if $f->{_err};
- # Get the releases
- # Setup $what_string to use only the bare minimum to reduce database load
- my $what_string = '';
- $what_string .= ' extended' if $f->{pub}||$f->{res}||$f->{voi}||$f->{ani}||$f->{not};
- $what_string .= ' platforms' if $f->{pla};
- $what_string .= ' media' if $f->{med};
- my $r = $self->dbReleaseGet(vid => $vid, what => $what_string, sort => $f->{s}, reverse => $f->{o});
+ # Get the release info
+ my %what = map +($_->{what}, 1), grep $_->{what} && $f->{$_->{id}}, @rel_cols;
+ my $r = $self->dbReleaseGet(vid => $vid, what => join(' ', keys %what), sort => $f->{s}, reverse => $f->{o});
# url generator
my $url = sub {
- my($type, $new_val, $new_sort_type) = @_;
-
- # create a link, which includes all settings in $f
- my $generated_url = "/v$vid/releases?";
- foreach ( keys %$f ) {
- if ($_ eq 's' && $type eq 'o' ) {
- # changing o changes s as well
- $generated_url .= ';s=' . $new_sort_type;
- next;
- }
- $generated_url .= ';' . $_ . '='.($type eq $_ ? $new_val : $f->{$_});
- }
- return $generated_url;
+ my %u = (%$f, @_);
+ return "/v$vid/releases?".join(';', map "$_=$u{$_}", sort keys %u);
};
div class => 'mainbox releases_compare';
h1 $title;
if(!@$r) {
- # No releases to write in table
- # End before drawing anything in the table
td mt '_vnpage_rel_none';
} else {
+ _releases_buttons($self, $f, $url, $r);
+ }
+ end 'div';
- # change all column hide/show status to $new_val while keeping the rest of the settings untouched
- my $all_url = sub {
- my($new_val) = @_;
+ _releases_table($self, $f, $url, $r) if @$r;
+ $self->htmlFooter;
+}
- my $generated_url = "/v$vid/releases?";
- foreach my $key ( keys %$f ) {
- # Note all columns have a length of 3 while non-columns have lengths different from 3
- $generated_url .= ';' . $key . '='. (length($key) == 3 ? $new_val : $f->{$key});
- }
- return $generated_url;
- };
- my $get_lang_plat_list = sub {
- my($type) = @_;
+sub _releases_buttons {
+ my($self, $f, $url, $r) = @_;
- my @return_array = ();
- for my $rel (@$r) {
- for my $element (@{$rel->{$type}}) {
- push(@return_array, $element) if not (grep $_ eq $element, @return_array);
- }
- }
- return sort(@return_array); # sort to make order consistent
- };
+ # Column visibility
+ p class => 'browseopts';
+ a href => $url->($_->{id}, $f->{$_->{id}} ? 0 : 1), $f->{$_->{id}} ? (class => 'optselected') : (), mt $_->{button_string}
+ for (grep $_->{button_string}, @rel_cols);
+ end;
- my $all_selected = sub {
- my($value) = @_;
+ # Misc options
+ my $all_selected = !grep $_->{button_string} && !$f->{$_->{id}}, @rel_cols;
+ my $all_unselected = !grep $_->{button_string} && $f->{$_->{id}}, @rel_cols;
+ my $all_url = sub { $url->(map +($_->{id},$_[0]), grep $_->{button_string}, @rel_cols); };
+ p class => 'browseopts';
+ a href => $all_url->(1), $all_selected ? (class => 'optselected') : (), mt '_all_on';
+ a href => $all_url->(0), $all_unselected ? (class => 'optselected') : (), mt '_all_off';
+ a href => $url->('cw', $f->{cw} ? 0 : 1), $f->{cw} ? (class => 'optselected') : (), mt '_vnpage_restrict_column_width';
+ end;
- for (@columb_list) {
- if (!$f->{substr($_,0,3)} != !$value) {
- return 0;
- }
- }
- return 1;
- };
-
- # Language and platform drawing code is almost identical. Skip writing it twice
- my $plat_lang_draw = sub {
- my($row, $option, $lang) = @_;
-
- if (!$f->{substr($row, 0, 3)}) {
- # Column is hidden
- # Do not display row of platforms/flags as they aren't read from the database
- # Set filter to all as it makes no sense to try to filter by hidden and potientially unread data
- $f->{$option} = 'all';
- return;
+ # Platform/language filters
+ my $plat_lang_draw = sub {
+ my($row, $option, $l10nprefix, $csscat) = @_;
+ my %opts = map +($_,1), map @{$_->{$row}}, @$r;
+ return if !keys %opts;
+ p class => 'browseopts';
+ for('all', sort keys %opts) {
+ a href => $url->($option, $_), $_ eq $f->{$option} ? (class => 'optselected') : ();
+ $_ eq 'all' ? txt mt '_all' : cssicon "$csscat $_", mt $l10nprefix.$_;
+ end 'a';
}
+ end 'p';
+ };
+ $plat_lang_draw->('platforms', 'os', '_plat_', '') if $f->{pla};
+ $plat_lang_draw->('languages', 'lang','_lang_', 'lang') if $f->{lan};
+}
- p class => 'browseopts';
- foreach ( 'all', $get_lang_plat_list->($row)) {
- a href => $url->($option, $_), $_ eq $f->{$option} ? (class => 'optselected') : ();
- $_ eq 'all' ? txt mt '_all' :
- cssicon "$lang $_", mt '_' . substr($row, 0, 4) . '_' . $_;
- end 'a';
- };
- end 'p';
- };
- p class => 'browseopts';
- foreach ( @columb_list ) {
- my $short_name = substr($_, 0, 3);
- a href => $url->($short_name, $f->{$short_name} ? 0 : 1), $f->{$short_name} ? (class => 'optselected') : (), mt $c{$_}{button_string};
- };
- end;
- p class => 'browseopts';
- a href => $all_url->(1), $all_selected->(1) ? (class => 'optselected') : (), mt '_all_on';
- a href => $all_url->(0), $all_selected->(0) ? (class => 'optselected') : (), mt '_all_off';
- a href => $url->('cw', $f->{cw} ? 0 : 1), $f->{cw} ? (class => 'optselected') : (), mt '_vnpage_restrict_column_width';
- end;
+sub _releases_table {
+ my($self, $f, $url, $r) = @_;
- $plat_lang_draw->('platforms', 'os', '' );
- $plat_lang_draw->('languages', 'lang', 'lang');
- }
- end 'div';
- if(!@$r) {
- $self->htmlFooter;
- return;
- }
+ # Apply language and platform filters
+ my @r = grep +
+ ($f->{os} eq 'all' || ($_->{platforms} && grep $_ eq $f->{os}, @{$_->{platforms}})) &&
+ ($f->{lang} eq 'all' || ($_->{languages} && grep $_ eq $f->{lang}, @{$_->{languages}})), @$r;
- # Remove all releases which fails to meet the platform and language filter settings
- my $counter = 0;
- while ($counter <= $#$r) {
- my $rel = @$r[$counter];
- if (($f->{os} eq 'all' || $f->{os} ~~ $rel->{platforms}) &&
- ($f->{lang} eq 'all' || $f->{lang} ~~ $rel->{languages}) ){
- $counter++;
- } else {
- splice @$r, $counter, 1;
- }
- };
+ # Figure out which columns to display
+ my @col;
+ for my $c (@rel_cols) {
+ next if $c->{button_string} && !$f->{$c->{id}}; # Hidden by settings
+ push @col, $c if !@r || !$c->{has_data} || grep $c->{has_data}->($_), @r; # Must have relevant data
+ }
div class => 'mainbox releases_compare';
table;
- $counter = 0;
- my @column_types = ( 'title' );
- foreach ( @columb_list ) {
- next if not $f->{substr($_, 0, 3)}; # skip columns unselected in f
- if (_column_is_in_use($r, $_)){
- push(@column_types, $_);
- $counter++;
- if ($counter == 3) {
- $counter = 0;
- push(@column_types, 'legend');
- # Legend adds a narrow column, which is hardcoded with rowspan => 1
- # This gives each block the same colour as the titles, which should help read the spreadsheet
- }
- }
- }
-
- # Draw the top/key row based on @column_types
thead;
Tr;
- foreach my $column_type (@column_types) {
- td class => 'key';
- txt mt $c{$column_type}{column_string} if $c{$column_type}{column_string};
- if (!$c{$column_type}{unsortable}) {
- for(0..1) {
- # draw the assending/decending arrows
- # draw it in a a container with a link unless it is the already selected one
- my $make_link = !($f->{s} eq $column_type && $f->{o} == $_);
- a href => $url->('o', $_, $column_type) if $make_link;
- lit $_ ? "\x{25BE}" : "\x{25B4}";
- end 'a' if $make_link;
+ for my $c (@col) {
+ td class => 'key';
+ txt mt $c->{column_string} if $c->{column_string};
+ for($c->{sort_field} ? (0,1) : ()) {
+ my $active = $f->{s} eq $c->{sort_field} && !$f->{o} == !$_;
+ a href => $url->(o => $_, s => $c->{sort_field}) if !$active;
+ lit $_ ? "\x{25BE}" : "\x{25B4}";
+ end 'a' if !$active;
}
- }
- end 'td';
+ end 'td';
}
end 'tr';
end 'thead';
- my $td_type = 0;
- my $column_width = 0;
- my @height = ((0) x $#column_types);
-
- for my $r_index (0 .. $#{$r}) {
- my $rel = @$r[$r_index];
- Tr;
- for my $column_index (0 .. $#column_types) {
- next if $height[$column_index] || $column_width; # already drawn multicell box
-
- my $column = $column_types[$column_index];
-
- # assume a height of 1, then add 1 for each following release with identical setting in $column
- $height[$column_index] = 1;
- while ($r_index + $height[$column_index] <= $#{$r} && # end of release array not reached
- _compare_rel(@$r[$r_index + $height[$column_index]], $rel, $column, $c{$column}{na_for_patch})) { # $column are identical in both releases
- $height[$column_index]++;
- }
-
- $column_width = 1;
- if ($c{$column}{na_for_patch} && $rel->{patch}) {
- my $skipped_legend = 0;
- while (($column_index + $column_width + $skipped_legend) <= $#column_types && # end array not reached
- (($c{$column_types[$column_index + $column_width + $skipped_legend]}{na_for_patch}) || # column with no data for patches
- $column_types[$column_index + $column_width + $skipped_legend] eq 'legend' )) { # ignore legends
- if ($column_types[$column_index + $column_width + $skipped_legend] eq 'legend') {
- # column just right of a patch cell is a legend
- # remember this and continue to check
- $skipped_legend = 1;
- } else {
- if ($skipped_legend) {
- # last column was a legend
- # include this one in the patch cell since the columns on both sides will be included in the patch cell
- $height[$column_index + $column_width] = $height[$column_index];
- $column_width++;
- $skipped_legend = 0;
+ for my $r (@r) {
+ Tr;
+ # Combine "N/A for patches" columns
+ my $cspan = 1;
+ for my $c (0..$#col) {
+ if($r->{patch} && $col[$c]{na_for_patch} && $c < $#col && $col[$c+1]{na_for_patch}) {
+ $cspan++;
+ next;
}
- $height[$column_index + $column_width] = $height[$column_index];
- $column_width++;
- }
+ td $cspan > 1 ? (colspan => $cspan) : ();
+ if($r->{patch} && $col[$c]{na_for_patch}) {
+ txt mt '_vnpage_na_for_patches';
+ } else {
+ $col[$c]{draw}->($r);
+ }
+ end;
+ $cspan = 1;
}
- }
-
- td class => $height[$column_index] > 1 ? 'multi' : ($td_type ? 'bg' : 'normal'),
- rowspan => $height[$column_index],
- colspan => $column_width,
- $column_width > 1 ? ( align => 'center' ) : (),
- $c{$column}{column_width} && $f->{cw} ? (style => $c{$column}{column_width}) : ();
- if ($c{$column}{na_for_patch} && $rel->{patch}) {
- txt mt '_vnpage_na_for_patches';
- } else {
- _write_release_string($self, $rel, $column);
- }
- end 'td';
- } continue {
- $height[$column_index]-- if $height[$column_index];
- $column_width-- if $column_width;
- }
- end 'tr';
- } continue {
- # Toggle td_type
- # This will provide the same effect as stripe table class,
- # except rowspan settings will not cause the columns to go out of sync
- $td_type = !$td_type;
+ end;
}
end 'table';
end 'div';
- $self->htmlFooter;
}
-sub _column_is_in_use {
- my($r, $column_type) = @_;
-
- for my $rel (@$r) {
- given ($column_type) {
- # Some types should always be printet. Title is always needed
- # Some types contains info even when unset (like non-free commercial publications)
- when ('title') { return 1 }
- when ('type') { return 1 }
- when ('languages') { return 1 if @{$rel->{languages}} }
- when ('publication'){ return 1 }
- when ('platforms') { return 1 if @{$rel->{platforms}} }
- when ('media') { return 1 if @{$rel->{media}} }
- when ('resolution') { return 1 if $rel->{resolution} }
- when ('voiced') { return 1 if $rel->{voiced} }
- when ('ani_ero') { return 1 if $rel->{ani_story}||$rel->{ani_ero} }
- when ('released') { return 1 }
- when ('minage') { return 1 if $rel->{minage} != -1 }
- when ('notes') { return 1 if $rel->{notes} }
- }
- }
- # No release has data set in the column in question and return value should be false
- # However every row should be drawn (true) in case all releases are filtered out
- return !@$r;
-}
-
-## Compare a specific variable in two releases
-# Returns true if $variable is identical in both releases
-sub _compare_rel {
- my($last_rel, $rel, $variable, $patch_na_var) = @_;
-
- if ($patch_na_var) {
- return 0 if !$rel->{patch} != !$last_rel->{patch};
- return 1 if $rel->{patch} && $last_rel->{patch};
- }
-
- if ($variable eq 'resolution' || $variable eq 'voiced' || $variable eq 'released' || $variable eq 'minage') {
- return $last_rel->{$variable} == $rel->{$variable}
- } elsif ($variable eq 'ani_ero') {
- return $last_rel->{ani_story} eq $rel->{ani_story} &&
- $last_rel->{ani_ero} eq $rel->{ani_ero};
- } elsif ($variable eq 'media' || $variable eq 'platforms' || $variable eq 'languages'){
- if (scalar @{$last_rel->{$variable}} != scalar @{$rel->{$variable}}) {
- # last_rel and rel can't be identical if they even fail to have the same length of arrays
- # No need to check anything else
- return 0;
- }
- if (scalar @{$last_rel->{$variable}} == 0) {
- # Both are empty
- return 1;
- }
-
- # check for each item in last_rel to find an identical item in rel
- for my $item_a (@{$last_rel->{$variable}}) {
- my $test_var = 0;
- for my $item_b (@{$rel->{$variable}}) {
- if ($variable eq 'media') {
- if ($item_a->{medium} eq $item_b->{medium} &&
- $item_a->{qty} == $item_b->{qty}){
- $test_var = 1;
- }
- } elsif ($item_a eq $item_b){
- $test_var = 1;
- }
- }
- if ($test_var == 0) {
- # no match
- # $item_a from $last_rel is not present in $rel
- return 0;
- }
- }
- # everything from last_rel is found in rel
- return 1;
- } elsif ($variable eq 'type') {
- return $last_rel->{type} eq $rel->{type} &&
- !$last_rel->{patch} == !$rel->{patch}
- } elsif ($variable eq 'publication') {
- return !$last_rel->{patch} == !$rel->{patch} &&
- !$last_rel->{freeware} == !$rel->{freeware} &&
- !$last_rel->{doujin} == !$rel->{doujin}
- } elsif ($variable eq 'notes') {
- return $last_rel->{notes} eq $rel->{notes};
- }
- # Any line reaching this has no code to compare.
- # Treat everything as unique and return 0.
- # Note: certain types like title ends up here by design
- return 0;
-}
-
-## Draw the text/icon for a release
-# Draw the string for $variable in release $rel
-# No code to tell where to draw. Caller is responsible for setup of Tr, td and similar
-sub _write_release_string {
- my($self, $rel, $variable) = @_;
-
- given ($variable) {
- when ('title') { a href => "/r$rel->{id}", shorten $rel->{title}, 60 }
- when ('type') { cssicon "rt$rel->{type}", mt "_rtype_$rel->{type}";
- txt mt '_vnpage_rel_patch' if $rel->{patch};
- }
- when ('languages') { for (@{$rel->{languages}}) {
- cssicon "lang $_", mt "_lang_$_";
- br if $_ ne $rel->{languages}[$#{$rel->{languages}}];
- }
- txt mt '_unknown' if !@{$rel->{languages}};
- }
- when ('publication'){ txt mt $rel->{patch} ? '_relinfo_pub_patch' : '_relinfo_pub_nopatch', $rel->{freeware}?0:1, $rel->{doujin}?0:1 }
- when ('platforms') { for(@{$rel->{platforms}}) {
- cssicon $_, mt "_plat_$_";
- br if $_ ne $rel->{platforms}[$#{$rel->{platforms}}];
- }
- txt mt '_unknown' if !@{$rel->{platforms}};
- }
- when ('media') { for (@{$rel->{media}}) {
- txt $self->{media}{$_->{medium}} ? $_->{qty}.' '.mt("_med_$_->{medium}", $_->{qty}) : mt("_med_$_->{medium}",1);
- br if $_ ne $rel->{media}[$#{$rel->{media}}];
- }
- txt mt '_unknown' if !@{$rel->{media}};
- }
- when ('resolution') { if($rel->{resolution}) {
- my $res = $self->{resolutions}[$rel->{resolution}][0];
- txt $res =~ /^_/ ? mt $res : $res;
- } else {
- txt mt '_unknown';
- }
- }
- when ('voiced') { txt mtvoiced $rel->{voiced}; }
- when ('ani_ero') { txt join ', ',
- $rel->{ani_story} ? mt('_relinfo_ani_story', mtani $rel->{ani_story}):(),
- $rel->{ani_ero} ? mt('_relinfo_ani_ero', mtani $rel->{ani_ero} ):();
- txt mt '_unknown' if !$rel->{ani_story} && !$rel->{ani_ero};
- }
- when ('released') { lit $self->{l10n}->datestr($rel->{released}) }
- when ('minage') { txt minage $rel->{minage} }
- when ('notes') { lit bb2html "$rel->{notes}"; }
- }
-}
sub page {
my($self, $vid, $rev) = @_;