sub matchUser { # Find all db entries related to user # while looking through all db items # parsedbstring # if user answer # get linked question # parse the question # push question into final data structure: @matchQuestionsAndAnswers # if user note # add to array of notes @notes # add notesto final data structure while (($key, $val) = each %hash){ parseDatabaseString($val); $hold = $val; # if the data is an answer if (($parsedinfo[1] eq '3') && ($call{'user'} eq $parsedinfo[2])){ # put existing answer info into a buffer $tempid = $parsedinfo[0]; $tempdatatype = $parsedinfo[1]; $tempuser = $parsedinfo[2]; $templinkid = $parsedinfo[3]; $tempkeywords = $keywords; $tempquestion = $parsedinfo[4]; # get linked question # Hash access doesn't allow subscript. # use a clean var with no subscript $clean = $parsedinfo[3]; $val = $hash{$clean}; # parse the question parseDatabaseString($val); # sets @parsedinfo to question data # push question into final data structure: push (@matchQuestionsAndAnswers, { ID => $parsedinfo[0], datatype => $parsedinfo[1], user => $parsedinfo[2], linkid => $parsedinfo[3], keywords => $keywords, question => $parsedinfo[4] }); # push buffered answer into final data structure: push (@matchQuestionsAndAnswers, { ID => $tempid, datatype => $tempdatatype, user => $tempuser, linkid => $templinkid, keywords => $tempkeywords, question => $tempquestion }); } elsif (($parsedinfo[1] eq '2') && ($call{'user'} eq $parsedinfo[2])){ # add to array of notes @notes push (@notes, { ID => $parsedinfo[0], datatype => $parsedinfo[1], user => $parsedinfo[2], linkid => $parsedinfo[3], keywords => $keywords, question => $parsedinfo[4] }); } } # add notes to final data structure while ($i <= $#notes){ push (@matchQuestionsAndAnswers, { ID => $notes[$i]{'ID'}, datatype => $notes[$i]{'datatype'}, user => $notes[$i]{'user'}, linkid => $notes[$i]{'linkid'}, keywords => $notes[$i]{'keywords'}, question => $notes[$i]{'question'} }); $i++; } $i = 0; } sub fixQuestionOrder{ &defineKeywords; while (($key, $val) = each %hash){ $count = 0; #print "We are at: key: $key, val: $val
\n"; parseDatabaseString($val); #print "We are at: parsedinfo[1]: $parsedinfo[1]
\n"; $i = 0; # while looping through the array of keywords from the form while ($i <= $#formkeys){ #print "We are at: i $i <= #formkeys $#formkeys
\n"; $j = 0; # compare with each keyword in the database location while ($j <= $#parsedstring){ #print "We are at: j $j <= #parsedstring $#parsedstring
\n"; if ($formkeys[$i] eq $parsedstring[$j]){ #print "We are at: formkeys[$i]: $formkeys[$i] eq parsedstring[$j]: $parsedstring[$j]
\n"; # this keyword matches. increment count $count += 1; $j = $#parsedstring; } $j++; } $i++; } # if there are the same number of matches # as the size of the array parsedstring, # we have a match #print "Test: count: $count == #parsedstring: $#parsedstring
\n"; if ($count == ($#parsedstring + 1)){ # if daata type 1 or (if user matches & datatype is either 2 or 3) # print "Debug: parsedinfo[1] eq $parsedinfo[1]
\n"; if ($parsedinfo[1] eq '1'){ # print "$call{'user'} eq $parsedinfo[2] && $parsedinfo[1] is either 2 or 3, or $parsedinfo[1] = 1
\n"; $buffer = $parsedinfo[3]; $fixQuestionOrder[$buff]{'ID'} = $parsedinfo[0]; $fixQuestionOrder[$buff]{'datatype'} = $parsedinfo[1]; $fixQuestionOrder[$buff]{'user'} = $parsedinfo[2]; $fixQuestionOrder[$buff]{'linkid'} = $parsedinfo[3]; $fixQuestionOrder[$buff]{'keywords'} = $keywords; $fixQuestionOrder[$buff]{'question'} = $parsedinfo[4]; $fixQuestionOrderSize += 1; print "Debug: Push matchKeywords: $parsedinfo[0] #: $#matchKeywords
\n"; } } } #print "Hello: keywordsfound = $keywordsfound\n"; # clean up $i = ''; $j = ''; # now, file through the array # set linkid to new array index. Replace entry in Database while ($i <= $fixQuestionOrderSize){ if ($fixQuestionOrder[$i]{'ID'}){ $j += 1; $fixQuestionOrder[$i]{'linkid'} = $j; $addstring = $fixQuestionOrder[$i]{'ID'} . "|" . $fixQuestionOrder[$i]{'datatype'} . "|" . $fixQuestionOrder[$i]{'user'} . "|" . $fixQuestionOrder[$i]{'linkid'} . "|" . $fixQuestionOrder[$i]{'keywords'} . "|" . $fixQuestionOrder[$i]{'question'}; $id = $fixQuestionOrder[$i]{'ID'}; print "fizing order!
\n"; &addEntryToDatabase; } $i++; } } sub addAnswersAndNotes{ # addAnswersAndNotes's job is to add a answer to a question in the database # is called by a form, who's required elements are: database, user, # question id to link to, answer, keywords. Keywords must match the # question to link to. There will be no finalize form because the # student is likely to be adding a few answers, and can edit their # answers later. Then addAnswersAndNotes calls search to display the question # with the answer added. Assumes DB is already open # add answers to questions and notes to database # $call{'questioncount'}, $call{'user'}, # $call{'keywordsx'} x is 1 - $call{'keywordcount'}, # $call{'notes'}, #
# # review form information, determine if info is to be added to db # while looping $call{'questioncount'} times $j = 0; # while looking at each ? on the form, while ($j < $call{'questioncount'}){ # print "while : $j < $call{'questioncount'}"; $j++; $ans = 'ansid' . $j; # if the user is admin, handle editing the question if ($call{'user'} eq $hash{'1'}){ $quest = ('question' . $j); if ($call{$quest}){ #if ($call{$quest} =~ m/delete/g){ # $qid = ("qid" . $j); # $del = $call{$qid}; # print "Deleting: qid: $qid
\n"; # delete $hash{$del}; #} #else { # edit the question here $datatype = '1'; $qlink = ("qlink" . $j); $linkid = $call{$qlink}; #print "Setting linkid: $qlink: $call{$qlink}.
\n"; $formdata = $call{$quest}; $qid = ("qid" . $j); #print "qid: $qid
\n"; $count = $call{$qid}; &assembleString; # parsedata.pl &addEntryToDatabase; #} } } # so if the text in the textbox exists, we can add a new entry. if ($call{$ans} eq 'new'){ # print "call{ans} eq 'new'
\n"; $loca = ("answer" . $j); if ($call{$loca}){ # print "I am adding an Answer
\n"; $datatype = '3'; $lnkid = ("link" . $j); #print "lnkid = $lnkid
\n"; $linkid = $call{$lnkid}; #print "Setting linkid: $linkid
\n"; $text = "answer" . $j; $formdata = $call{$text}; #print "Debug: call{$ans}: $call{ans}
\n"; #$count = $call{$ans}; &incrementDBcount; &assembleString; # parsedata.pl &addEntryToDatabase; } } # or, since the entry already exists, we update the db with new info else { $loca = ("answer" . $j); # print "loca : $loca"; if ($call{$loca}){ # print "adding Answer
\n"; $datatype = '3'; $lnkid = ("link" . $j); # print "lnkid = $lnkid
\n"; $linkid = $call{$lnkid}; # print "Setting linkid: $linkid
\n"; $text = "answer" . $j; $formdata = $call{$text}; # print "Debug: call{$ans}: $call{ans}
\n"; $count = $call{$ans}; #&incrementDBcount; &assembleString; # parsedata.pl &addEntryToDatabase; } } } # Now we will edit the where to go next text. if (($call{'next'}) && ($call{'user'} eq $hash{'1'})){ $datatype = '4'; $linkid = 'n'; # n = next (not used here, better than null) $formdata = $call{'next'}; $count = $call{'nextid'}; &assembleString; # parsedata.pl &addEntryToDatabase; } # Here is where we handle the wildcard data # the form is set up with the following fields # $call{'wildcardcount'} # $call{'keywordsx'} # These keywords exist only when the user is admin # Conceptually, when you edit a wildcard question, # it adds a new entry in the database. There is an # issue I am debating, How to set these questions up # to block the wildcard from appearing at this location? # $call{'wildcardq1'} # $call{'wildcardqlink1'} 4 # Anyways, the users can add answers that are relevant # to the wildcard q's. A problem however is that the answer # will appear in the normal array of questions because it # is like any other question. I know: Set the linkId of the # answer to this 'w45' where the w tells the program that # it links to a wildcard and it should be treated differently. # $call{'wildcard1'} The text for the answers # $call{'wildcardlink1'} 48 # $call{'wildcardansid1'} new # $call{'wildcardqid1'} $i = 0; $j = 0; while ($j <= $call{'wildcardcount'}){ $wildqid = "wildcardqid$j"; $wild = "wildcard$j"; $wildlink = "wildcardlink$j"; $wildansid = "wildcardansid$j"; # print "That's Wild! $wildqid, $wild, $wildlink, $wildansid"; if ($call{$wild}){ if ($call{$wildansid} eq "new"){ # create a new db item $datatype = '3'; $linkid = "w$call{$wildqid}"; $formdata = $call{$wild}; &incrementDBcount; &assembleString; # parsedata.pl &addEntryToDatabase; } else{ $datatype = '3'; $linkid = "w$call{$wildqid}"; $formdata = $call{$wild}; $count = $call{$wildansid}; &assembleString; # parsedata.pl &addEntryToDatabase; } } $j++; } # the following commented code calls the routine to fix the order # of questions in the db, and it's pretty buggy. #if ($call{'user'} eq $hash{'1'}){ # &fixQuestionOrder; #} if ($call{'note'} eq 'new'){ if ($call{'notes'}){ # print "Adding New Notes
\n"; # add notes to db $datatype = '2'; $linkid = '-'; $formdata = $call{'notes'}; &incrementDBcount; &assembleString; # parsedata.pl &addEntryToDatabase; } } else { if ($call{'notes'}){ # print "Editing Existing Notes
\n"; # add notes to db $datatype = '2'; $linkid = '-'; $formdata = $call{'notes'}; $count = $call{'note'}; #&incrementDBcount; &assembleString; # parsedata.pl &addEntryToDatabase; } } } sub matchKeywords{ # matchKeywords has to look for questions that match the # keyword identifiers, then it must look for data at these # locations that match the user and push the matching # database lines into an array. # the array that we are building's structure will be a list of hashes: # @matchKeywords = # [1]: # 'ID' = '14', # $matchKeywords[1]{'ID'} # 'datatype' = '1', # 'user' = 'keny', # 'linkid' = '2', # 'keywords' = 'x=y,x=y,x=y', # there will be a sub that parses keys # 'question' = 'the question?' # [2]: # 'ID' = '14', # 'datatype' = '1', # 'user' = 'keny', # 'linkid' = '2', # 'keywords' = 'x=y,x=y,x=y', # 'question' = 'the question?' # pseudo # for each entry in db # parseDatabaseString # if keywords match # if data type 1 add question to array # or user match && data type is 2 or 3, add note or answer to array # else ignore this db entry &defineKeywords; #$wildcards = 20; while (($key, $val) = each %hash){ $count = 0; #print "We are at: key: $key, val: $val
\n"; parseDatabaseString($val); #print "Debug $parsedinfo[1] eq '4'? $parsedinfo[0]
\n"; # if the data is the right type #if ($parsedinfo[1] eq '1') #print "We are at: parsedinfo[1]: $parsedinfo[1]
\n"; $i = 0; # while looping through the array of keywords from the form while ($i <= $#formkeys){ #print "We are at: i $i <= #formkeys $#formkeys
\n"; $j = 0; # compare with each keyword in the database location while ($j <= $#parsedstring){ #print "We are at: j $j <= #parsedstring $#parsedstring
\n"; if ($formkeys[$i] eq $parsedstring[$j]){ #print "We are at: formkeys[$i]: $formkeys[$i] eq parsedstring[$j]: $parsedstring[$j]
\n"; # this keyword matches. increment count $count += 1; $j = $#parsedstring; } $j++; } $i++; } $i = 0; # look for wildcards and increment count by number of # wildcard keywords while ($i <= $#parsedstring){ if ($parsedstring[$i] eq '*'){ $count += 1; $j = $#parsedstring; # print "want to play a game? $key $parsedstring[$j]
\n"; } $i += 1; } $i = 0; # if there are the same number of matches # as the size of the array parsedstring, # we have a match # print "Test: count: $count == #parsedstring: $#parsedstring
\n"; if ($count == ($#parsedstring + 1)){ # if daata type 1 or (if user matches & datatype is either 2 or 3) # print "Debug: parsedinfo[1] eq $parsedinfo[1]
\n"; if (($parsedinfo[1] eq '1') || ($parsedinfo[1] eq '4') || (($call{'user'} eq $parsedinfo[2]) && (($parsedinfo[1] eq '2') || ($parsedinfo[1] eq '3')))){ # print "$call{'user'} eq $parsedinfo[2] && $parsedinfo[1] is either 2 or 3, or $parsedinfo[1] = 1
\n"; if ($keywords =~ m/\*/){ push (@wildcards, { ID => $parsedinfo[0], # $matchKeywords[1]{'ID'} datatype => $parsedinfo[1], user => $parsedinfo[2], linkid => $parsedinfo[3], keywords => $keywords, # there will be a sub that parses keys question => $parsedinfo[4] }); if ($parsedinfo[1] eq '1'){ $wildcardcount += 1; } } elsif ($parsedinfo[1] eq '4'){ push (@gonext, { ID => $parsedinfo[0], # $matchKeywords[1]{'ID'} datatype => $parsedinfo[1], user => $parsedinfo[2], linkid => $parsedinfo[3], keywords => $keywords, # there will be a sub that parses keys question => $parsedinfo[4] }); } else{ if ($parsedinfo[3] !~ m/w/){ push (@matchKeywords, { ID => $parsedinfo[0], # $matchKeywords[1]{'ID'} datatype => $parsedinfo[1], user => $parsedinfo[2], linkid => $parsedinfo[3], keywords => $keywords, # there will be a sub that parses keys question => $parsedinfo[4] }); } else { # handle the wildcard response # print "Baa Baa Black Sheep
\n"; push (@wildcards, { ID => $parsedinfo[0], # $matchKeywords[1]{'ID'} datatype => $parsedinfo[1], user => $parsedinfo[2], linkid => $parsedinfo[3], keywords => $keywords, # there will be a sub that parses keys question => $parsedinfo[4] }); } } # print "Debug: Push matchKeywords: $parsedinfo[0] #: $#matchKeywords
\n"; } } } #print "Hello: keywordsfound = $keywordsfound\n"; # clean up $i = ''; $j = ''; #print "lo, Match Keywords out!"; } sub addEntryToDatabase{ # adds addstring to the database add string is an # assembled entry to the database it will be added at $id # Lesson: {$id} assigns the variable held in $id # as the hash key. {'$id'} assigns $id to the hash key # only use single quotes when there is a number or string, # not a variable. $hash{$id} = $addstring; } sub setOrderOfDisplayQuestions{ # assumes database is already open # analyzes form parameters from printFinalizeAddForm # and changes the appropriate link ids of the questions # that match the current question location. It then # creates $linkid which is the number for the current # question being added to be used in assembleQuestionEntry # $call{'numbermatched'} is the amount of questions found that match # $call{'order1_numbermatched'} are the form elements that contain id's # $call{'order_numbermatched+1'} is the question to be added. value = 0 # our job is to go through the form parameters and change the order to # the value set in $call{'order1_numbermatched'}. # while going through found form id's while ($i <= ($call{'numbermatched'} + 1)){ $num = 'order' . $i; # generates form variabale $id = $call{$num}; # points to form variable if ($call{$num} eq '0'){ # this one is the new question $linkid = $i; } else { $val = $hash{$id}; # points to db string &parseDatabaseString; # creates the next few var's $addstring = $parsedinfo[0] . "|" . $parsedinfo[1] . "|" . $parsedinfo[2] . "|" . $i . "|" . $keywords . "|" . $parsedinfo[4]; # if there is a legitimate string to add... if ($addstring != "|||||"){ &addEntryToDatabase; # see previous subroutine } } $i++; # go to next question } $i = 0; # print "The new question is Question # $linkid"; } sub searchForMatchQuestions{ # searchForMatchQuestions looks trough the database and # finds out whether or not there are questions that exist # for the keywords specified in @keywords. if it finds any # matching questions it pushes them into @matches @matches = ''; &openDBhash; # set up form elements into an array for future improvements # it would be nice to figure out a way to do this for as many # keywords as possible, but it's hard wired for 6 now. # a lesson learned: Parenthesis make this an array, # Brackets make this a hash. Hmmm. &defineKeywords; while (($key, $val) = each %hash){ #print "We are at: key: $key, val: $val
\n"; parseDatabaseString($val); # if the data is the right type if ($parsedinfo[1] eq '1'){ #print "We are at: parsedinfo[1]: $parsedinfo[1]
\n"; $i = 0; $count = 0; # while looping through the array of keywords from the form while ($i <= $#formkeys){ # print "We are at: i $i <= #formkeys $#formkeys
\n"; $j = 0; # compare with each keyword in the database location while ($j <= $#parsedstring){ #print "We are at: j $j <= #parsedstring $#parsedstring
\n"; if ($formkeys[$i] eq $parsedstring[$j]){ # print "We are at: formkeys[$i]: $formkeys[$i] eq parsedstring[$j]: $parsedstring[$j]
\n"; # this keyword matches. increment count $count += 1; $j = $#parsedstring; } $j++; } $i++; } # if there are the same number of matches # as the size of the array parsedstring, # we have a match #print "Test: count: $count == #parsedstring: $#parsedstring
\n"; if ($count == ($#parsedstring + 1)){ push @matches, $parsedinfo[0]; $keywordsfound = '1'; # we found matching keyword sets in the db } } } #print "Hello: keywordsfound = $keywordsfound\n"; &closeDBhash; # clean up $i = ''; $j = ''; } sub checkDatabase{ # checkdatabase is how we define which database to be used # therefore it must be present at all calls to riverweb # This element should be checked in the beginning of the # script. This routine returns an error page if the # database does not exist, exits the program. if ($call{'database'}){ # check to see if the database exists $buffer = 'database/' . $call{'database'}; if (!(-e $buffer)){ &printHtmlHeader; print "

"; print "The Database you specified does not exist.\n"; print "Please use your Browser's back button to fix the error\n"; print "

"; &printHtmlFooter; exit; } } else{ # the database is not specified # print error to screen # exit program &printHtmlHeader; print "

"; print "There was no database specified.\n"; print "Please use your Browser's back button to specify a database\n"; print "

"; &printHtmlFooter; exit; } } sub openDBhash{ # need to implement lock routines here tie %hash, DB_File, $dbmfile # open database, to be accessed or print "Can't open $dbmfile: $!\n"; # through %HASH } sub closeDBhash{ untie %hash; # close the database } sub incrementDBcount{ # $hash{'0'} is the special location where the count is kept # instead of using multiple databases, we are using one database and # setting certian locations to hold info. Hash format is better for # this even though we use numbers to index everything because unlike # arrays you can delete items and still have the same index numbers. # we need the same index numbers because we are linking items together # If you have an opinion I'd like to hear it: keny@graphicage.com $count = $hash{'0'}; $count = ($count +1); $hash{'0'} = $count; } 1;