| 1 |
# Copyright (C) 2005 Software Freedom Law Center, Inc. |
|---|
| 2 |
# Author: Bradley M. Kuhn <bkuhn@softwarefreedom.org> |
|---|
| 3 |
# |
|---|
| 4 |
# This software gives you freedom; it is licensed to you under version |
|---|
| 5 |
# 3 of the GNU Affero General Public License. |
|---|
| 6 |
# |
|---|
| 7 |
# This software is distributed WITHOUT ANY WARRANTY, without even the |
|---|
| 8 |
# implied warranties of MERCHANTABILITY and FITNESS FOR A PARTICULAR |
|---|
| 9 |
# PURPOSE. See the GNU Affero General Public License for further |
|---|
| 10 |
# details. |
|---|
| 11 |
# |
|---|
| 12 |
# You should have received a copy of the GNU Affero General Public |
|---|
| 13 |
# License, version 3 along with this software. If not, see |
|---|
| 14 |
# <http://www.gnu.org/licenses/>. |
|---|
| 15 |
package SFLC::TimeTracker::Question; |
|---|
| 16 |
|
|---|
| 17 |
use strict; |
|---|
| 18 |
use warnings; |
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
require Exporter; |
|---|
| 22 |
#use AutoLoader qw(AUTOLOAD); |
|---|
| 23 |
|
|---|
| 24 |
our @ISA = qw(Exporter); |
|---|
| 25 |
|
|---|
| 26 |
our @EXPORT_OK = (); |
|---|
| 27 |
|
|---|
| 28 |
our @EXPORT = qw( ); |
|---|
| 29 |
|
|---|
| 30 |
our $VERSION = '0.01'; |
|---|
| 31 |
|
|---|
| 32 |
our $FREE_FORM_STRING = "__FREEFORM__"; |
|---|
| 33 |
our $REJECT_STRING = "__REJECT__"; |
|---|
| 34 |
our $EXISTING_STRING = "__EXISTING__"; |
|---|
| 35 |
|
|---|
| 36 |
my %CHARS = ($FREE_FORM_STRING => 'i', |
|---|
| 37 |
$EXISTING_STRING => 'f', |
|---|
| 38 |
$REJECT_STRING => 'x'); |
|---|
| 39 |
|
|---|
| 40 |
our $DATABASE; |
|---|
| 41 |
|
|---|
| 42 |
use Date::Manip; |
|---|
| 43 |
|
|---|
| 44 |
use Carp; |
|---|
| 45 |
|
|---|
| 46 |
############################################################################### |
|---|
| 47 |
sub Initialize ($) { |
|---|
| 48 |
$DATABASE = shift; |
|---|
| 49 |
} |
|---|
| 50 |
sub new { |
|---|
| 51 |
my($class, %args) = @_; |
|---|
| 52 |
|
|---|
| 53 |
my $self = {}; bless $self, $class; |
|---|
| 54 |
|
|---|
| 55 |
if (defined $args{entryList} and ref $args{entryList} eq "ARRAY") { |
|---|
| 56 |
$self->{entryList} = $args{entryList}; |
|---|
| 57 |
} else { |
|---|
| 58 |
$self->{entryList} = []; |
|---|
| 59 |
} |
|---|
| 60 |
croak "answers must be an array reference" |
|---|
| 61 |
unless defined $args{answers} and ref $args{answers} eq "ARRAY"; |
|---|
| 62 |
my $ii = 0; |
|---|
| 63 |
$self->{numberRegex} = '[\d'; |
|---|
| 64 |
foreach my $ans (@{$args{answers}}) { |
|---|
| 65 |
my $special =0; |
|---|
| 66 |
foreach my $k (keys %CHARS) { |
|---|
| 67 |
if ($ans eq $k) { |
|---|
| 68 |
$self->{answers}{$CHARS{$k}} = $ans; |
|---|
| 69 |
$special = 1; |
|---|
| 70 |
$self->{numberRegex} .= $CHARS{$k}; |
|---|
| 71 |
last; |
|---|
| 72 |
} |
|---|
| 73 |
} |
|---|
| 74 |
$self->{answers}{$ii++} = $ans unless $special; |
|---|
| 75 |
} |
|---|
| 76 |
$self->{numberRegex} .= ']'; |
|---|
| 77 |
|
|---|
| 78 |
foreach my $arg (qw/question userHandle/) { |
|---|
| 79 |
croak "cannot instantiate without $arg" unless defined $args{$arg}; |
|---|
| 80 |
$self->{$arg} = $args{$arg}; |
|---|
| 81 |
} |
|---|
| 82 |
# optional fields |
|---|
| 83 |
foreach my $arg (qw/inputString timeStamp/) { |
|---|
| 84 |
$self->{$arg} = $args{$arg}; |
|---|
| 85 |
} |
|---|
| 86 |
$self->{lastAsked} = undef; |
|---|
| 87 |
return $self; |
|---|
| 88 |
} |
|---|
| 89 |
############################################################################### |
|---|
| 90 |
sub validateAnswer ($$) { |
|---|
| 91 |
my($self, $answer) = @_; |
|---|
| 92 |
|
|---|
| 93 |
my $n = $self->{numberRegex}; |
|---|
| 94 |
return undef if not defined $self->{answers}; |
|---|
| 95 |
if ($answer =~ /^\s*($n+)\s*$/ and (defined $self->{answers}{$1})) { |
|---|
| 96 |
return $answer; |
|---|
| 97 |
} elsif ( ($answer =~ /^\s*($n+)\s+.+\s*$/) and |
|---|
| 98 |
(defined $self->{answers}{$1} |
|---|
| 99 |
and ($self->{answers}{$1} eq $FREE_FORM_STRING or |
|---|
| 100 |
$self->{answers}{$1} eq $EXISTING_STRING))) { |
|---|
| 101 |
print "$1 validated\n"; |
|---|
| 102 |
return $1; |
|---|
| 103 |
} elsif (defined $self->{answers}{$answer}) { |
|---|
| 104 |
return $answer; |
|---|
| 105 |
} else { |
|---|
| 106 |
$answer =~ s/^\s+//; $answer =~ s/\s+$//; |
|---|
| 107 |
|
|---|
| 108 |
foreach my $ans (keys %{$self->{answers}}) { |
|---|
| 109 |
return $ans if ($self->{answers}{$ans} eq $answer); |
|---|
| 110 |
} |
|---|
| 111 |
return undef; |
|---|
| 112 |
} |
|---|
| 113 |
} |
|---|
| 114 |
############################################################################### |
|---|
| 115 |
sub _formatTime ($) { |
|---|
| 116 |
my($self) = @_; |
|---|
| 117 |
|
|---|
| 118 |
my $string = ""; |
|---|
| 119 |
|
|---|
| 120 |
# Only give the time if we have a timestamp and it's been more than five |
|---|
| 121 |
# minutes since the first time we asked. |
|---|
| 122 |
|
|---|
| 123 |
if (defined $self->{timeStamp} and |
|---|
| 124 |
Delta_Format(DateCalc($self->{timeStamp}, 'now'), 1, '%mt') > 5) { |
|---|
| 125 |
my $today = UnixDate("now", '%b %E'); |
|---|
| 126 |
my $time = UnixDate($self->{timeStamp}, '%i:%M%p'); $time =~ s/^\s+//; |
|---|
| 127 |
my $day = UnixDate($self->{timeStamp}, '%b %E'); |
|---|
| 128 |
$time = "$time (on $day)" if ($day ne $today); |
|---|
| 129 |
$string .= "At $time, "; |
|---|
| 130 |
} |
|---|
| 131 |
return $string; |
|---|
| 132 |
} |
|---|
| 133 |
############################################################################### |
|---|
| 134 |
sub formatQuestion ($) { |
|---|
| 135 |
my($self) = @_; |
|---|
| 136 |
|
|---|
| 137 |
my $string = $self->_formatTime(); |
|---|
| 138 |
|
|---|
| 139 |
my $isQues = $self->{question} =~ /\?\s*$/; |
|---|
| 140 |
if (defined $self->{inputString}) { |
|---|
| 141 |
$string .= (($string eq "") ? "Y" : "y" ) . |
|---|
| 142 |
"ou said, \"$self->{inputString}\""; |
|---|
| 143 |
} else { |
|---|
| 144 |
$string .= "you attempted to make a time entry"; |
|---|
| 145 |
|
|---|
| 146 |
} |
|---|
| 147 |
$string .= $isQues ? ", which led me to ask: " : ". However, "; |
|---|
| 148 |
|
|---|
| 149 |
$string .= "$self->{question} " . |
|---|
| 150 |
"Choose an option: "; |
|---|
| 151 |
foreach my $ans (sort { return ($a cmp $b) if $a =~ /^[a-z]+$/ and $b =~ /^[a-z]+$/; |
|---|
| 152 |
return ($a <=> $b)if $a =~ /^\d+$/ and $b =~ /^\d+$/; |
|---|
| 153 |
return 1 if $a =~ /^[a-z]+$/ and $b =~ /^\d+$/; |
|---|
| 154 |
return -1 if $b =~ /^[a-z]+$/ and $a =~ /^\d+$/; |
|---|
| 155 |
return 0 } keys %{$self->{answers}}) { |
|---|
| 156 |
if ($self->{answers}{$ans} eq $FREE_FORM_STRING) { |
|---|
| 157 |
$string .= "(${ans}) " . $self->freeFormReplacement($ans) . ", "; |
|---|
| 158 |
} elsif ($self->{answers}{$ans} eq $REJECT_STRING) { |
|---|
| 159 |
$string .= "(${ans}) " . $self->rejectReplacement($ans) . ", "; |
|---|
| 160 |
} elsif ($self->{answers}{$ans} eq $EXISTING_STRING) { |
|---|
| 161 |
$string .= "(${ans}) " . $self->existingReplacement($ans) . ", "; |
|---|
| 162 |
} else { |
|---|
| 163 |
$string .= "(${ans}) $self->{answers}{$ans}, "; |
|---|
| 164 |
} |
|---|
| 165 |
} |
|---|
| 166 |
$string =~ s/,\s*$//; |
|---|
| 167 |
|
|---|
| 168 |
return $string; |
|---|
| 169 |
} |
|---|
| 170 |
############################################################################### |
|---|
| 171 |
sub freeFormReplacement { |
|---|
| 172 |
my($self, $ans) = @_; |
|---|
| 173 |
|
|---|
| 174 |
return "Enter your own freeform text by typing \"$ans <STRING>\""; |
|---|
| 175 |
} |
|---|
| 176 |
############################################################################### |
|---|
| 177 |
sub resolve ($$) { |
|---|
| 178 |
my($self, $answer) = @_; |
|---|
| 179 |
|
|---|
| 180 |
$self->validateAnswer($answer); |
|---|
| 181 |
croak "INVALID CALL OF BASCLASS METHOD"; |
|---|
| 182 |
|
|---|
| 183 |
} |
|---|
| 184 |
############################################################################### |
|---|
| 185 |
sub formatResolveString ($$) { |
|---|
| 186 |
my($self, $answer) = @_; |
|---|
| 187 |
|
|---|
| 188 |
if (not defined $answer) { |
|---|
| 189 |
$answer = $self->{lastAnswer}; |
|---|
| 190 |
} |
|---|
| 191 |
if (not defined $answer) { |
|---|
| 192 |
$answer = ""; |
|---|
| 193 |
carp "Got an undefined answer for question $self->{id}"; |
|---|
| 194 |
} |
|---|
| 195 |
return "I am sorry, but I am totally confused." if not defined $answer; |
|---|
| 196 |
return "Your response was invalid." if $answer =~ /^INVALID/; |
|---|
| 197 |
return "Thank you." if $answer eq "RESOLVED"; |
|---|
| 198 |
return undef; |
|---|
| 199 |
} |
|---|
| 200 |
|
|---|
| 201 |
|
|---|
| 202 |
sub getDatabase { |
|---|
| 203 |
return $DATABASE; |
|---|
| 204 |
} |
|---|
| 205 |
1; |
|---|
| 206 |
__END__ |
|---|
| 207 |
|
|---|
| 208 |
# |
|---|
| 209 |
# Local variables: |
|---|
| 210 |
# compile-command: "perl -I ../../../Modules -c Question.pm" |
|---|
| 211 |
# End: |
|---|
| 212 |
|
|---|