SPTRecommender.php
Go to the documentation of this file.
00001 <?PHP 00002 # 00003 # FILE: SPTRecommender.php 00004 # 00005 # Copyright 2002-2010 Internet Scout and Edward Almasy 00006 # http://scout.wisc.edu 00007 # 00008 00009 class SPTRecommender extends Recommender { 00010 00011 function SPTRecommender() 00012 { 00013 # set up recommender configuration values for SPT 00014 $ItemTableName = "Resources"; 00015 $ItemIdFieldName = "ResourceId"; 00016 $RatingTableName = "ResourceRatings"; 00017 $UserIdFieldName = "UserId"; 00018 $RatingFieldName = "Rating"; 00019 00020 # build field info from SPT metadata schema 00021 $this->Schema = new MetadataSchema(); 00022 $Fields = $this->Schema->GetFields(); 00023 foreach ($Fields as $Field) 00024 { 00025 if ($Field->Enabled() && $Field->IncludeInKeywordSearch()) 00026 { 00027 $FieldName = $Field->Name(); 00028 $FieldInfo[$FieldName]["DBFieldName"] = $Field->DBFieldName(); 00029 $FieldInfo[$FieldName]["Weight"] = $Field->SearchWeight(); 00030 switch ($Field->Type()) 00031 { 00032 case MetadataSchema::MDFTYPE_TEXT: 00033 case MetadataSchema::MDFTYPE_PARAGRAPH: 00034 case MetadataSchema::MDFTYPE_USER: 00035 case MetadataSchema::MDFTYPE_URL: 00036 $FieldInfo[$FieldName]["FieldType"] = 00037 Recommender::CONTENTFIELDTYPE_TEXT; 00038 break; 00039 00040 case MetadataSchema::MDFTYPE_TREE: 00041 case MetadataSchema::MDFTYPE_CONTROLLEDNAME: 00042 case MetadataSchema::MDFTYPE_OPTION: 00043 $FieldInfo[$FieldName]["FieldType"] = 00044 Recommender::CONTENTFIELDTYPE_TEXT; 00045 break; 00046 00047 case MetadataSchema::MDFTYPE_NUMBER: 00048 case MetadataSchema::MDFTYPE_FLAG: 00049 $FieldInfo[$FieldName]["FieldType"] = 00050 Recommender::CONTENTFIELDTYPE_NUMERIC; 00051 break; 00052 00053 case MetadataSchema::MDFTYPE_DATE: 00054 $FieldInfo[$FieldName]["FieldType"] = 00055 Recommender::CONTENTFIELDTYPE_DATERANGE; 00056 break; 00057 00058 case MetadataSchema::MDFTYPE_TIMESTAMP: 00059 $FieldInfo[$FieldName]["FieldType"] = 00060 Recommender::CONTENTFIELDTYPE_DATE; 00061 break; 00062 00063 case MetadataSchema::MDFTYPE_IMAGE: 00064 # (for images we use their alt text) 00065 $FieldInfo[$FieldName]["FieldType"] = 00066 Recommender::CONTENTFIELDTYPE_TEXT; 00067 break; 00068 00069 case MetadataSchema::MDFTYPE_FILE: 00070 # (for files we use the file name) 00071 $FieldInfo[$FieldName]["FieldType"] = 00072 Recommender::CONTENTFIELDTYPE_TEXT; 00073 break; 00074 } 00075 } 00076 } 00077 00078 # create our own schema object and tell it to cache values 00079 $this->Schema = new MetadataSchema(); 00080 $this->Schema->CacheData(TRUE); 00081 00082 # create a database connection for recommender to use 00083 $DB = new SPTDatabase(); 00084 00085 # pass configuration info to real recommender object 00086 $this->Recommender($DB, $ItemTableName, $RatingTableName, 00087 $ItemIdFieldName, $UserIdFieldName, $RatingFieldName, 00088 $FieldInfo); 00089 } 00090 00091 # overloaded version of method to retrieve field values from DB 00092 function GetFieldValue($ItemId, $FieldName) 00093 { 00094 static $Resources; 00095 00096 # if resource not already loaded 00097 if (!isset($Resources[$ItemId])) 00098 { 00099 # get resource object 00100 $Resources[$ItemId] = new Resource($ItemId); 00101 00102 # if cached resource limit exceeded 00103 if (count($Resources) > 100) 00104 { 00105 # dump oldest resource 00106 reset($Resources); 00107 list($DumpedItemId, $DumpedResources) = each($Resources); 00108 unset($Resources[$DumpedItemId]); 00109 } 00110 } 00111 00112 # retrieve field value from resource object and return to caller 00113 $FieldValue = $Resources[$ItemId]->Get($FieldName); 00114 return $FieldValue; 00115 } 00116 00117 function QueueUpdateForItem($ItemId, 00118 $Priority = ApplicationFramework::PRIORITY_LOW) 00119 { 00120 global $AF; 00121 $AF->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"), 00122 array(intval($ItemId), 0), $Priority); 00123 } 00124 00125 static function RunUpdateForItem($SourceItemId, $StartingIndex) 00126 { 00127 # check that resource still exists 00128 $RFactory = new ResourceFactory(); 00129 if (!$RFactory->ItemExists($SourceItemId)) { return; } 00130 00131 # load recommender engine 00132 static $Recommender; 00133 if (!isset($Recommender)) { $Recommender = new SPTRecommender(); } 00134 00135 # if starting update for source item 00136 if ($StartingIndex == 0) 00137 { 00138 # clear data for item 00139 $Recommender->DropItem($SourceItemId); 00140 } 00141 00142 # load array of item IDs 00143 $TargetItemIds = $Recommender->GetItemIds(); 00144 $TargetCount = count($TargetItemIds); 00145 00146 # while not last item ID and not out of time 00147 global $AF; 00148 for ($Index = $StartingIndex; ($Index < $TargetCount) 00149 && ($AF->GetSecondsBeforeTimeout() > 5); $Index++) 00150 { 00151 # if target ID points to non-temporary entry 00152 if ($TargetItemIds[$Index] >= 0) 00153 { 00154 # update correlation for source item and current item 00155 $Recommender->UpdateContentCorrelation( 00156 $SourceItemId, $TargetItemIds[$Index]); 00157 } 00158 } 00159 00160 # if all correlations completed for source item 00161 if ($Index >= $TargetCount) 00162 { 00163 # periodically prune correlations if enough time remaining 00164 if (($AF->GetSecondsBeforeTimeout() > 10) && (rand(1, 10) == 1)) 00165 { 00166 $Recommender->PruneCorrelations(); 00167 } 00168 } 00169 else 00170 { 00171 # requeue updates for remaining items 00172 $AF->QueueUniqueTask(array(__CLASS__, "RunUpdateForItem"), 00173 array($SourceItemId, $Index), ApplicationFramework::PRIORITY_MEDIUM); 00174 } 00175 } 00176 00177 00178 # ---- PRIVATE INTERFACE ------------------------------------------------- 00179 00180 private $Schema; 00181 00182 }; 00183 00184 00185 ?>