--- loncom/interface/lonfeedback.pm 2012/01/05 21:18:49 1.322 +++ loncom/interface/lonfeedback.pm 2012/01/06 18:17:44 1.324 @@ -1,7 +1,7 @@ # The LearningOnline Network # Feedback # -# $Id: lonfeedback.pm,v 1.322 2012/01/05 21:18:49 www Exp $ +# $Id: lonfeedback.pm,v 1.324 2012/01/06 18:17:44 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -931,21 +931,26 @@ sub build_posting_display { my $skip_group_check = 0; my $symb=&Apache::lonenc::check_decrypt($ressymb); my $escsymb=&escape($ressymb); +# These are the discussion contributions my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'}, $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'}); +# And these are the likes/unlikes my %likes=&Apache::lonnet::dump('disclikes', $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'}, '^'.$symb.':'); my $thisuser=$env{'user.name'}.':'.$env{'user.domain'}; - +# Array with likes to figure out averages, etc. + my @theselikes=(); +# Is the user allowed to see the real name behind anonymous postings? my $see_anonymous = &Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:'')); if ((@{$grouppick} == 0) || (grep(/^all$/,@{$grouppick}))) { $skip_group_check = 1; } +# Deletions and hiddens are just lists. Split them up into a hash for quicker lookup my (%deletions,%hiddens); if ($contrib{'deleted'}) { my $deleted = $contrib{'deleted'}; @@ -959,6 +964,7 @@ sub build_posting_display { $hidden =~ s/\.$//; %hiddens = map { $_ => 1 } (split(/\.\./,$hidden)); } +# Versions if store/restore are used to actually store the messages. if ($contrib{'version'}) { my $oldest = $contrib{'1:timestamp'}; if ($prevread eq '0') { @@ -974,6 +980,8 @@ sub build_posting_display { my $idx=$id; next if ($contrib{$idx.':deleted'}); next if ($contrib{$idx.':hidden'}); +# If we get here, we are actually going to display the message - we don't know where and we don't know if we display +# previous edits, but it counts as one entry my $posttime = $contrib{$idx.':timestamp'}; if ($prevread <= $posttime) { $$newpostsflag = 1; @@ -1107,6 +1115,13 @@ sub build_posting_display { unless ($likes{$symb.':'.$idx.':unlikers'}=~/\,\Q$thisuser\E\,/) { $sender.=' '.&discussion_link($symb,&mt('Unlike'),'unlike',$idx,$$newpostsflag,$prevread,&group_args($group)); } + my $thislikes=$likes{$symb.':'.$idx.':likes'}; + push(@theselikes,$thislikes); + if ($thislikes>0) { + $sender.=' ('.&mt("[_1] likes",$thislikes).')'; + } elsif ($thislikes<0) { + $sender.=' ('.&mt("[_1] unlikes",abs($thislikes)).')'; + } if (&editing_allowed($escsymb.':::'.$idx,$group)) { if (($env{'user.domain'} eq $contrib{$idx.':senderdomain'}) && ($env{'user.name'} eq $contrib{$idx.':sendername'})) { $sender.=' '. @@ -1309,12 +1324,34 @@ sub build_posting_display { $$discussionitems[$idx] .= ''.$version.'. - '.&Apache::lonlocal::locallocaltime($postversions[$i]).' '; } } +# end of unless ($$notshown ...) } +# end of if ($message) ... } +# end of the else-branch of target being export } +# end of unless hidden or deleted } +# end of the loop over all discussion entries } +# Figure out average likes and standard deviation if there are enough discussions to warrant that + if ($#theselikes>1) { + my $sum=0; + my $num=$#theselikes+1; + foreach my $thislike (@theselikes) { + $sum.=$thislike; + } + my $ave=$sum/$num; + my $sumsq=0; + foreach my $thislike (@theselikes) { + $sumsq+=($thislike-$ave)*($thislike-$ave); + } + my $stddev=sqrt($sumsq/$num); +# &Apache::lonnet::logthis(join(',',@theselikes)." Ave $ave StdDev $stddev"); + } +# end of "if there actually are any discussion } +# end of subroutine "build_posting_display" } sub filter_regexp { @@ -3851,6 +3888,11 @@ ENDREDIR my $entry=$env{'form.like'}?$env{'form.like'}:$env{'form.unlike'}; my ($symb,$idx)=split(/\:\:\:/,$entry); ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb); +# +# Likes and unlikes are in db-file "disclikes" of the course +# The prefix is the $symb to identify the resource discussion, +# and the $idx to identify the entry +# my $prefix=$symb.':'.$idx.':'; my %contrib=&Apache::lonnet::dump('disclikes', $env{'course.'.$env{'request.course.id'}.'.domain'}, @@ -3859,8 +3901,10 @@ ENDREDIR # Get all who like or unlike this my $currentlikers=$contrib{$prefix.'likers'}; my $currentunlikers=$contrib{$prefix.'unlikers'}; +# Get the current "likes" count my $likes=$contrib{$prefix.'likes'}; # Find out if they already voted +# Users cannot like a post twice, or unlike it twice. They can change their mind, though my $alreadyflag=0; my $thisuser=$env{'user.name'}.':'.$env{'user.domain'}; if ($env{'form.like'}) { @@ -3868,7 +3912,7 @@ ENDREDIR $alreadyflag=1; } else { if ($currentunlikers=~/\,\Q$thisuser\E\,/) { - $currentunlikers=~s/\,\Q$thisuser\E\,//; + $currentunlikers=~s/\,\Q$thisuser\E\,//g; } else { $currentlikers.=','.$thisuser.','; } @@ -3879,7 +3923,7 @@ ENDREDIR $alreadyflag=1; } else { if ($currentlikers=~/\,\Q$thisuser\E\,/) { - $currentlikers=~s/\,\Q$thisuser\E\,//; + $currentlikers=~s/\,\Q$thisuser\E\,//g; } else { $currentunlikers.=','.$thisuser.','; } @@ -3887,14 +3931,17 @@ ENDREDIR } } my $result; +# $alreadyflag would be 1 if they tried to double-like or double-unlike unless ($alreadyflag) { my %newhash=($prefix.'likes' => $likes, $prefix.'likers' => $currentlikers, $prefix.'unlikers' => $currentunlikers); +# Store data in db-file "disclikes" if (&Apache::lonnet::put('disclikes', \%newhash, $env{'course.'.$env{'request.course.id'}.'.domain'}, $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') { +# Also store with the person who posted the liked/unliked entry if ($env{'form.like'}) { &storediscussionlikes(1,$contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'}); $result=&mt("Registered 'Like'"); @@ -3903,6 +3950,7 @@ ENDREDIR $result=&mt("Registered 'Unlike'"); } } else { +# Oops, something went wrong $result=&mt("Failed to register vote"); } }