report: Sort more sensibly.
[dvddb] / report
CommitLineData
14acb11f
MW
1#! /usr/bin/perl -w
2
3use open ":utf8";
4use strict;
5
6use DBI;
7use Encode qw{encode_utf8 decode_utf8};
8use File::Find;
9
10BEGIN { binmode STDOUT, ":utf8"; }
11
12my $ROOT = "/mnt/dvd/archive";
13my $DB = DBI->connect("dbi:Pg:host=roadstar", "", "",
14 { AutoCommit => 0,
15 RaiseError => 1,
16 ReadOnly => 1 });
17
18my %iso = ();
19find(sub {
20 if (/\.iso$/ && ! -l && -f) {
21 my $fn = decode_utf8 $File::Find::name;
22 $fn =~ s:^$ROOT/::;
23 $iso{$fn} = 1;
24 }
25 }, $ROOT);
26
27my %set_path;
28my %set_id;
b2e7e49c 29my %box;
b2a25885
MW
30my $st_set = $DB->prepare("SELECT id, name, n_disc FROM dvd_set");
31my $st_disc = $DB->prepare
b2e7e49c 32 ("SELECT disc, path, box FROM dvd_disc WHERE set_id = ? ORDER BY disc");
14acb11f
MW
33$st_set->execute;
34
b2a25885 35while (my @r = $st_set->fetchrow_array) {
14acb11f
MW
36 my ($id, $name, $ndisc) = @r;
37 my @path;
38
39 $st_disc->execute($id);
b2a25885 40 while (my @r = $st_disc->fetchrow_array) {
b2e7e49c 41 my ($disc, $path, $box) = @r;
14acb11f 42 $disc == @path or die "bad disc sequence for `$name'";
b2e7e49c 43 $box{$path} = $box if defined $box;
14acb11f
MW
44 push @path, $path;
45 }
46 @path == $ndisc or die "wrong number of discs for `$name'";
47 $set_path{$name} = \@path; $set_id{$name} = $id;
48}
49
50for my $name (keys %set_path) {
51 my $allp = 1;
52 for my $path (@{$set_path{$name}}) {
53 if (defined $path && exists $iso{$path}) { delete $iso{$path}; }
54 else { $allp = 0; }
55 }
56 ##if ($allp) { delete $set_path{$name}; }
57}
58
59my @iso = sort keys %iso;
b2e7e49c
MW
60my $lastbox = "#nil";
61sub set_box ($) {
62 my ($box) = @_;
63 $box //= "#nil";
64 if ($box ne $lastbox) { print "!box $box\n"; $lastbox = $box; }
65}
66
562fc845
MW
67sub path_key ($) {
68 my ($p) = @_;
69 if ($p =~ m{^ ([a-z]) / ([^/]+) ((?: / .*)?) $}ix) {
70 my $init = $1;
71 my $focus = $2;
72 my $tail = $3;
73 my $head = undef;
74 if ($focus =~ /^ (the | a ) \s+ (\S .*) $/x)
75 { $head = $1; $focus = $2; }
76 if (lc $init ne lc substr($focus, 0, 1) &&
77 $focus =~ /^ (.*) \s+ ($init .*) $/x)
78 { $head .= (defined $head && " ") . $1; $focus = $2; }
79 if (defined $head) { return "$init/$focus, $head$tail"; }
80 }
81 return $p;
82}
83
396896e5
MW
84for my $name (sort { my $pa = $set_path{$a}[0]; my $ba = $box{$pa} // "~~~";
85 my $pb = $set_path{$b}[0]; my $bb = $box{$pb} // "~~~";
562fc845 86 $ba cmp $bb || path_key $pa cmp path_key $pb }
14acb11f
MW
87 keys %set_path) {
88 my $paths = $set_path{$name};
89 my @unk;
b2e7e49c 90 set_box $box{$paths->[0]};
14acb11f
MW
91 while (@iso && $iso[0] lt $paths->[0]) { push @unk, shift @iso; }
92 if (@unk) {
93 print "[#UNK: *]\n";
94 for my $path (@unk) { print "\t", $path, "\n"; }
95 }
96 printf "[#%d: %d] %s\n", $set_id{$name}, scalar @$paths, $name;
97 my $i = 0;
98 for my $path (@$paths) {
99 $i++;
100 if (!defined $path) {
101 printf "\t!! (disc %d)\n", $i;
102 } else {
103 my $fn = "$ROOT/$path";
b2e7e49c 104 set_box $box{$path};
14acb11f
MW
105 if (-f $fn && ! -l $fn) { print "\t" . $path . "\n"; }
106 else { print "\t!! ". $path . "\n"; }
107 }
108 }
109}
110
111if (@iso) {
112 print "[#UNK: *]\n";
113 for my $path (@iso) { print "\t", $path, "\n"; }
114}
115
116$DB->disconnect;