--- /dev/null
+#! /usr/bin/perl
+
+# Time Tracker
+#
+# Copyright (c) 2007 Martin Schulze <joey@infodrom.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+
+use strict;
+use warnings;
+
+use DBI;
+use Getopt::Long;
+use Term::ReadLine;
+
+my $table = "stempel";
+my $engine = "dbi:Pg:dbname=infocon";
+
+my $dbh = DBI->connect($engine);
+if (!$dbh) {
+ print "Access to database denied!\n";
+ return 1;
+}
+$dbh->do("SET DateStyle = 'ISO'");
+
+sub min2hour
+{
+ my $minutes = shift;
+
+ return sprintf('%02d:%02d', $minutes/60, $minutes%60);
+}
+
+sub is_open
+{
+ my $query = q{SELECT count(*) AS count FROM stempel WHERE stop IS NULL};
+ my $sth = $dbh->prepare ($query);
+ if ($sth && $sth->execute > 0) {
+ my $row = $sth->fetchrow_hashref;
+ return $row->{count} > 0 ? 1 : 0;
+ }
+ return 0;
+}
+
+sub customerlist
+{
+ my @res;
+
+ my $query = q{SELECT DISTINCT customer FROM stempel ORDER BY customer};
+ my $sth = $dbh->prepare ($query);
+ if ($sth && $sth->execute > 0) {
+ while ((my $row = $sth->fetchrow_hashref)) {
+ push @res, $row->{customer};
+ }
+ }
+ return @res;
+}
+
+sub open_task
+{
+ my $term = new Term::ReadLine '';
+ my @customers = customerlist;
+
+ $term->addhistory($_) foreach (@customers);
+
+ my $attribs = $term->Attribs;
+ $attribs->{completion_entry_function} = $attribs->{list_completion_function};
+ $attribs->{completion_word} = \@customers;
+
+ printf "[%s]\n", join (', ', @customers);
+
+ my $customer = $term->readline ('Kunde: ');
+
+ if (defined $customer && length($customer) > 0) {
+ $customer =~ s/\s*$//;
+ $attribs->{completion_word} = undef;
+ my $task = $term->readline ('Aufgabe: ');
+ if (length($task) > 0) {
+ my $query = q{INSERT INTO stempel (start,customer,task) VALUES('now()',?,?)};
+ my $sth = $dbh->prepare($query);
+ $sth->execute($customer, $task);
+ }
+ }
+}
+
+sub quarter
+{
+ my $min = shift;
+
+ return 15 if $min < 15;
+
+ return $min - $min%15 if ($min%15 < 3);
+
+ return $min + 15-$min%15;
+}
+
+sub hdiff
+{
+ my ($sh, $sm, $eh, $em) = @_;
+
+ if ($em >= $sm) {
+ return ($eh-$sh)*60 + $em-$sm;
+ } else {
+ return ($eh-$sh)*60 - ($sm-$em);
+ }
+}
+
+sub close_task
+{
+ my ($d_sec,$d_min,$d_hour,$d_mday,$d_mon,$d_year,$d_wday,$d_isdst) = localtime();
+
+ my $query = q{SELECT oid,start FROM stempel WHERE stop IS NULL};
+ my $sth = $dbh->prepare ($query);
+ if ($sth && $sth->execute > 0) {
+ while ((my $row = $sth->fetchrow_hashref)) {
+ my @arr = split(/ /, $row->{start});
+ my @d = split(/-/, $arr[0]);
+
+ if ($d[0] != $d_year+1900 || $d[1] != $d_mon+1 || $d[2] != $d_mday) {
+ printf "Task not started today, aborting.\n";
+ next;
+ }
+
+ my @t = split(/:/, $arr[1]);
+ my $int = quarter(hdiff($t[0], $t[1], $d_hour, $d_min));
+
+ $query = sprintf('UPDATE stempel SET stop=now(),time=%d WHERE oid = %d',
+ $int, $row->{oid});
+ $dbh->do ($query);
+ printf "Wrote %s.\n", min2hour($int);
+ }
+ }
+ exit(0);
+}
+
+sub list_open
+{
+ my ($d_sec,$d_min,$d_hour,$d_mday,$d_mon,$d_year,$d_wday,$d_isdst) = localtime();
+ my $query = q{SELECT customer,start,task FROM stempel WHERE time IS NULL ORDER BY start,customer};
+
+ my $sth = $dbh->prepare ($query);
+ if ($sth && $sth->execute > 0) {
+ while ((my $row = $sth->fetchrow_hashref)) {
+ my @arr = split(/ /, $row->{start});
+ my $day = $arr[0];
+ my @d = split(/-/, $day);
+
+ if ($d[0] != $d_year+1900 || $d[1] != $d_mon+1 || $d[2] != $d_mday) {
+ printf "Task not started today, aborting.\n";
+ next;
+ }
+
+ my @t = split(/:/, $arr[1]);
+ my $time = sprintf('%02d:%02d', $t[0], $t[1]);
+ my $int = quarter(hdiff($t[0], $t[1], $d_hour, $d_min));
+
+ printf "%-15s %s %s (%s) %s\n", $row->{customer}, $day, $time, min2hour($int), $row->{task};
+ }
+ }
+ exit 0;
+}
+
+sub list_all
+{
+ # my $query = q{SELECT customer,sum(time) FROM stempel GROUP BY customer ORDER BY customer};
+ my $query = q{SELECT start,customer,time,task FROM stempel WHERE time IS NOT NULL ORDER BY customer,start};
+
+ my $sth = $dbh->prepare ($query);
+
+ if ($sth && $sth->execute > 0) {
+ while ((my $row = $sth->fetchrow_hashref)) {
+ if (defined $row->{time}) {
+ my $day = (split(/ /, $row->{start}))[0];
+ my $time = min2hour $row->{time};
+ printf "%-15s %s %s %s\n", $row->{customer}, $day, $time, $row->{task};
+ }
+ }
+ }
+ exit 0;
+}
+
+sub toggle_task
+{
+ if (is_open) {
+ list_open;
+ } else {
+ open_task;
+ }
+}
+
+
+my %options = ('list' => \&list_all,
+ 'open' => \&list_open,
+ 'terminate|end|d' => \&close_task,
+ );
+GetOptions %options;
+
+toggle_task;