/[drupal]/contributions/sandbox/scottreynolds/modules/cre.module
ViewVC logotype

Contents of /contributions/sandbox/scottreynolds/modules/cre.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.7 - (show annotations) (download) (as text)
Tue Jul 11 23:22:10 2006 UTC (3 years, 4 months ago) by scottreynolds
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +2 -2 lines
File MIME type: text/x-php
cre speed improvements. Added page callback to node_recommendation.
Intial work on views addition
1 <?php
2 // $Id:$
3 /*
4 A generalized recommendation engine. Depends on votingapi.module. see README.txt
5 */
6
7 function cre_help($section) {
8 switch ($section) {
9 case 'admin/modules#description':
10 return t("Provides api access any votable content used in votingapi. This is the backend engine");
11 case 'admin/settings/cre':
12 return t("Provides an recommendataion api to access recommended content");
13 }
14 }
15 /*
16 * Creates or updates a record in cre_similarity_matrix. Maintains the sum and count
17 * Therefore, the avgerage difference between the two pieces of content can be calculated
18 *
19 * @param $userID
20 * The uid of the vote
21 *
22 * @param $itemID
23 * content_id of the new vote
24 *
25 * @return
26 * NONE
27 *
28 */
29 function cre_modify_avg_difference($userID,$itemID)
30 {
31 // switch globals on database type!!!
32 // Run my magik! put the values in cre_similarity_matrix table
33
34 $db_result = db_query("SELECT DISTINCT r.content_id, r2.value-r.value as rating_difference, r.content_type as content_type1, r2.content_type as content_type2
35 FROM {votingapi_vote} r, {votingapi_vote} r2
36 WHERE r.uid=%d AND r2.content_id=%d AND r2.uid=r.uid", $userID, $itemID);
37 if(!$db_result)
38 {
39 drupal_set_message(t('ERROR'));
40 }
41 else
42 {
43 while($row = db_fetch_array($db_result))
44 {
45 $other_node=$row["content_id"];
46 $rating_difference=$row["rating_difference"];
47
48 // check to see if the pair of content ($itemID and $other_node) are already in the cre_similarity_matrix table
49 if(db_num_rows(db_query("SELECT content_id1 from {cre_similarity_matrix} WHERE content_id1=%d AND content_id2=%d",$itemID,$other_node)) > 0)
50 {
51 //update the two rows
52 //drupal_set_message(t('updated!'));
53 db_query("UPDATE {cre_similarity_matrix} SET count=count+1, sum=sum+%d
54 WHERE content_id1=%d AND content_id2=%d", $rating_difference, $itemID, $other_node);
55 // update the second row ONLY if the two nodes are different
56 if($itemID != $other_node)
57 {
58 db_query("UPDATE {cre_similarity_matrix} SET count=count+1, sum=sum-%d
59 WHERE content_id1=%d AND content_id2=%d", $rating_difference, $other_node, $itemID);
60 }
61 }
62 // if this is a new 'pairing' create two rows
63 else
64 {
65 $content_type1 = $row['content_type1'];
66 $content_type2 = $row['content_type2'];
67 // insert 2 rows only if the nodes are different
68 db_query("INSERT INTO {cre_similarity_matrix} VALUES (%d,%d,'%s','%s',1, %d)",$itemID,$other_node,$content_type1,$content_type2,$rating_difference);
69
70 if($itemID != $other_node)
71 {
72 db_query("INSERT INTO {cre_similarity_matrix} VALUES(%d, %d,'%s','%s',1,%d)",$other_node,$itemID,$content_type2,$content_type1,-$rating_difference);
73 }
74 }
75 }
76 }
77 }
78
79 /*
80 * Returns an array of the top n content
81 *
82 * @param $uid
83 * user id for the personalized recommendation
84 *
85 * @param $n default 10
86 * specifies the number of contents to return
87 *
88 * @param $target_type
89 * the type of content that the calling function would like
90 *
91 * @param $tag default 'vote'
92 * same as in votingapi. See votingapi
93 *
94 * @param $reference_type default NULL
95 * When set only those votes whos content_type is equal to this
96 * will be considered for the recommendations.
97 *
98 * @return
99 * returns an array of objs with content_id and score
100 */
101 function cre_top($uid, $n=10, $target_type = 'node', $tag = 'vote',$reference_type = NULL)
102 {
103
104 if(isset($reference_type)) {
105 $db_result = db_query("SELECT d.content_id1 as 'content_id', sum(d.sum+d.count*r.value)/sum(d.count) as 'score'
106 FROM {votingapi_vote} r, {cre_similarity_matrix} d
107 WHERE r.uid=%d AND d.content_id1<>r.content_id AND d.content_id2=r.content_id AND d.content_type1='%s' AND d.content_type2='%s' AND r.tag='%s'
108 GROUP BY d.content_id1 ORDER BY score DESC",$uid,$target_type,$reference_type, $tag);
109
110 }
111 else
112 {
113 $db_result = db_query("SELECT d.content_id1 as 'content_id', sum(d.sum+d.count*r.value)/sum(d.count) as 'score'
114 FROM {votingapi_vote} r, {cre_similarity_matrix} d
115 WHERE r.uid=%d AND d.content_id1<>r.content_id AND d.content_id2=r.content_id AND d.content_type1='%s' AND d.content_type2=d.content_type1 AND r.tag='%s'
116 GROUP BY d.content_id1 ORDER BY score DESC",$uid,$target_type,$tag);
117 }
118
119 $count = 0;
120
121 while($matrixobj = db_fetch_object($db_result)) {
122 if($count >= $n) {
123 break;
124 }
125 // do a check to see if the content was rated by the uid
126 $content_id = $matrixobj->content_id;
127 $user_check_result = votingapi_get_vote($target_type, $content_id,'percent', 'vote', $uid);
128
129 if(!$user_check_result) {
130 $return_value[] = $matrixobj;
131 $count++;
132 }
133 }
134 if(isset($return_value)) {
135 return $return_value;
136 }
137 else
138 {
139 // do something special when user has rated all nodes
140 // return top rated nodes?
141 //return "No nodes";
142 }
143 }
144
145 /*
146 * Returns an array of content objs
147 *
148 * @param $n
149 * The number of objs to return
150 *
151 * @param $nid
152 * content_id that the return objects will be similar too
153 *
154 * @param $target_type
155 * Type of content to return from this function
156 *
157 * @param $tag
158 * votingapi tag. See Votingapi.module
159 *
160 * @param $reference_type
161 * specifies the type of content that will be only be used to determine the revelenance of
162 * a certain piece of content
163 *
164 * @return
165 * $return_value[] is an array of objs that have two fields, content_id and average.
166 *
167 */
168
169 function cre_similar($n,$nid,$target_type,$tag='vote',$reference_type = NULL) // reference_type is sets which content_types are allowed to be reference when determining score
170 {
171 // need to allow for reference_type to be an array!
172
173 if(isset($reference_type)) {
174 $sql_result = db_query("SELECT d.content_id2 as 'content_id', (d.sum / d.count) AS 'average'
175 FROM {cre_similarity_matrix} d
176 WHERE d.content_id1=%d AND d.content_id2 <> %d AND content_type1='%s' AND content_type2='%s'
177 ORDER BY (sum/count) DESC LIMIT %d",$nid,$nid, $reference_type,$target_type,$n);
178 }
179 else {
180 $sql_result = db_query("SELECT d.content_id2 as 'content_id', (d.sum / d.count) AS 'average'
181 FROM {cre_similarity_matrix} d
182 WHERE d.content_id1=%d AND d.content_id2 <> %d AND content_type2='%s'
183 ORDER BY (sum/count) DESC LIMIT %d",$nid,$nid,$target_type,$n);
184 }
185 while($recommend_obj = db_fetch_object($sql_result)) {
186 $return_value[] = $recommend_obj;
187 }
188 return $return_value;
189
190 }
191
192 /*
193 * implementation of votingapi's hook_insert()
194 */
195
196 function cre_votingapi_insert(&$vote)
197 {
198 // run my magik!
199 // $vote obj has all the fields for a vote record! extract uid, nid
200 cre_modify_avg_difference($vote->uid,$vote->content_id);
201 //drupal_set_message(t('function Called'));
202 return;
203 }
204
205 /*
206 * implementation of votingapi's hook_update
207 */
208
209 function cre_votingapi_update(&$vote,$new_value)
210 {
211 // when a vote is updated need to just adjust sum NOT COUNT!!
212 // for all records in cre_similarity_matrix where content_id1 or content_id2 equals vote->content_id
213 // and the adjustment to sum MUST BE THE RATING_DIFFERENCE
214
215 $rating_difference = $new_value-$vote->value;
216 //drupal_set_message(t('difference = ' . $rating_difference));
217
218 db_query("UPDATE {cre_similarity_matrix} SET sum=sum+%d
219 WHERE content_id1=%d", $rating_difference, $vote->content_id);
220
221 db_query("UPDATE {cre_similarity_matrix} SET sum=sum-%d
222 WHERE content_id2=%d",$rating_difference, $vote->content_id);
223
224 }
225 /*
226 * implementation of votingapi's hook_delete
227 */
228 function cre_votingapi_delete(&$vote)
229 {
230 // TODO: modifiy the cre_similarity_matrix table by subratcting from count
231 // and subtracting vote value from sum
232 // OVER ALL REFERENCES TO THE CONTENT_ID
233 // THINK !!! reverse of build!!
234 $userID = $vote->uid;
235 $itemID = $vote->content_id;
236 $db_result = db_query("SELECT DISTINCT r.content_id, r2.value-r.value as rating_difference, r.content_type as content_type1, r2.content_type as content_type2
237 FROM {votingapi_vote} r, {votingapi_vote} r2
238 WHERE r.uid=%d AND r2.content_id=%d AND r2.uid=r.uid", $userID, $itemID);
239 if(!$db_result)
240 {
241 drupal_set_message(t('ERROR $userID, $itemID'));
242 }
243 else
244 {
245 while($row = db_fetch_array($db_result))
246 {
247 $other_node=$row["content_id"];
248 $rating_difference=$row["rating_difference"];
249
250
251 //update the two rows
252 db_query("UPDATE {cre_similarity_matrix} SET count=count-1, sum=sum-%d
253 WHERE content_id1=%d AND content_id2=%d", $rating_difference, $itemID, $other_node);
254
255 // update the second row ONLY if the two nodes are different
256 if($itemID != $other_node)
257 {
258 db_query("UPDATE {cre_similarity_matrix} SET count=count-1, sum=sum+%d
259 WHERE content_id1=%d AND content_id2=%d", $rating_difference, $other_node, $itemID);
260 }
261 }
262 }
263 }
264
265 /*
266 * private function to install the module over existing voting data
267 */
268
269 function _cre_load_all_diff_avg()
270 {
271 // for every uid
272 $usersSQL = "SELECT DISTINCT uid from {votingapi_vote}";
273
274 $db_result = db_query($usersSQL);
275 if(!$db_result)
276 {
277 drupal_set_message(t('NO USERS!!'));
278 return;
279 }
280
281 while($row = db_fetch_array($db_result))
282 {
283 $userID = $row['uid'];
284
285 // for every thing they rated
286 $vote_result = db_query("SELECT content_id
287 FROM {votingapi_vote}
288 WHERE uid=%d",$userID);
289 if(!$vote_result)
290 {
291 drupal_set_message(t('No votes have been placed yet'));
292 return;
293 }
294 while($voting_record = db_fetch_array($vote_result))
295 {
296 $content_id = $voting_record['content_id'];
297
298 // run the build function
299 cre_modify_avg_difference($userID,$content_id);
300 }
301 }
302 }

  ViewVC Help
Powered by ViewVC 1.1.2