Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
118
Task/Simple-database/Perl/simple-database.pl
Normal file
118
Task/Simple-database/Perl/simple-database.pl
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#!/usr/bin/perl
|
||||
use warnings;
|
||||
use strict;
|
||||
use feature qw{ say };
|
||||
|
||||
use JSON::PP;
|
||||
use Time::Piece;
|
||||
|
||||
use constant {
|
||||
NAME => 0,
|
||||
CATEGORY => 1,
|
||||
DATE => 2,
|
||||
DB => 'simple-db',
|
||||
};
|
||||
|
||||
my $operation = shift // "";
|
||||
|
||||
my %dispatch = (
|
||||
n => \&add_new,
|
||||
l => \&print_latest,
|
||||
L => \&print_latest_for_categories,
|
||||
a => \&print_all,
|
||||
);
|
||||
|
||||
if ($dispatch{$operation}) {
|
||||
$dispatch{$operation}->(@ARGV);
|
||||
} else {
|
||||
die "Invalid option. Use one of n, l, L, a.\n"
|
||||
}
|
||||
|
||||
sub add_new {
|
||||
my ($name, $category, $date) = @_;
|
||||
my $db = eval { load() } || {};
|
||||
if (defined $date) {
|
||||
eval { 'Time::Piece'->strptime($date, '%Y-%m-%d'); 1 }
|
||||
or die "Invalid date format: YYYY-MM-DD.\n";
|
||||
|
||||
} else {
|
||||
$date //= localtime->ymd;
|
||||
}
|
||||
|
||||
my @ids = keys %{ $db->{by_id} };
|
||||
my $max_id = max(num => @ids) || 0;
|
||||
$db->{by_id}{ ++$max_id } = [ $name, $category, $date ];
|
||||
save($db);
|
||||
}
|
||||
|
||||
sub print_latest {
|
||||
build_indexes( my $db = load(), 0, 1 );
|
||||
_print_latest($db);
|
||||
}
|
||||
|
||||
sub _print_latest {
|
||||
my ($db, $category) = @_;
|
||||
my @dates = keys %{ $db->{by_date} };
|
||||
@dates = grep {
|
||||
grep $db->{by_id}{$_}[CATEGORY] eq $category,
|
||||
@{ $db->{by_date}{$_} };
|
||||
} @dates if defined $category;
|
||||
|
||||
my $last_date = max(str => @dates);
|
||||
say for map $db->{by_id}{$_}[NAME],
|
||||
grep ! defined $category
|
||||
|| $db->{by_id}{$_}[CATEGORY] eq $category,
|
||||
@{ $db->{by_date}{$last_date} };
|
||||
}
|
||||
|
||||
sub max {
|
||||
my $type = shift;
|
||||
my $max = $_[0];
|
||||
{ num => sub { $_ > $max },
|
||||
str => sub { $_ gt $max},
|
||||
}->{$type}->() and $max = $_
|
||||
for @_[ 1 .. $#_ ];
|
||||
return $max
|
||||
}
|
||||
|
||||
sub print_latest_for_categories {
|
||||
build_indexes( my $db = load(), 1, 1 );
|
||||
|
||||
for my $category (sort keys %{ $db->{by_category} }){
|
||||
say "* $category";
|
||||
_print_latest($db, $category);
|
||||
}
|
||||
}
|
||||
|
||||
sub print_all {
|
||||
build_indexes( my $db = load(), 0, 1 );
|
||||
|
||||
for my $date (sort keys %{ $db->{by_date} }) {
|
||||
for my $id (@{ $db->{by_date}{$date} }) {
|
||||
say $db->{by_id}{$id}[NAME];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub load {
|
||||
open my $in, '<', DB or die "Can't open database: $!\n";
|
||||
local $/;
|
||||
return { by_id => decode_json(<$in>) };
|
||||
}
|
||||
|
||||
sub save {
|
||||
my ($db) = @_;
|
||||
open my $out, '>', DB or die "Can't save database: $!\n";
|
||||
print {$out} encode_json($db->{by_id});
|
||||
close $out;
|
||||
}
|
||||
|
||||
sub build_indexes {
|
||||
my ($db, $by_category, $by_date) = @_;
|
||||
for my $id (keys %{ $db->{by_id} }) {
|
||||
push @{ $db->{by_category}{ $db->{by_id}{$id}[CATEGORY] } }, $id
|
||||
if $by_category;
|
||||
push @{ $db->{by_date}{ $db->{by_id}{$id}[DATE] } }, $id
|
||||
if $by_date;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue