From 4c82eb9b616e9b1d4950df713baf083b427cbb63 Mon Sep 17 00:00:00 2001 From: Kaleb Murphy Date: Fri, 24 Oct 2008 21:38:03 +0000 Subject: [PATCH] Add new report table (and sql file), and the survey now does reporting. --- Survey.sql | 106 ++++++++++++++++++ lib/WebGUI/Asset/Wobject/Survey.pm | 85 ++++++++++++-- .../Asset/Wobject/Survey/ResponseJSON.pm | 56 ++++++--- lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm | 8 +- lib/WebGUI/i18n/English/Asset_Survey.pm | 8 +- survey_templates.wgpkg | Bin 9014 -> 9019 bytes 6 files changed, 235 insertions(+), 28 deletions(-) create mode 100644 Survey.sql diff --git a/Survey.sql b/Survey.sql new file mode 100644 index 000000000..b1c3b5fda --- /dev/null +++ b/Survey.sql @@ -0,0 +1,106 @@ +-- MySQL dump 10.11 +-- +-- Host: localhost Database: www_survey_com +-- ------------------------------------------------------ +-- Server version 5.0.67 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `Survey` +-- + +DROP TABLE IF EXISTS `Survey`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +CREATE TABLE `Survey` ( + `groupToTakeSurvey` varchar(22) character set utf8 collate utf8_bin NOT NULL default '2', + `groupToViewReports` varchar(22) character set utf8 collate utf8_bin NOT NULL default '3', + `responseTemplateId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '', + `overviewTemplateId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '', + `maxResponsesPerUser` int(11) NOT NULL default '1', + `gradebookTemplateId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '', + `assetId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '', + `templateId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '', + `revisionDate` bigint(20) NOT NULL default '0', + `surveyEditTemplateId` varchar(22) NOT NULL, + `answerEditTemplateId` varchar(22) NOT NULL, + `questionEditTemplateId` varchar(22) NOT NULL, + `sectionEditTemplateId` varchar(22) NOT NULL, + `surveyTakeTemplateId` varchar(22) NOT NULL, + `surveyQuestionsId` varchar(22) NOT NULL, + `exitURL` varchar(512) default NULL, + `surveyJSON` longblob, + PRIMARY KEY (`assetId`,`revisionDate`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `Survey_response` +-- + +DROP TABLE IF EXISTS `Survey_response`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +CREATE TABLE `Survey_response` ( + `assetId` varchar(22) character set utf8 collate utf8_bin NOT NULL, + `Survey_responseId` varchar(22) character set utf8 collate utf8_bin NOT NULL default '', + `userId` varchar(22) default NULL, + `username` varchar(255) default NULL, + `ipAddress` varchar(15) default NULL, + `startDate` bigint(20) NOT NULL default '0', + `endDate` bigint(20) NOT NULL default '0', + `isComplete` int(11) NOT NULL default '0', + `anonId` varchar(255) default NULL, + `responseJSON` longblob, + PRIMARY KEY (`Survey_responseId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `Survey_tempReport` +-- + +DROP TABLE IF EXISTS `Survey_tempReport`; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8; +CREATE TABLE `Survey_tempReport` ( + `assetId` varchar(22) NOT NULL, + `Survey_responseId` varchar(22) NOT NULL, + `order` smallint(5) unsigned NOT NULL, + `sectionNumber` smallint(5) unsigned NOT NULL, + `sectionName` varchar(512) default NULL, + `questionNumber` smallint(5) unsigned NOT NULL, + `questionName` varchar(512) default NULL, + `questionComment` mediumtext, + `answerNumber` smallint(5) unsigned default NULL, + `answerValue` mediumtext, + `answerComment` mediumtext, + `entryDate` bigint(20) unsigned NOT NULL COMMENT 'UTC Unix Time', + `isCorrect` tinyint(3) unsigned default NULL, + `value` int(11) default NULL, + `fileStoreageId` varchar(22) default NULL COMMENT 'Not implemented yet', + PRIMARY KEY (`assetId`,`Survey_responseId`,`order`), + KEY `assetId` (`assetId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +SET character_set_client = @saved_cs_client; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2008-10-24 21:38:00 diff --git a/lib/WebGUI/Asset/Wobject/Survey.pm b/lib/WebGUI/Asset/Wobject/Survey.pm index 555e764e0..fa7b558f3 100644 --- a/lib/WebGUI/Asset/Wobject/Survey.pm +++ b/lib/WebGUI/Asset/Wobject/Survey.pm @@ -38,6 +38,11 @@ sub definition { hoverHelp=>"A Survey System", label=>"Template ID" }, + groupToEditSurvey => { + fieldType => 'group', + defaultValue => 4, + label => "Group to edit survey", + }, groupToTakeSurvey => { fieldType => 'group', defaultValue => 2, @@ -552,6 +557,7 @@ sub prepareView { sub purge { my $self = shift; $self->session->db->write("delete from Survey_response where assetId = ?",[$self->getId()]); + $self->session->db->write("delete from Survey_tempReport where assetId = ?",[$self->getId()]); $self->session->db->write("delete from Survey where assetId = ?",[$self->getId()]); return $self->SUPER::purge; } @@ -589,12 +595,13 @@ returns the output. sub view { my $self = shift; my %var; + $var{'edit_survey_url'} = $self->getUrl('func=editSurvey'); $var{'take_survey_url'} = $self->getUrl('func=takeSurvey'); + $var{'view_reports_url'} = $self->getUrl('func=viewReports'); $var{'user_canTakeSurvey'} = $self->session->user->isInGroup($self->get("groupToTakeSurvey")); - - $var{'user_canTakeSurvey'} = 1; - + $var{'user_canViewReports'} = $self->session->user->isInGroup($self->get("groupToViewReports")); + $var{'user_canEditSurvey'} = $self->session->user->isInGroup($self->get("groupToEditSurvey")); my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate}); return $out; @@ -842,14 +849,18 @@ sub loadBothJSON{ #------------------------------------------------------------------- sub loadResponseJSON{ my $self = shift; +$self->log("1"); my $jsonHash = shift; my $rId = shift; + $rId = defined $rId ? $rId : $self->{responseId}; + if(defined $self->response and ! defined $rId){return;} - if(defined $self->response){return;} +$self->log("loading $rId"); - $jsonHash = $self->session->db->quickScalar("select surveyJSON from Survey where assetId = ?",[$self->getId]) if(! defined $jsonHash); - - $self->{response} = WebGUI::Asset::Wobject::Survey::ResponseJSON->new($jsonHash,$self->session->errorHandler, $rId, $self->survey); + $jsonHash = $self->session->db->quickScalar("select responseJSON from Survey_response where assetId = ? and Survey_responseId = ?", + [$self->getId,$rId]) if(! defined $jsonHash); +$self->log("jsonhash was ".(length $jsonHash)); + $self->{response} = WebGUI::Asset::Wobject::Survey::ResponseJSON->new($jsonHash,$self->session->errorHandler, $self->survey); } #------------------------------------------------------------------- @@ -984,7 +995,67 @@ $self->session->errorHandler->error("Can take was NOT already defined"); } +#------------------------------------------------------------------- +sub www_viewReports { + my $self = shift; + $self->loadTempReportTable(); + return "" unless ($self->session->user->isInGroup($self->get("groupToViewReports"))); + my $filename = $self->session->url->escape($self->get("title")."_results.tab"); + my $content = $self->session->db->quickTab("select * from Survey_tempReport t where t.assetId=? order by t.Survey_responseId, t.order",[$self->getId()]); + return $self->export($filename,$content); +} + +#------------------------------------------------------------------- +sub export{ + my $self = shift; + my $filename = shift; + $filename =~ s/[^\w\d\.]/_/g; + my $content = shift; + #Create a temporary directory to store files if it doesn't already exist + my $store = WebGUI::Storage->createTemp( $self->session ); + my $tmpDir = $store->getPath(); + my $filepath = $store->getPath($filename); + unless (open TEMP, ">$filepath") { + return "Error - Could not open temporary file for writing. Please use the back button and try again"; + } + print TEMP $content; + close TEMP; + my $fileurl = $store->getUrl($filename); + + $self->session->http->setRedirect($fileurl); + + return undef; +} +sub loadTempReportTable{ + my $self = shift; + + $self->loadSurveyJSON(); + my $refs = $self->session->db->buildArrayRefOfHashRefs("select * from Survey_response where assetId = ?",[$self->getId()]); + $self->session->db->write("delete from Survey_tempReport where assetId = ?",[$self->getId()]); + for my $ref(@$refs){ + $self->loadResponseJSON(undef,$ref->{Survey_responseId}); + my $count = 1; + for my $q(@{$self->response->returnResponseForReporting()}){ + if(@{$q->{answers}} == 0 and $q->{comment} =~ /\w/){ + $self->session->db->write("insert into Survey_tempReport VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + [$self->getId(),$ref->{Survey_responseId}, $count++, $q->{section},$q->{sectionName},$q->{question},$q->{questionName}, + $q->{questionComment},undef,undef,undef,undef,undef,undef,undef]); + next; + } + for my $a(@{$q->{answers}}){ + $self->session->db->write("insert into Survey_tempReport VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + [$self->getId(),$ref->{Survey_responseId}, $count++, $q->{section},$q->{sectionName},$q->{question},$q->{questionName}, + $q->{questionComment},$a->{id},$a->{value},$a->{comment},$a->{time},$a->{isCorrect},$a->{value},undef]); + } + } + } + return 1; +} +sub log{ + my $self = shift; + $self->session->errorHandler->error(shift); +} 1; diff --git a/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm b/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm index 606875c60..d385e5ae7 100644 --- a/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm +++ b/lib/WebGUI/Asset/Wobject/Survey/ResponseJSON.pm @@ -8,12 +8,10 @@ sub new{ my $class = shift; my $json = shift; my $log = shift; - my $rId = shift; my $survey = shift; my $self = {}; $self->{survey} = $survey; $self->{log} = $log; - $self->{responseId} = $rId; my $temp = decode_json($json) if defined $json; $self->{surveyOrder} = defined $temp->{surveyOrder} ? $temp->{surveyOrder} : [];#an array of question addresses, with the third member being an array of answers $self->{responses} = defined $temp->{responses} ? $temp->{responses} : {}; @@ -34,10 +32,9 @@ Forks are passed in to show where to branch the new order. sub createSurveyOrder{ my $self = shift; -# my $fork = shift || []; my $order; my $qstarting = 0; -eval{ + for(my $s = 0; $s <= $#{$self->survey->sections()}; $s++){ #create question order for section my @qorder; @@ -61,17 +58,8 @@ eval{ @aorder = (($qstarting .. $#{$self->survey->question([$s,$_])->{answers}})); } push(@$order,[$s,$_,\@aorder]); -# if(@$fork == 2){ -# if($$fork[0][0] == $s and $$fork[0][1] == $_){ -# $s = $$fork[1][0]-1; -# $qstarting = $$fork[1][1]; -# last; -# } -# } } } -}; -$self->log($@) if($@); $self->{surveyOrder} = $order; } sub shuffle { @@ -90,6 +78,7 @@ sub freeze{ delete $temp{survey}; return encode_json(\%temp); } + #the index of the last surveyOrder entry shown sub lastResponse{ my $self = shift; @@ -162,6 +151,7 @@ $self->log("There are questions to be submitted in this section"); $terminal = 1; $terminalUrl = $question->{terminalUrl}; } + $self->responses->{$question->{id}}->{comment} = $responses->{$question->{id}."comment"}; for my $answer(@{$question->{answers}}){ if(defined($responses->{$answer->{id}}) and $responses->{$answer->{id}} =~ /\S/){ @@ -169,11 +159,13 @@ $self->log("There are questions to be submitted in this section"); $aAnswered = 1; if($mcTypes{$question->{questionType}}){ $self->responses->{$answer->{id}}->{value} = $answer->{recordedAnswer}; +$self->log("Recorded Answer ".$answer->{recordedAnswer}); } else{ +$self->log("Returned Answer ".$responses->{$answer->{id}}); $self->responses->{$answer->{id}}->{value} = $responses->{$answer->{id}}; } - + $self->responses->{$answer->{id}}->{'time'} = time(); $self->responses->{$answer->{id}}->{comment} = $responses->{$answer->{id}."comment"}; if($answer->{terminal}){ @@ -250,7 +242,6 @@ $self->log("next sectionid is $nextSectionId"); my $section = $self->nextSection(); $self->log("Section text is ".$section->{text}); $section->{'text'} =~ s/\[\[([^\%]*?)\]\]/$self->getPreviousAnswer($1)/eg; -# $section->{'text'} =~ s/(\[\[\%.*?\]\])/$self->getRandomText($responseId,$1)/eg; $self->log("qperpage $qPerPage"); @@ -290,6 +281,41 @@ $self->log("ENDING THE SURVEY\n\n\n") if($self->lastResponse > $#{$self->surveyO return 0; } +sub returnResponseForReporting{ + my $self = shift; + my @responses = (); + for my $entry(@{$self->surveyOrder}){ + if(@$entry == 1){ + next; + } + my @answers; + for (@{$$entry[2]}){ + if(defined $self->responses->{"$$entry[0]-$$entry[1]-$_"}){ + $self->responses->{"$$entry[0]-$$entry[1]-$_"}->{id} = $_; + if($self->survey->answer([$$entry[0],$$entry[1],$_])->{isCorrect}){ + my $value; + if($self->survey->answer([$$entry[0],$$entry[1],$_])->{value} =~ /\w/){ + $value = $self->survey->answer([$$entry[0],$$entry[1],$_])->{value}; + }else{ + $value = $self->survey->question([$$entry[0],$$entry[1]])->{value}; + } + $self->responses->{"$$entry[0]-$$entry[1]-$_"}->{value} = $value; + $self->responses->{"$$entry[0]-$$entry[1]-$_"}->{isCorrect} = 1; + }else{ + $self->responses->{"$$entry[0]-$$entry[1]-$_"}->{isCorrect} = 0; + } + push(@answers,($self->responses->{"$$entry[0]-$$entry[1]-$_"})); + } + } + push(@responses,({'section',$$entry[0],'question',$$entry[1], + 'sectionName',$self->survey->section([$$entry[0]])->{variable}, + 'questionName',$self->survey->question([$$entry[0],$$entry[1]])->{variable}, + 'questionComment',$self->responses->{"$$entry[0]-$$entry[1]"}->{comment}, + 'answers',\@answers})); + } +$self->log(Dumper @responses); + return \@responses; +} #the actual responses to the survey. A response is for a question and is accessed by the exact same address as a survey member. #Questions only contain the comment and an array of answer Responses. diff --git a/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm b/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm index 6c4483f59..506ceb45a 100644 --- a/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm +++ b/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm @@ -150,12 +150,14 @@ sub update{ my $object; my $newQuestion = 0; if(@$address == 1){ +$self->log("A section"); $object = $self->section($address); if(! defined $object){ $object = $self->newSection(); push(@{$self->sections},$object); } }elsif(@$address == 2){ +$self->log("A question"); $object = $self->question($address); if(! defined $object){ my $newQuestion = 1; @@ -163,6 +165,7 @@ sub update{ push(@{$self->questions($address)},$object); } }elsif(@$address == 3){ +$self->log("A answer"); $object = $self->answer($address); if(! defined $object){ $object = $self->newAnswer(); @@ -175,6 +178,7 @@ sub update{ } } for my $key(keys %$object){ +$self->log("$key $$object{$key}"); $object->{$key} = $ref->{$key} if(defined $$ref{$key}); } } @@ -263,8 +267,8 @@ sub newQuestion{ 'maxAnswers',1, 'value',1, 'textInButton',0, - 'terminal',0, - 'terminalUrl','', +# 'terminal',0, +# 'terminalUrl','', 'type','question' ); $members{answers} = []; diff --git a/lib/WebGUI/i18n/English/Asset_Survey.pm b/lib/WebGUI/i18n/English/Asset_Survey.pm index 312d8e306..7b7e795a0 100644 --- a/lib/WebGUI/i18n/English/Asset_Survey.pm +++ b/lib/WebGUI/i18n/English/Asset_Survey.pm @@ -15,8 +15,8 @@ our $I18N = { message => q|Take Survey|, lastUpdated => 1224686319 }, - 'view results' => { - message => q|View Reports|, + 'view reports' => { + message => q|View Results|, lastUpdated => 1224686319 }, 'continue button' => { @@ -127,7 +127,7 @@ our $I18N = { message => q|Question type:|, lastUpdated => 1224686319 }, - 'randomzied words' => { + 'randomized words' => { message => q|Randomized words:|, lastUpdated => 1224686319 }, @@ -155,7 +155,7 @@ our $I18N = { message => q|Maximum number of answers:|, lastUpdated => 1224686319 }, - 'qrequired' => { + 'required' => { message => q|Required|, lastUpdated => 1224686319 }, diff --git a/survey_templates.wgpkg b/survey_templates.wgpkg index dd0ee20159309e165eef2838d6d0c24660ea668a..ed0c8eb999a0587364dcde65b4439b84206a78a9 100644 GIT binary patch literal 9019 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 literal 9014 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