Пример #1
0
 static function getSuggestions($userId = -1)
 {
     global $configArray;
     if ($userId == -1) {
         global $user;
         $userId = $user->id;
     }
     //Load all titles the user is not interested in
     $notInterestedTitles = array();
     $notInterested = new NotInterested();
     $resource = new Resource();
     $notInterested->joinAdd($resource);
     $notInterested->userId = $userId;
     $notInterested->find();
     while ($notInterested->fetch()) {
         if ($notInterested->source == 'VuFind') {
             $fullId = $notInterested->record_id;
         } else {
             $fullId = 'econtentRecord' . $notInterested->record_id;
         }
         $notInterestedTitles[$fullId] = $fullId;
     }
     //Load all titles the user has rated (print)
     $allRatedTitles = array();
     $allLikedRatedTitles = array();
     $ratings = new UserRating();
     $ratings->userid = $userId;
     $resource = new Resource();
     $notInterested->joinAdd($resource);
     $ratings->joinAdd($resource);
     $ratings->find();
     while ($ratings->fetch()) {
         $allRatedTitles[$ratings->record_id] = $ratings->record_id;
         if ($ratings->rating >= 4) {
             $allLikedRatedTitles[] = $ratings->record_id;
         }
     }
     //Load all titles the user has rated (eContent)
     $econtentRatings = new EContentRating();
     $econtentRatings->userId = $userId;
     $econtentRatings->find();
     while ($econtentRatings->fetch()) {
         $allRatedTitles['econtentRecord' . $econtentRatings->recordId] = 'econtentRecord' . $econtentRatings->recordId;
         if ($econtentRatings->rating >= 4) {
             $allLikedRatedTitles[] = 'econtentRecord' . $econtentRatings->recordId;
         }
     }
     // Setup Search Engine Connection
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     $db = new $class($url);
     if ($configArray['System']['debugSolr']) {
         $db->debug = true;
     }
     //Get a list of all titles the user has rated (3 star and above)
     $ratings = new UserRating();
     $ratings->whereAdd("userId = {$userId}", 'AND');
     $ratings->whereAdd('rating >= 3', 'AND');
     $ratings->orderBy('rating DESC, dateRated DESC, id DESC');
     //Use the 20 highest ratings to make real-time recommendations faster
     $ratings->limit(0, 5);
     $ratings->find();
     $suggestions = array();
     //echo("User has rated {$ratings->N} titles<br/>");
     if ($ratings->N > 0) {
         while ($ratings->fetch()) {
             $resourceId = $ratings->resourceid;
             //Load the resource
             $resource = new Resource();
             $resource->id = $resourceId;
             $resource->find();
             if ($resource->N != 1) {
                 //echo("Did not find resource for $resourceId<br/>");
             } else {
                 $resource->fetch();
                 //echo("Found resource for $resourceId - {$resource->title}<br/>");
                 $ratedTitles[$resource->record_id] = clone $ratings;
                 $numRecommendations = 0;
                 if ($resource->isbn) {
                     //If there is an isbn for the title, we can load similar titles based on Novelist.
                     $isbn = $resource->isbn;
                     $numRecommendations = Suggestions::getNovelistRecommendations($ratings, $isbn, $resource, $allRatedTitles, $suggestions, $notInterestedTitles);
                     //echo("&nbsp;- Found $numRecommendations for $isbn from Novelist<br/>");
                 }
                 if ($numRecommendations == 0) {
                     Suggestions::getSimilarlyRatedTitles($db, $ratings, $userId, $allRatedTitles, $suggestions, $notInterestedTitles);
                     //echo("&nbsp;- Found $numRecommendations based on ratings from other users<br/>");
                 }
             }
         }
     }
     //Also get eContent the user has rated highly
     $econtentRatings = new EContentRating();
     $econtentRatings->userId = $userId;
     $econtentRatings->whereAdd('rating >= 3');
     $econtentRatings->orderBy('rating DESC, dateRated DESC');
     $econtentRatings->limit(0, 5);
     $econtentRatings->find();
     //echo("User has rated {$econtentRatings->N} econtent titles<br/>");
     if ($econtentRatings->N > 0) {
         while ($econtentRatings->fetch()) {
             //echo("Processing eContent Rating {$econtentRatings->recordId}<br/>");
             //Load the resource
             $resource = new Resource();
             $resource->record_id = $econtentRatings->recordId;
             $resource->source = 'eContent';
             $resource->find();
             if ($resource->N != 1) {
                 //echo("Did not find resource for $resourceId<br/>");
             } else {
                 $resource->fetch();
                 //echo("Found resource for $resourceId - {$resource->title}<br/>");
                 $ratedTitles[$resource->record_id] = clone $econtentRatings;
                 $numRecommendations = 0;
                 if ($resource->isbn) {
                     //If there is an isbn for the title, we can load similar titles based on Novelist.
                     $isbn = $resource->isbn;
                     $numRecommendations = Suggestions::getNovelistRecommendations($ratings, $isbn, $resource, $allRatedTitles, $suggestions, $notInterestedTitles);
                     //echo("&nbsp;- Found $numRecommendations for $isbn from Novelist<br/>");
                 }
                 if ($numRecommendations == 0) {
                     Suggestions::getSimilarlyRatedTitles($db, $ratings, $userId, $allRatedTitles, $suggestions, $notInterestedTitles);
                     //echo("&nbsp;- Found $numRecommendations based on ratings from other users<br/>");
                 }
             }
         }
     }
     $groupedTitles = array();
     foreach ($suggestions as $suggestion) {
         $groupingTerm = $suggestion['titleInfo']['grouping_term'];
         $groupedTitles[] = $groupingTerm;
     }
     //If the user has not rated anything, return nothing.
     if (count($allLikedRatedTitles) == 0) {
         return array();
     }
     //Get recommendations based on everything I've rated using more like this functionality
     $class = $configArray['Index']['engine'];
     $url = $configArray['Index']['url'];
     /** @var Solr $db */
     $db = new $class($url);
     //$db->debug = true;
     $moreLikeTheseSuggestions = $db->getMoreLikeThese($allLikedRatedTitles);
     //print_r($moreLikeTheseSuggestions);
     if (count($suggestions) < 30) {
         foreach ($moreLikeTheseSuggestions['response']['docs'] as $suggestion) {
             $groupingTerm = $suggestion['grouping_term'];
             if (array_key_exists($groupingTerm, $groupedTitles)) {
                 //echo ($suggestion['grouping_term'] . " is already in the suggestions");
                 continue;
             }
             $groupedTitles[$groupingTerm] = $groupingTerm;
             //print_r($suggestion);
             if (!array_key_exists($suggestion['id'], $allRatedTitles) && !array_key_exists($suggestion['id'], $notInterestedTitles)) {
                 $suggestions[$suggestion['id']] = array('rating' => $suggestion['rating'] - 2.5, 'titleInfo' => $suggestion, 'basedOn' => 'MetaData for all titles rated');
             }
             if (count($suggestions) == 30) {
                 break;
             }
         }
     }
     //print_r($groupedTitles);
     //sort suggestions based on score from ascending to descending
     uasort($suggestions, 'Suggestions::compareSuggestions');
     //Only return up to 50 suggestions to make the page size reasonable
     $suggestions = array_slice($suggestions, 0, 30, true);
     //Return suggestions for use in the user interface.
     return $suggestions;
 }