Mercurial > hg > xemacs-beta
comparison lisp/gnus/gnus-gl.el @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | ec9a17fef872 |
children | 0d2f883870bc |
comparison
equal
deleted
inserted
replaced
69:804d1389bcd6 | 70:131b0175ea99 |
---|---|
1 ;;; gnus-gl.el --- an interface to GroupLens for Gnus | 1 ;;; gnus-gl.el --- an interface to GroupLens for Gnus |
2 ;; Copyright (C) 1995,96,97 Free Software Foundation, Inc. | 2 ;; Copyright (C) 1995,96 Free Software Foundation, Inc. |
3 | 3 |
4 ;; Author: Brad Miller <bmiller@cs.umn.edu> | 4 ;; Author: Brad Miller <bmiller@cs.umn.edu> |
5 ;; Keywords: news, score | 5 ;; Keywords: news, score |
6 | 6 |
7 ;; This file is part of GNU Emacs. | 7 ;; This file is part of GNU Emacs. |
41 ;; warranty. | 41 ;; warranty. |
42 ;; | 42 ;; |
43 ;; The copyright holders request that they be notified of | 43 ;; The copyright holders request that they be notified of |
44 ;; modifications of this code. Please send electronic mail to | 44 ;; modifications of this code. Please send electronic mail to |
45 ;; grouplens@cs.umn.edu for more information or to announce derived | 45 ;; grouplens@cs.umn.edu for more information or to announce derived |
46 ;; works. | 46 ;; works. |
47 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 47 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
48 ;; Author: Brad Miller | 48 ;; Author: Brad Miller |
49 ;; | 49 ;; |
50 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 50 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
51 ;; | 51 ;; |
54 ;; You must also register a pseudonym with the Better Bit Bureau. | 54 ;; You must also register a pseudonym with the Better Bit Bureau. |
55 ;; http://www.cs.umn.edu/Research/GroupLens | 55 ;; http://www.cs.umn.edu/Research/GroupLens |
56 ;; | 56 ;; |
57 ;; ---------------- For your .emacs or .gnus file ---------------- | 57 ;; ---------------- For your .emacs or .gnus file ---------------- |
58 ;; | 58 ;; |
59 ;; As of version 2.5, grouplens now works as a minor mode of | 59 ;; As of version 2.5, grouplens now works as a minor mode of |
60 ;; gnus-summary-mode. To get make that work you just need a couple of | 60 ;; gnus-summary-mode. To get make that work you just need a couple of |
61 ;; hooks. | 61 ;; hooks. |
62 ;; (setq gnus-use-grouplens t) | 62 ;; (setq gnus-use-grouplens t) |
63 ;; (setq grouplens-pseudonym "") | 63 ;; (setq grouplens-pseudonym "") |
64 ;; (setq grouplens-bbb-host "grouplens.cs.umn.edu") | 64 ;; (setq grouplens-bbb-host "grouplens.cs.umn.edu") |
67 ;; | 67 ;; |
68 ;; USING GROUPLENS | 68 ;; USING GROUPLENS |
69 ;; How do I Rate an article?? | 69 ;; How do I Rate an article?? |
70 ;; Before you type n to go to the next article, hit a number from 1-5 | 70 ;; Before you type n to go to the next article, hit a number from 1-5 |
71 ;; Type r in the summary buffer and you will be prompted. | 71 ;; Type r in the summary buffer and you will be prompted. |
72 ;; Note that when you're in grouplens-minor-mode 'r' masks the | 72 ;; Note that when you're in grouplens-minor-mode 'r' maskes the |
73 ;; usual reply binding for 'r' | 73 ;; usual reply binding for 'r' |
74 ;; | 74 ;; |
75 ;; What if, Gasp, I find a bug??? | 75 ;; What if, Gasp, I find a bug??? |
76 ;; Please type M-x gnus-gl-submit-bug-report. This will set up a | 76 ;; Please type M-x gnus-gl-submit-bug-report. This will set up a |
77 ;; mail buffer with the state of variables and buffers that will help | 77 ;; mail buffer with the state of variables and buffers that will help |
78 ;; me debug the problem. A short description up front would help too! | 78 ;; me debug the problem. A short description up front would help too! |
79 ;; | 79 ;; |
80 ;; How do I display the prediction for an article: | 80 ;; How do I display the prediction for an aritcle: |
81 ;; If you set the gnus-summary-line-format as shown above, the score | 81 ;; If you set the gnus-summary-line-format as shown above, the score |
82 ;; (prediction) will be shown automatically. | 82 ;; (prediction) will be shown automatically. |
83 ;; | 83 ;; |
84 ;; | 84 ;; |
85 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 85 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
86 ;; Programmer Notes | 86 ;; Programmer Notes |
87 ;; 10/9/95 | 87 ;; 10/9/95 |
88 ;; gnus-scores-articles contains the articles | 88 ;; gnus-scores-articles contains the articles |
89 ;; When scoring is done, the call tree looks something like: | 89 ;; When scoring is done, the call tree looks something like: |
90 ;; gnus-possibly-score-headers | 90 ;; gnus-possibly-score-headers |
91 ;; ==> gnus-score-headers | 91 ;; ==> gnus-score-headers |
113 ;; 4. Better error handling for token timeouts. | 113 ;; 4. Better error handling for token timeouts. |
114 ;; | 114 ;; |
115 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 115 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
116 ;; bugs | 116 ;; bugs |
117 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 117 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
118 ;; | 118 ;; |
119 | 119 |
120 ;;; Code: | 120 ;;; Code: |
121 | 121 |
122 (require 'gnus-score) | 122 (require 'gnus-score) |
123 (require 'cl) | 123 (require 'cl) |
124 (require 'gnus) | |
125 | 124 |
126 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 125 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
127 ;;;; User variables | 126 ;;;; User variables |
128 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 127 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
129 | 128 |
130 (defvar gnus-summary-grouplens-line-format | 129 (defvar gnus-summary-grouplens-line-format |
131 "%U\%R\%z%l%I\%(%[%4L: %-20,20n%]%) %s\n" | 130 "%U\%R\%z%l%I\%(%[%4L: %-20,20n%]%) %s\n" |
132 "*The line format spec in summary GroupLens mode buffers.") | 131 "*The line format spec in summary GroupLens mode buffers.") |
133 | 132 |
134 (defvar grouplens-pseudonym "" | 133 (defvar grouplens-pseudonym "" |
135 "User's pseudonym. | 134 "User's pseudonym. This pseudonym is obtained during the registration process") |
136 This pseudonym is obtained during the registration process") | |
137 | 135 |
138 (defvar grouplens-bbb-host "grouplens.cs.umn.edu" | 136 (defvar grouplens-bbb-host "grouplens.cs.umn.edu" |
139 "Host where the bbbd is running" ) | 137 "Host where the bbbd is running" ) |
140 | 138 |
141 (defvar grouplens-bbb-port 9000 | 139 (defvar grouplens-bbb-port 9000 |
142 "Port where the bbbd is listening" ) | 140 "Port where the bbbd is listening" ) |
143 | 141 |
144 (defvar grouplens-newsgroups | 142 (defvar grouplens-newsgroups |
145 '("comp.groupware" "comp.human-factors" "comp.lang.c++" | 143 '("comp.lang.c++" "rec.humor" "rec.food.recipes" "comp.groupware" |
146 "comp.lang.java" "comp.os.linux.admin" "comp.os.linux.advocacy" | |
147 "comp.os.linux.announce" "comp.os.linux.answers" | |
148 "comp.os.linux.development" "comp.os.linux.development.apps" | |
149 "comp.os.linux.development.system" "comp.os.linux.hardware" | |
150 "comp.os.linux.help" "comp.os.linux.m68k" "comp.os.linux.misc" | |
151 "comp.os.linux.networking" "comp.os.linux.setup" "comp.os.linux.x" | |
152 "mn.general" "rec.arts.movies" "rec.arts.movies.current-films" | 144 "mn.general" "rec.arts.movies" "rec.arts.movies.current-films" |
153 "rec.food.recipes" "rec.humor") | 145 "comp.lang.java" "comp.os.linux.announce" "comp.os.linux.misc" |
146 "comp.os.linux.development.apps" "comp.os.linux.development.system") | |
154 "*Groups that are part of the GroupLens experiment.") | 147 "*Groups that are part of the GroupLens experiment.") |
155 | 148 |
156 (defvar grouplens-prediction-display 'prediction-spot | 149 (defvar grouplens-prediction-display 'prediction-spot |
157 "valid values are: | 150 "valid values are: |
158 prediction-spot -- an * corresponding to the prediction between 1 and 5, | 151 prediction-spot -- an * corresponding to the prediction between 1 and 5, |
159 confidence-interval -- a numeric confidence interval | 152 confidence-interval -- a numeric confidence interval |
160 prediction-bar -- |##### | the longer the bar, the better the article, | 153 prediction-bar -- |##### | the longer the bar, the better the article, |
161 confidence-bar -- | ----- } the prediction is in the middle of the bar, | 154 confidence-bar -- | ----- } the prediction is in the middle of the bar, |
162 confidence-spot -- ) * | the spot gets bigger with more confidence, | 155 confidence-spot -- ) * | the spot gets bigger with more confidence, |
163 prediction-num -- plain-old numeric value, | 156 prediction-num -- plain-old numeric value, |
164 confidence-plus-minus -- prediction +/i confidence") | 157 confidence-plus-minus -- prediction +/i confidence") |
165 | 158 |
166 (defvar grouplens-score-offset 0 | 159 (defvar grouplens-score-offset 0 |
167 "Offset the prediction by this value. | 160 "Offset the prediction by this value. |
168 Setting this variable to -2 would have the following effect on | 161 Setting this variable to -2 would have the following effect on |
169 GroupLens scores: | 162 GroupLens scores: |
170 | 163 |
171 1 --> -2 | 164 1 --> -2 |
172 2 --> -1 | 165 2 --> -1 |
173 3 --> 0 | 166 3 --> 0 |
174 4 --> 1 | 167 4 --> 1 |
175 5 --> 2 | 168 5 --> 2 |
176 | 169 |
177 The reason is that a user might want to do this is to combine | 170 The reason is that a user might want to do this is to combine |
178 GroupLens predictions with scores calculated by other score methods.") | 171 GroupLens predictions with scores calculated by other score methods.") |
179 | 172 |
180 (defvar grouplens-score-scale-factor 1 | 173 (defvar grouplens-score-scale-factor 1 |
181 "This variable allows the user to magnify the effect of GroupLens scores. | 174 "This variable allows the user to magnify the effect of GroupLens scores. |
182 The scale factor is applied after the offset.") | 175 The scale factor is applied after the offset.") |
183 | 176 |
184 (defvar gnus-grouplens-override-scoring 'override | 177 (defvar gnus-grouplens-override-scoring 'override |
185 "Tell GroupLens to override the normal Gnus scoring mechanism. | 178 "Tell Grouplens to override the normal Gnus scoring mechanism. |
186 GroupLens scores can be combined with gnus scores in one of three ways. | 179 GroupLens scores can be combined with gnus scores in one of three ways. |
187 'override -- just use grouplens predictions for grouplens groups | 180 'override -- just use grouplens predictions for grouplens groups |
188 'combine -- combine grouplens scores with gnus scores | 181 'combine -- combine grouplens scores with gnus scores |
189 'separate -- treat grouplens scores completely separate from gnus") | 182 'separate -- treat grouplens scores completely separate from gnus") |
190 | 183 |
191 | 184 |
192 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 185 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
193 ;;;; Program global variables | 186 ;;;; Program global variables |
194 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 187 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
195 (defvar grouplens-bbb-token nil | 188 (defvar grouplens-bbb-token "0" |
196 "Current session token number") | 189 "Current session token number") |
197 | 190 |
198 (defvar grouplens-bbb-process nil | 191 (defvar grouplens-bbb-process nil |
199 "Process Id of current bbbd network stream process") | 192 "Process Id of current bbbd network stream process") |
200 | 193 |
202 "Buffer associated with the BBBD process") | 195 "Buffer associated with the BBBD process") |
203 | 196 |
204 (defvar grouplens-rating-alist nil | 197 (defvar grouplens-rating-alist nil |
205 "Current set of message-id rating pairs") | 198 "Current set of message-id rating pairs") |
206 | 199 |
207 (defvar grouplens-current-hashtable nil | 200 (defvar grouplens-current-hashtable (make-hash-table :test 'equal :size 100)) |
208 "A hashtable to hold predictions from the BBB") | 201 ;; this seems like a pretty ugly way to get around the problem, but If |
202 ;; I don't do this, then the compiler complains when I call gethash | |
203 ;; | |
204 (eval-when-compile (setq grouplens-current-hashtable | |
205 (make-hash-table :test 'equal :size 100))) | |
209 | 206 |
210 (defvar grouplens-current-group nil) | 207 (defvar grouplens-current-group nil) |
211 | 208 |
212 ;;(defvar bbb-alist nil) | 209 (defvar bbb-mid-list nil) |
210 | |
211 (defvar bbb-alist nil) | |
213 | 212 |
214 (defvar bbb-timeout-secs 10 | 213 (defvar bbb-timeout-secs 10 |
215 "Number of seconds to wait for some response from the BBB. | 214 "Number of seconds to wait for some response from the BBB. |
216 If this times out we give up and assume that something has died..." ) | 215 If this times out we give up and assume that something has died..." ) |
217 | 216 |
219 "Message-ID of the last article read.") | 218 "Message-ID of the last article read.") |
220 | 219 |
221 (defvar bbb-read-point) | 220 (defvar bbb-read-point) |
222 (defvar bbb-response-point) | 221 (defvar bbb-response-point) |
223 | 222 |
224 (defun bbb-renew-hash-table () | |
225 (setq grouplens-current-hashtable (make-vector 100 0))) | |
226 | |
227 (bbb-renew-hash-table) | |
228 | |
229 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 223 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
230 ;;;; Utility Functions | 224 ;;;; Utility Functions |
231 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 225 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
232 | |
233 (defun bbb-connect-to-bbbd (host port) | 226 (defun bbb-connect-to-bbbd (host port) |
234 (unless grouplens-bbb-buffer | 227 (unless grouplens-bbb-buffer |
235 (setq grouplens-bbb-buffer | 228 (setq grouplens-bbb-buffer |
236 (get-buffer-create (format " *BBBD trace: %s*" host))) | 229 (get-buffer-create (format " *BBBD trace: %s*" host))) |
237 (save-excursion | 230 (save-excursion |
238 (set-buffer grouplens-bbb-buffer) | 231 (set-buffer grouplens-bbb-buffer) |
239 (make-local-variable 'bbb-read-point) | 232 (make-local-variable 'bbb-read-point) |
240 (make-local-variable 'bbb-response-point) | |
241 (setq bbb-read-point (point-min)))) | 233 (setq bbb-read-point (point-min)))) |
242 | |
243 ;; if an old process is still running for some reason, kill it | |
244 (when grouplens-bbb-process | |
245 (ignore-errors | |
246 (when (eq 'open (process-status grouplens-bbb-process)) | |
247 (set-process-buffer grouplens-bbb-process nil) | |
248 (delete-process grouplens-bbb-process)))) | |
249 | |
250 ;; clear the trace buffer of old output | 234 ;; clear the trace buffer of old output |
251 (save-excursion | 235 (save-excursion |
252 (set-buffer grouplens-bbb-buffer) | 236 (set-buffer grouplens-bbb-buffer) |
253 (erase-buffer)) | 237 (erase-buffer)) |
254 | |
255 ;; open the connection to the server | 238 ;; open the connection to the server |
239 (setq grouplens-bbb-process nil) | |
256 (catch 'done | 240 (catch 'done |
257 (condition-case error | 241 (condition-case error |
258 (setq grouplens-bbb-process | 242 (setq grouplens-bbb-process |
259 (open-network-stream "BBBD" grouplens-bbb-buffer host port)) | 243 (open-network-stream "BBBD" grouplens-bbb-buffer host port)) |
260 (error (gnus-message 3 "Error: Failed to connect to BBB") | 244 (error (gnus-message 3 "Error: Failed to connect to BBB") |
261 nil)) | 245 nil)) |
262 (and (null grouplens-bbb-process) | 246 (and (null grouplens-bbb-process) |
263 (throw 'done nil)) | 247 (throw 'done nil)) |
248 ;; (set-process-filter grouplens-bbb-process 'bbb-process-filter) | |
264 (save-excursion | 249 (save-excursion |
265 (set-buffer grouplens-bbb-buffer) | 250 (set-buffer grouplens-bbb-buffer) |
266 (setq bbb-read-point (point-min)) | 251 (setq bbb-read-point (point-min)) |
267 (or (bbb-read-response grouplens-bbb-process) | 252 (or (bbb-read-response grouplens-bbb-process) |
268 (throw 'done nil)))) | 253 (throw 'done nil)))) |
269 | |
270 ;; return the process | |
271 grouplens-bbb-process) | 254 grouplens-bbb-process) |
255 | |
256 ;; (defun bbb-process-filter (process output) | |
257 ;; (save-excursion | |
258 ;; (set-buffer (bbb-process-buffer process)) | |
259 ;; (goto-char (point-max)) | |
260 ;; (insert output))) | |
272 | 261 |
273 (defun bbb-send-command (process command) | 262 (defun bbb-send-command (process command) |
274 (goto-char (point-max)) | 263 (goto-char (point-max)) |
275 (insert command) | 264 (insert command) |
276 (insert "\r\n") | 265 (insert "\r\n") |
277 (setq bbb-read-point (point)) | 266 (setq bbb-read-point (point)) |
278 (setq bbb-response-point (point)) | 267 (setq bbb-response-point (point)) |
279 (set-marker (process-mark process) (point)) ; process output also comes here | 268 (set-marker (process-mark process) (point)) ; process output also comes here |
280 (process-send-string process command) | 269 (process-send-string process command) |
281 (process-send-string process "\r\n") | 270 (process-send-string process "\r\n")) |
282 (process-send-eof process)) | 271 |
283 | 272 (defun bbb-read-response (process) ; &optional return-response-string) |
284 (defun bbb-read-response (process) | |
285 "This function eats the initial response of OK or ERROR from the BBB." | 273 "This function eats the initial response of OK or ERROR from the BBB." |
286 (let ((case-fold-search nil) | 274 (let ((case-fold-search nil) |
287 match-end) | 275 match-end) |
288 (goto-char bbb-read-point) | 276 (goto-char bbb-read-point) |
289 (while (and (not (search-forward "\r\n" nil t)) | 277 (while (and (not (search-forward "\r\n" nil t)) |
290 (accept-process-output process bbb-timeout-secs)) | 278 (accept-process-output process bbb-timeout-secs)) |
291 (goto-char bbb-read-point)) | 279 (goto-char bbb-read-point)) |
292 (setq match-end (point)) | 280 (setq match-end (point)) |
300 (defun bbb-login () | 288 (defun bbb-login () |
301 "return the token number if login is successful, otherwise return nil" | 289 "return the token number if login is successful, otherwise return nil" |
302 (interactive) | 290 (interactive) |
303 (setq grouplens-bbb-token nil) | 291 (setq grouplens-bbb-token nil) |
304 (if (not (equal grouplens-pseudonym "")) | 292 (if (not (equal grouplens-pseudonym "")) |
305 (let ((bbb-process | 293 (let ((bbb-process |
306 (bbb-connect-to-bbbd grouplens-bbb-host grouplens-bbb-port))) | 294 (bbb-connect-to-bbbd grouplens-bbb-host grouplens-bbb-port))) |
307 (if bbb-process | 295 (if bbb-process |
308 (save-excursion | 296 (save-excursion |
309 (set-buffer (process-buffer bbb-process)) | 297 (set-buffer (process-buffer bbb-process)) |
310 (bbb-send-command bbb-process | 298 (bbb-send-command bbb-process |
311 (concat "login " grouplens-pseudonym)) | 299 (concat "login " grouplens-pseudonym)) |
312 (if (bbb-read-response bbb-process) | 300 (if (bbb-read-response bbb-process) |
313 (setq grouplens-bbb-token (bbb-extract-token-number)) | 301 (setq grouplens-bbb-token (bbb-extract-token-number)) |
314 (gnus-message 3 "Error: GroupLens login failed"))))) | 302 (gnus-message 3 "Error: Grouplens login failed"))))) |
315 (gnus-message 3 "Error: you must set a pseudonym")) | 303 (gnus-message 3 "Error: you must set a pseudonym")) |
316 grouplens-bbb-token) | 304 grouplens-bbb-token) |
317 | 305 |
318 (defun bbb-extract-token-number () | 306 (defun bbb-extract-token-number () |
319 (let ((token-pos (search-forward "token=" nil t))) | 307 (let ((token-pos (search-forward "token=" nil t) )) |
320 (when (looking-at "[0-9]+") | 308 (if (looking-at "[0-9]+") |
321 (buffer-substring token-pos (match-end 0))))) | 309 (buffer-substring token-pos (match-end 0))))) |
322 | 310 |
323 (gnus-add-shutdown 'bbb-logout 'gnus) | 311 (gnus-add-shutdown 'bbb-logout 'gnus) |
324 | 312 |
325 (defun bbb-logout () | 313 (defun bbb-logout () |
326 "logout of bbb session" | 314 "logout of bbb session" |
327 (when grouplens-bbb-token | 315 (let ((bbb-process |
328 (let ((bbb-process | 316 (bbb-connect-to-bbbd grouplens-bbb-host grouplens-bbb-port))) |
329 (bbb-connect-to-bbbd grouplens-bbb-host grouplens-bbb-port))) | 317 (if bbb-process |
330 (when bbb-process | 318 (save-excursion |
331 (save-excursion | |
332 (set-buffer (process-buffer bbb-process)) | 319 (set-buffer (process-buffer bbb-process)) |
333 (bbb-send-command bbb-process (concat "logout " grouplens-bbb-token)) | 320 (bbb-send-command bbb-process (concat "logout " grouplens-bbb-token)) |
334 (bbb-read-response bbb-process)))))) | 321 (bbb-read-response bbb-process)) |
322 nil))) | |
335 | 323 |
336 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 324 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
337 ;;;; Get Predictions | 325 ;;;; Get Predictions |
338 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 326 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
339 | 327 |
340 (defun bbb-build-mid-scores-alist (groupname) | 328 (defun bbb-build-mid-scores-alist (groupname) |
341 "this function can be called as part of the function to return the | 329 "this function can be called as part of the function to return the |
342 list of score files to use. See the gnus variable | 330 list of score files to use. See the gnus variable |
343 gnus-score-find-score-files-function. | 331 gnus-score-find-score-files-function. |
344 | 332 |
345 *Note:* If you want to use grouplens scores along with calculated scores, | 333 *Note:* If you want to use grouplens scores along with calculated scores, |
346 you should see the offset and scale variables. At this point, I don't | 334 you should see the offset and scale variables. At this point, I don't |
347 recommend using both scores and grouplens predictions together." | 335 recommend using both scores and grouplens predictions together." |
348 (setq grouplens-current-group groupname) | 336 (setq grouplens-current-group groupname) |
349 (when (member groupname grouplens-newsgroups) | 337 (if (member groupname grouplens-newsgroups) |
350 (setq grouplens-previous-article nil) | 338 (let* ((mid-list (bbb-get-all-mids)) |
351 ;; scores-alist should be a list of lists: | 339 (predict-list (bbb-get-predictions mid-list groupname))) |
352 ;; ((("message-id" ("<mid1>" score1 nil s) ("<mid2> score2 nil s)))) | 340 (setq grouplens-previous-article nil) |
353 ;;`((("message-id" . ,predict-list))) ; Yes, this is the return value | 341 ;; scores-alist should be a list of lists: |
354 (list | 342 ;; ((("message-id" ("<mid1>" score1 nil s) ("<mid2> score2 nil s)))) |
355 (list | 343 ;;`((("message-id" . ,predict-list))) ; Yes, this is the return value |
356 (list (append (list "message-id") | 344 (list (list (list (append (list "message-id") predict-list))))) |
357 (bbb-get-predictions (bbb-get-all-mids) groupname))))))) | 345 nil)) |
358 | 346 |
359 (defun bbb-get-predictions (midlist groupname) | 347 (defun bbb-get-predictions (midlist groupname) |
360 "Ask the bbb for predictions, and build up the score alist." | 348 "Ask the bbb for predictions, and build up the score alist." |
361 (gnus-message 5 "Fetching Predictions...") | 349 (if (or (null grouplens-bbb-token) |
362 (if grouplens-bbb-token | 350 (equal grouplens-bbb-token "0")) |
363 (let ((bbb-process (bbb-connect-to-bbbd grouplens-bbb-host | 351 (progn |
364 grouplens-bbb-port))) | 352 (gnus-message 3 "Error: You are not logged in to a BBB") |
365 (when bbb-process | 353 nil) |
366 (save-excursion | 354 (gnus-message 5 "Fetching Predictions...") |
355 (let (predict-list | |
356 (predict-command (bbb-build-predict-command midlist groupname | |
357 grouplens-bbb-token)) | |
358 (bbb-process (bbb-connect-to-bbbd grouplens-bbb-host | |
359 grouplens-bbb-port))) | |
360 (if bbb-process | |
361 (save-excursion | |
367 (set-buffer (process-buffer bbb-process)) | 362 (set-buffer (process-buffer bbb-process)) |
368 (bbb-send-command bbb-process | 363 (bbb-send-command bbb-process predict-command) |
369 (bbb-build-predict-command midlist groupname | |
370 grouplens-bbb-token)) | |
371 (if (bbb-read-response bbb-process) | 364 (if (bbb-read-response bbb-process) |
372 (bbb-get-prediction-response bbb-process) | 365 (setq predict-list (bbb-get-prediction-response bbb-process)) |
373 (gnus-message 1 "Invalid Token, login and try again") | 366 (gnus-message 1 "Invalid Token, login and try again") |
374 (ding))))) | 367 (ding)))) |
375 (gnus-message 3 "Error: You are not logged in to a BBB") | 368 (setq bbb-alist predict-list)))) |
376 (ding))) | |
377 | 369 |
378 (defun bbb-get-all-mids () | 370 (defun bbb-get-all-mids () |
379 (mapcar (function (lambda (x) (mail-header-id x))) gnus-newsgroup-headers)) | 371 (let ((index (nth 1 (assoc "message-id" gnus-header-index))) |
372 (articles gnus-newsgroup-headers) | |
373 art this) | |
374 (setq bbb-mid-list nil) | |
375 (while articles | |
376 (progn (setq art (car articles) | |
377 this (aref art index) | |
378 articles (cdr articles)) | |
379 (setq bbb-mid-list (cons this bbb-mid-list)))) | |
380 bbb-mid-list)) | |
380 | 381 |
381 (defun bbb-build-predict-command (mlist grpname token) | 382 (defun bbb-build-predict-command (mlist grpname token) |
382 (concat "getpredictions " token " " grpname "\r\n" | 383 (let ((cmd (concat "getpredictions " token " " grpname "\r\n")) |
383 (mapconcat 'identity mlist "\r\n") "\r\n.\r\n")) | 384 art) |
385 (while mlist | |
386 (setq art (car mlist) | |
387 cmd (concat cmd art "\r\n") | |
388 mlist (cdr mlist))) | |
389 (setq cmd (concat cmd ".\r\n")) | |
390 cmd)) | |
384 | 391 |
385 (defun bbb-get-prediction-response (process) | 392 (defun bbb-get-prediction-response (process) |
386 (let ((case-fold-search nil)) | 393 (let ((case-fold-search nil) |
394 match-end) | |
387 (goto-char bbb-read-point) | 395 (goto-char bbb-read-point) |
388 (while (and (not (search-forward ".\r\n" nil t)) | 396 (while (and (not (search-forward ".\r\n" nil t)) |
389 (accept-process-output process bbb-timeout-secs)) | 397 (accept-process-output process bbb-timeout-secs)) |
390 (goto-char bbb-read-point)) | 398 (goto-char bbb-read-point)) |
391 (goto-char (+ bbb-response-point 4));; we ought to be right before OK | 399 (setq match-end (point)) |
400 (goto-char (+ bbb-response-point 4)) ;; we ought to be right before OK | |
392 (bbb-build-response-alist))) | 401 (bbb-build-response-alist))) |
393 | 402 |
394 ;; build-response-alist assumes that the cursor has been positioned at | 403 ;; build-response-alist assumes that the cursor has been positioned at |
395 ;; the first line of the list of mid/rating pairs. | 404 ;; the first line of the list of mid/rating pairs. For now we will |
405 ;; use a prediction of 99 to signify no prediction. Ultimately, we | |
406 ;; should just ignore messages with no predictions. | |
396 (defun bbb-build-response-alist () | 407 (defun bbb-build-response-alist () |
397 (let (resp mid pred) | 408 (let ((resp nil) |
409 (match-end (point))) | |
410 (setq grouplens-current-hashtable (make-hash-table :test 'equal :size 100)) | |
398 (while | 411 (while |
399 (cond | 412 (cond ((looking-at "\\(<.*>\\) :nopred=") |
400 ((looking-at "\\(<.*>\\) :nopred=") | 413 (push `(,(bbb-get-mid) ,gnus-summary-default-score nil s) resp) |
401 ;;(push `(,(bbb-get-mid) ,gnus-summary-default-score nil s) resp) | 414 (forward-line 1) |
402 (forward-line 1) | 415 t) |
403 t) | 416 ((looking-at "\\(<.*>\\) :pred=\\([0-9]\.[0-9][0-9]\\) :conflow=\\([0-9]\.[0-9][0-9]\\) :confhigh=\\([0-9]\.[0-9][0-9]\\)") |
404 ((looking-at "\\(<.*>\\) :pred=\\([0-9]\.[0-9][0-9]\\) :conflow=\\([0-9]\.[0-9][0-9]\\) :confhigh=\\([0-9]\.[0-9][0-9]\\)") | 417 (push `(,(bbb-get-mid) ,(bbb-get-pred) nil s) resp) |
405 (setq mid (bbb-get-mid) | 418 (cl-puthash (bbb-get-mid) |
406 pred (bbb-get-pred)) | 419 (list (bbb-get-pred) (bbb-get-confl) (bbb-get-confh)) |
407 (push `(,mid ,pred nil s) resp) | 420 grouplens-current-hashtable) |
408 (gnus-sethash mid (list pred (bbb-get-confl) (bbb-get-confh)) | 421 (forward-line 1) |
409 grouplens-current-hashtable) | 422 t) |
410 (forward-line 1) | 423 ((looking-at "\\(<.*>\\) :pred=\\([0-9]\.[0-9][0-9]\\)") |
411 t) | 424 (push `(,(bbb-get-mid) ,(bbb-get-pred) nil s) resp) |
412 ((looking-at "\\(<.*>\\) :pred=\\([0-9]\.[0-9][0-9]\\)") | 425 (cl-puthash (bbb-get-mid) |
413 (setq mid (bbb-get-mid) | 426 (list (bbb-get-pred) 0 0) |
414 pred (bbb-get-pred)) | 427 grouplens-current-hashtable) |
415 (push `(,mid ,pred nil s) resp) | 428 (forward-line 1) |
416 (gnus-sethash mid (list pred 0 0) grouplens-current-hashtable) | 429 t) |
417 (forward-line 1) | 430 (t nil))) |
418 t) | |
419 (t nil))) | |
420 resp)) | 431 resp)) |
421 | 432 |
422 ;; these "get" functions assume that there is an active match lying | 433 ;; these two functions assume that there is an active match lying |
423 ;; around. Where the first parenthesized expression is the | 434 ;; around. Where the first parenthesized expression is the |
424 ;; message-id, and the second is the prediction, the third and fourth | 435 ;; message-id, and the second is the prediction. Since gnus assumes |
425 ;; are the confidence interval | 436 ;; that scores are integer values?? we round the prediction. |
426 ;; | |
427 ;; Since gnus assumes that scores are integer values?? we round the | |
428 ;; prediction. | |
429 (defun bbb-get-mid () | 437 (defun bbb-get-mid () |
430 (buffer-substring (match-beginning 1) (match-end 1))) | 438 (buffer-substring (match-beginning 1) (match-end 1))) |
431 | 439 |
432 (defun bbb-get-pred () | 440 (defun bbb-get-pred () |
433 (let ((tpred (string-to-number (buffer-substring (match-beginning 2) | 441 (let ((tpred (string-to-number (buffer-substring |
434 (match-end 2))))) | 442 (match-beginning 2) |
443 (match-end 2))))) | |
435 (if (> tpred 0) | 444 (if (> tpred 0) |
436 (round (* grouplens-score-scale-factor | 445 (round (* grouplens-score-scale-factor (+ grouplens-score-offset tpred))) |
437 (+ grouplens-score-offset tpred))) | |
438 1))) | 446 1))) |
439 | 447 |
440 (defun bbb-get-confl () | 448 (defun bbb-get-confl () |
441 (string-to-number (buffer-substring (match-beginning 4) (match-end 4)))) | 449 (string-to-number (buffer-substring (match-beginning 3) (match-end 3)))) |
442 | 450 |
443 (defun bbb-get-confh () | 451 (defun bbb-get-confh () |
444 (string-to-number (buffer-substring (match-beginning 4) (match-end 4)))) | 452 (string-to-number (buffer-substring (match-beginning 4) (match-end 4)))) |
445 | 453 |
446 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 454 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
453 | 461 |
454 (defvar gnus-tmp-score) | 462 (defvar gnus-tmp-score) |
455 (defun bbb-grouplens-score (header) | 463 (defun bbb-grouplens-score (header) |
456 (if (eq gnus-grouplens-override-scoring 'separate) | 464 (if (eq gnus-grouplens-override-scoring 'separate) |
457 (bbb-grouplens-other-score header) | 465 (bbb-grouplens-other-score header) |
458 (let* ((rate-string (make-string 12 ?\ )) | 466 (let* ((rate-string (make-string 12 ? )) |
459 (mid (mail-header-id header)) | 467 (mid (aref header (nth 1 (assoc "message-id" gnus-header-index)))) |
460 (hashent (gnus-gethash mid grouplens-current-hashtable)) | 468 (hashent (gethash mid grouplens-current-hashtable)) |
461 (iscore gnus-tmp-score) | 469 (iscore gnus-tmp-score) |
462 (low (car (cdr hashent))) | 470 (low (car (cdr hashent))) |
463 (high (car (cdr (cdr hashent))))) | 471 (high (car (cdr (cdr hashent))))) |
464 (aset rate-string 0 ?|) | 472 (aset rate-string 0 ?|) |
465 (aset rate-string 11 ?|) | 473 (aset rate-string 11 ?|) |
466 (unless (member grouplens-current-group grouplens-newsgroups) | 474 (unless (member grouplens-current-group grouplens-newsgroups) |
467 (unless (equal grouplens-prediction-display 'prediction-num) | 475 (unless (equal grouplens-prediction-display 'prediction-num) |
468 (cond ((< iscore 0) | 476 (cond ((< iscore 0) |
469 (setq iscore 1)) | 477 (setq iscore 1)) |
470 ((> iscore 5) | 478 ((> iscore 5) |
471 (setq iscore 5)))) | 479 (setq iscore 5)))) |
472 (setq low 0) | 480 (setq low 0) |
473 (setq high 0)) | 481 (setq high 0)) |
474 (if (and (bbb-valid-score iscore) | 482 (if (and (bbb-valid-score iscore) |
475 (not (null mid))) | 483 (not (null mid))) |
476 (cond | 484 (cond |
477 ;; prediction-spot | 485 ;; prediction-spot |
478 ((equal grouplens-prediction-display 'prediction-spot) | 486 ((equal grouplens-prediction-display 'prediction-spot) |
479 (setq rate-string (bbb-fmt-prediction-spot rate-string iscore))) | 487 (setq rate-string (bbb-fmt-prediction-spot rate-string iscore))) |
480 ;; confidence-interval | 488 ;; confidence-interval |
481 ((equal grouplens-prediction-display 'confidence-interval) | 489 ((equal grouplens-prediction-display 'confidence-interval) |
498 ) | 506 ) |
499 (t (gnus-message 3 "Invalid prediction display type"))) | 507 (t (gnus-message 3 "Invalid prediction display type"))) |
500 (aset rate-string 5 ?N) (aset rate-string 6 ?A)) | 508 (aset rate-string 5 ?N) (aset rate-string 6 ?A)) |
501 rate-string))) | 509 rate-string))) |
502 | 510 |
511 ;; | |
503 ;; Gnus user format function that doesn't depend on | 512 ;; Gnus user format function that doesn't depend on |
504 ;; bbb-build-mid-scores-alist being used as the score function, but is | 513 ;; bbb-build-mid-scores-alist being used as the score function, but is |
505 ;; instead called from gnus-select-group-hook. -- LAB | 514 ;; instead called from gnus-select-group-hook. -- LAB |
506 (defun bbb-grouplens-other-score (header) | 515 (defun bbb-grouplens-other-score (header) |
507 (if (not (member grouplens-current-group grouplens-newsgroups)) | 516 (if (not (member grouplens-current-group grouplens-newsgroups)) |
508 ;; Return an empty string | 517 ;; Return an empty string |
509 "" | 518 "" |
510 (let* ((rate-string (make-string 12 ?\ )) | 519 (let* ((rate-string (make-string 12 ? )) |
511 (mid (mail-header-id header)) | 520 (mid (aref header (nth 1 (assoc "message-id" gnus-header-index)))) |
512 (hashent (gnus-gethash mid grouplens-current-hashtable)) | 521 (hashent (gethash mid grouplens-current-hashtable)) |
513 (pred (or (nth 0 hashent) 0)) | 522 (pred (or (nth 0 hashent) 0)) |
514 (low (nth 1 hashent)) | 523 (low (nth 1 hashent)) |
515 (high (nth 2 hashent))) | 524 (high (nth 2 hashent))) |
516 ;; Init rate-string | 525 ;; Init rate-string |
517 (aset rate-string 0 ?|) | 526 (aset rate-string 0 ?|) |
518 (aset rate-string 11 ?|) | 527 (aset rate-string 11 ?|) |
519 (unless (equal grouplens-prediction-display 'prediction-num) | 528 (unless (equal grouplens-prediction-display 'prediction-num) |
520 (cond ((< pred 0) | 529 (cond ((< pred 0) |
521 (setq pred 1)) | 530 (setq pred 1)) |
522 ((> pred 5) | 531 ((> pred 5) |
523 (setq pred 5)))) | 532 (setq pred 5)))) |
524 ;; If no entry in BBB hash mark rate string as NA and return | 533 ;; If no entry in BBB hash mark rate string as NA and return |
525 (cond | 534 (cond |
526 ((null hashent) | 535 ((null hashent) |
527 (aset rate-string 5 ?N) | 536 (aset rate-string 5 ?N) |
528 (aset rate-string 6 ?A) | 537 (aset rate-string 6 ?A) |
529 rate-string) | 538 rate-string) |
530 | 539 |
531 ((equal grouplens-prediction-display 'prediction-spot) | 540 ((equal grouplens-prediction-display 'prediction-spot) |
532 (bbb-fmt-prediction-spot rate-string pred)) | 541 (bbb-fmt-prediction-spot rate-string pred)) |
533 | 542 |
534 ((equal grouplens-prediction-display 'confidence-interval) | 543 ((equal grouplens-prediction-display 'confidence-interval) |
535 (bbb-fmt-confidence-interval pred low high)) | 544 (bbb-fmt-confidence-interval pred low high)) |
536 | 545 |
537 ((equal grouplens-prediction-display 'prediction-bar) | 546 ((equal grouplens-prediction-display 'prediction-bar) |
538 (bbb-fmt-prediction-bar rate-string pred)) | 547 (bbb-fmt-prediction-bar rate-string pred)) |
539 | 548 |
540 ((equal grouplens-prediction-display 'confidence-bar) | 549 ((equal grouplens-prediction-display 'confidence-bar) |
541 (format "| %4.2f |" pred)) | 550 (format "| %4.2f |" pred)) |
542 | 551 |
543 ((equal grouplens-prediction-display 'confidence-spot) | 552 ((equal grouplens-prediction-display 'confidence-spot) |
544 (format "| %4.2f |" pred)) | 553 (format "| %4.2f |" pred)) |
545 | 554 |
546 ((equal grouplens-prediction-display 'prediction-num) | 555 ((equal grouplens-prediction-display 'prediction-num) |
547 (bbb-fmt-prediction-num pred)) | 556 (bbb-fmt-prediction-num pred)) |
548 | 557 |
549 ((equal grouplens-prediction-display 'confidence-plus-minus) | 558 ((equal grouplens-prediction-display 'confidence-plus-minus) |
550 (bbb-fmt-confidence-plus-minus pred low high)) | 559 (bbb-fmt-confidence-plus-minus pred low high)) |
551 | 560 |
552 (t | 561 (t |
553 (gnus-message 3 "Invalid prediction display type") | 562 (gnus-message 3 "Invalid prediction display type") |
554 (aset rate-string 0 ?|) | 563 (aset rate-string 0 ?|) |
555 (aset rate-string 11 ?|) | 564 (aset rate-string 11 ?|) |
556 rate-string))))) | 565 rate-string))))) |
557 | 566 |
558 (defun bbb-valid-score (score) | 567 (defun bbb-valid-score (score) |
559 (or (equal grouplens-prediction-display 'prediction-num) | 568 (or (equal grouplens-prediction-display 'prediction-num) |
585 (if (bbb-have-confidence low high) | 594 (if (bbb-have-confidence low high) |
586 (format "|%3.1f+/-%4.2f|" score (/ (- high low) 2.0)) | 595 (format "|%3.1f+/-%4.2f|" score (/ (- high low) 2.0)) |
587 (bbb-fmt-prediction-num score))) | 596 (bbb-fmt-prediction-num score))) |
588 | 597 |
589 (defun bbb-fmt-prediction-bar (rate-string score) | 598 (defun bbb-fmt-prediction-bar (rate-string score) |
590 (let* ((i 1) | 599 (let* ((i 1) |
591 (step (/ grplens-rating-range (- grplens-predstringsize 4))) | 600 (step (/ grplens-rating-range (- grplens-predstringsize 4))) |
592 (half-step (/ step 2)) | 601 (half-step (/ step 2)) |
593 (loc (- grplens-minrating half-step))) | 602 (loc (- grplens-minrating half-step))) |
594 (while (< i (- grplens-predstringsize 2)) | 603 (while (< i (- grplens-predstringsize 2)) |
595 (if (> score loc) | 604 (if (> score loc) |
596 (aset rate-string i ?#) | 605 (aset rate-string i ?#) |
597 (aset rate-string i ?\ )) | 606 (aset rate-string i ? )) |
598 (setq i (+ i 1)) | 607 (setq i (+ i 1)) |
599 (setq loc (+ loc step))) | 608 (setq loc (+ loc step))) |
600 ) | 609 ) |
601 rate-string) | 610 rate-string) |
602 | 611 |
605 | 614 |
606 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 615 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
607 ;;;; Put Ratings | 616 ;;;; Put Ratings |
608 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 617 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
609 | 618 |
619 ;; The message-id for the current article can be found in | |
620 ;; (aref gnus-current-headers (nth 1 (assoc "message-id" gnus-header-index))) | |
621 | |
610 (defun bbb-put-ratings () | 622 (defun bbb-put-ratings () |
611 (if (and grouplens-bbb-token | 623 (if (and grouplens-rating-alist |
612 grouplens-rating-alist | |
613 (member gnus-newsgroup-name grouplens-newsgroups)) | 624 (member gnus-newsgroup-name grouplens-newsgroups)) |
614 (let ((bbb-process (bbb-connect-to-bbbd grouplens-bbb-host | 625 (let ((bbb-process (bbb-connect-to-bbbd grouplens-bbb-host |
615 grouplens-bbb-port)) | 626 grouplens-bbb-port)) |
616 (rate-command (bbb-build-rate-command grouplens-rating-alist))) | 627 (rate-command (bbb-build-rate-command grouplens-rating-alist))) |
617 (if bbb-process | 628 (if bbb-process |
618 (save-excursion | 629 (save-excursion |
619 (set-buffer (process-buffer bbb-process)) | 630 (set-buffer (process-buffer bbb-process)) |
620 (gnus-message 5 "Sending Ratings...") | 631 (gnus-message 5 "Sending Ratings...") |
621 (bbb-send-command bbb-process rate-command) | 632 (bbb-send-command bbb-process rate-command) |
622 (if (bbb-read-response bbb-process) | 633 (if (bbb-read-response bbb-process) |
623 (setq grouplens-rating-alist nil) | 634 (setq grouplens-rating-alist nil) |
624 (gnus-message 1 | 635 (gnus-message 1 |
625 "Token timed out: call bbb-login and quit again") | 636 "Token timed out: call bbb-login and quit again") |
626 (ding)) | 637 (ding)) |
627 (gnus-message 5 "Sending Ratings...Done")) | 638 (gnus-message 5 "Sending Ratings...Done")) |
628 (gnus-message 3 "No BBB connection"))) | 639 (gnus-message 3 "No BBB connection"))) |
629 (setq grouplens-rating-alist nil))) | 640 (setq grouplens-rating-alist nil))) |
630 | 641 |
631 (defun bbb-build-rate-command (rate-alist) | 642 (defun bbb-build-rate-command (rate-alist) |
632 (concat "putratings " grouplens-bbb-token " " grouplens-current-group " \r\n" | 643 (let (this |
633 (mapconcat '(lambda (this) ; form (mid . (score . time)) | 644 (cmd (concat "putratings " grouplens-bbb-token |
634 (concat (car this) | 645 " " grouplens-current-group " \r\n"))) |
635 " :rating=" (cadr this) ".00" | 646 (while rate-alist |
636 " :time=" (cddr this))) | 647 (setq this (car rate-alist) |
637 rate-alist "\r\n") | 648 cmd (concat cmd (car this) " :rating=" (cadr this) ".00" |
638 "\r\n.\r\n")) | 649 " :time=" (cddr this) "\r\n") |
650 rate-alist (cdr rate-alist))) | |
651 (concat cmd ".\r\n"))) | |
639 | 652 |
640 ;; Interactive rating functions. | 653 ;; Interactive rating functions. |
641 (defun bbb-summary-rate-article (rating &optional midin) | 654 (defun bbb-summary-rate-article (rating &optional midin) |
642 (interactive "nRating: ") | 655 (interactive "nRating: ") |
643 (when (member gnus-newsgroup-name grouplens-newsgroups) | 656 (when (member gnus-newsgroup-name grouplens-newsgroups) |
644 (let ((mid (or midin (bbb-get-current-id)))) | 657 (let ((mid (or midin (bbb-get-current-id)))) |
645 (if (and rating | 658 (if (and rating |
646 (>= rating grplens-minrating) | 659 (>= rating grplens-minrating) |
647 (<= rating grplens-maxrating) | 660 (<= rating grplens-maxrating) |
648 mid) | 661 mid) |
649 (let ((oldrating (assoc mid grouplens-rating-alist))) | 662 (let ((oldrating (assoc mid grouplens-rating-alist))) |
650 (if oldrating | 663 (if oldrating |
651 (setcdr oldrating (cons rating 0)) | 664 (setcdr oldrating (cons rating 0)) |
652 (push `(,mid . (,rating . 0)) grouplens-rating-alist)) | 665 (push `(,mid . (,rating . 0)) grouplens-rating-alist)) |
653 (gnus-summary-mark-article nil (int-to-string rating))) | 666 (gnus-summary-mark-article nil (int-to-string rating))) |
654 (gnus-message 3 "Invalid rating"))))) | 667 (gnus-message 3 "Invalid rating"))))) |
655 | 668 |
656 (defun grouplens-next-unread-article (rating) | 669 (defun grouplens-next-unread-article (rating) |
657 "Select unread article after current one." | 670 "Select unread article after current one." |
658 (interactive "P") | 671 (interactive "P") |
659 (when rating | 672 (if rating (bbb-summary-rate-article rating)) |
660 (bbb-summary-rate-article rating)) | |
661 (gnus-summary-next-unread-article)) | 673 (gnus-summary-next-unread-article)) |
662 | 674 |
663 (defun grouplens-best-unread-article (rating) | 675 (defun grouplens-best-unread-article (rating) |
664 "Select unread article after current one." | 676 "Select unread article after current one." |
665 (interactive "P") | 677 (interactive "P") |
666 (when rating | 678 (if rating (bbb-summary-rate-article rating)) |
667 (bbb-summary-rate-article rating)) | |
668 (gnus-summary-best-unread-article)) | 679 (gnus-summary-best-unread-article)) |
669 | 680 |
670 (defun grouplens-summary-catchup-and-exit (rating) | 681 (defun grouplens-summary-catchup-and-exit (rating) |
671 "Mark all articles not marked as unread in this newsgroup as read, | 682 "Mark all articles not marked as unread in this newsgroup as read, |
672 then exit. If prefix argument ALL is non-nil, all articles are | 683 then exit. If prefix argument ALL is non-nil, all articles are |
673 marked as read." | 684 marked as read." |
674 (interactive "P") | 685 (interactive "P") |
675 (when rating | 686 (if rating |
676 (bbb-summary-rate-article rating)) | 687 (bbb-summary-rate-article rating)) |
677 (if (numberp rating) | 688 (if (numberp rating) |
678 (gnus-summary-catchup-and-exit) | 689 (gnus-summary-catchup-and-exit) |
679 (gnus-summary-catchup-and-exit rating))) | 690 (gnus-summary-catchup-and-exit rating))) |
680 | 691 |
681 (defun grouplens-score-thread (score) | 692 (defun grouplens-score-thread (score) |
682 "Raise the score of the articles in the current thread with SCORE." | 693 "Raise the score of the articles in the current thread with SCORE." |
683 (interactive "nRating: ") | 694 (interactive "nRating: ") |
684 (let (e) | 695 (let (e) |
685 (save-excursion | 696 (save-excursion |
686 (let ((articles (gnus-summary-articles-in-thread)) | 697 (let ((articles (gnus-summary-articles-in-thread))) |
687 article) | 698 (while articles |
688 (while (setq article (pop articles)) | 699 (gnus-summary-goto-subject (car articles)) |
689 (gnus-summary-goto-subject article) | |
690 (gnus-set-global-variables) | 700 (gnus-set-global-variables) |
691 (bbb-summary-rate-article score | 701 (bbb-summary-rate-article score |
692 (mail-header-id | 702 (mail-header-id |
693 (gnus-summary-article-header article))))) | 703 (gnus-summary-article-header |
704 (car articles)))) | |
705 (setq articles (cdr articles)))) | |
694 (setq e (point))) | 706 (setq e (point))) |
695 (let ((gnus-summary-check-current t)) | 707 (let ((gnus-summary-check-current t)) |
696 (or (zerop (gnus-summary-next-subject 1 t)) | 708 (or (zerop (gnus-summary-next-subject 1 t)) |
697 (goto-char e)))) | 709 (goto-char e)))) |
698 (gnus-summary-recenter) | 710 (gnus-summary-recenter) |
699 (gnus-summary-position-point) | 711 (gnus-summary-position-point) |
700 (gnus-set-mode-line 'summary)) | 712 (gnus-set-mode-line 'summary)) |
701 | 713 |
702 (defun bbb-exit-group () | |
703 (bbb-put-ratings) | |
704 (bbb-renew-hash-table)) | |
705 | 714 |
706 (defun bbb-get-current-id () | 715 (defun bbb-get-current-id () |
707 (if gnus-current-headers | 716 (if gnus-current-headers |
708 (mail-header-id gnus-current-headers) | 717 (aref gnus-current-headers |
718 (nth 1 (assoc "message-id" gnus-header-index))) | |
709 (gnus-message 3 "You must select an article before you rate it"))) | 719 (gnus-message 3 "You must select an article before you rate it"))) |
710 | 720 |
711 (defun bbb-grouplens-group-p (group) | 721 (defun bbb-grouplens-group-p (group) |
712 "Say whether GROUP is a GroupLens group." | 722 "Say whether GROUP is a GroupLens group." |
713 (if (member group grouplens-newsgroups) " (GroupLens Enhanced)" "")) | 723 (if (member group grouplens-newsgroups) " (GroupLens Enhanced)" "")) |
723 (defun grouplens-elapsed-time () | 733 (defun grouplens-elapsed-time () |
724 (let ((et (bbb-time-float (current-time)))) | 734 (let ((et (bbb-time-float (current-time)))) |
725 (- et (bbb-time-float grouplens-current-starting-time)))) | 735 (- et (bbb-time-float grouplens-current-starting-time)))) |
726 | 736 |
727 (defun bbb-time-float (timeval) | 737 (defun bbb-time-float (timeval) |
728 (+ (* (car timeval) 65536) | 738 (+ (* (car timeval) 65536) |
729 (cadr timeval))) | 739 (cadr timeval))) |
730 | 740 |
731 (defun grouplens-do-time () | 741 (defun grouplens-do-time () |
732 (when (member gnus-newsgroup-name grouplens-newsgroups) | 742 (when (member gnus-newsgroup-name grouplens-newsgroups) |
733 (when grouplens-previous-article | 743 (when grouplens-previous-article |
734 (let ((elapsed-time (grouplens-elapsed-time)) | 744 (let ((elapsed-time (grouplens-elapsed-time)) |
735 (oldrating (assoc grouplens-previous-article | 745 (oldrating (assoc grouplens-previous-article |
736 grouplens-rating-alist))) | 746 grouplens-rating-alist))) |
737 (if (not oldrating) | 747 (if (not oldrating) |
738 (push `(,grouplens-previous-article . (0 . ,elapsed-time)) | 748 (push `(,grouplens-previous-article . (0 . ,elapsed-time)) |
739 grouplens-rating-alist) | 749 grouplens-rating-alist) |
740 (setcdr oldrating (cons (cadr oldrating) elapsed-time))))) | 750 (setcdr oldrating (cons (cadr oldrating) elapsed-time))))) |
743 | 753 |
744 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 754 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
745 ;; BUG REPORTING | 755 ;; BUG REPORTING |
746 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 756 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
747 | 757 |
748 (defconst gnus-gl-version "gnus-gl.el 2.50") | 758 (defconst gnus-gl-version "gnus-gl.el 2.12") |
749 (defconst gnus-gl-maintainer-address "grouplens-bug@cs.umn.edu") | 759 (defconst gnus-gl-maintainer-address "grouplens-bug@cs.umn.edu") |
750 (defun gnus-gl-submit-bug-report () | 760 (defun gnus-gl-submit-bug-report () |
751 "Submit via mail a bug report on gnus-gl" | 761 "Submit via mail a bug report on gnus-gl" |
752 (interactive) | 762 (interactive) |
753 (require 'reporter) | 763 (require 'reporter) |
758 'grouplens-bbb-port | 768 'grouplens-bbb-port |
759 'grouplens-newsgroups | 769 'grouplens-newsgroups |
760 'grouplens-bbb-token | 770 'grouplens-bbb-token |
761 'grouplens-bbb-process | 771 'grouplens-bbb-process |
762 'grouplens-current-group | 772 'grouplens-current-group |
763 'grouplens-previous-article) | 773 'grouplens-previous-article |
774 'grouplens-mid-list | |
775 'bbb-alist) | |
764 nil | 776 nil |
765 'gnus-gl-get-trace)) | 777 'gnus-gl-get-trace)) |
766 | 778 |
767 (defun gnus-gl-get-trace () | 779 (defun gnus-gl-get-trace () |
768 "Insert the contents of the BBBD trace buffer" | 780 "Insert the contents of the BBBD trace buffer" |
769 (when grouplens-bbb-buffer | 781 (if grouplens-bbb-buffer (insert-buffer grouplens-bbb-buffer))) |
770 (insert-buffer grouplens-bbb-buffer))) | 782 |
771 | 783 ;;; |
772 ;; | 784 ;;; Additions to make gnus-grouplens-mode Warning Warning!! |
773 ;; GroupLens minor mode | 785 ;;; This version of the gnus-grouplens-mode does |
774 ;; | 786 ;;; not work with gnus-5.x. The "old" way of |
775 | 787 ;;; setting up GroupLens still works however. |
788 ;;; | |
776 (defvar gnus-grouplens-mode nil | 789 (defvar gnus-grouplens-mode nil |
777 "Minor mode for providing a GroupLens interface in Gnus summary buffers.") | 790 "Minor mode for providing a GroupLens interface in Gnus summary buffers.") |
778 | 791 |
779 (defvar gnus-grouplens-mode-map nil) | 792 (defvar gnus-grouplens-mode-map nil) |
780 | 793 |
804 "Minor mode for providing a GroupLens interface in Gnus summary buffers." | 817 "Minor mode for providing a GroupLens interface in Gnus summary buffers." |
805 (interactive "P") | 818 (interactive "P") |
806 (when (and (eq major-mode 'gnus-summary-mode) | 819 (when (and (eq major-mode 'gnus-summary-mode) |
807 (member gnus-newsgroup-name grouplens-newsgroups)) | 820 (member gnus-newsgroup-name grouplens-newsgroups)) |
808 (make-local-variable 'gnus-grouplens-mode) | 821 (make-local-variable 'gnus-grouplens-mode) |
809 (setq gnus-grouplens-mode | 822 (setq gnus-grouplens-mode |
810 (if (null arg) (not gnus-grouplens-mode) | 823 (if (null arg) (not gnus-grouplens-mode) |
811 (> (prefix-numeric-value arg) 0))) | 824 (> (prefix-numeric-value arg) 0))) |
812 (when gnus-grouplens-mode | 825 (when gnus-grouplens-mode |
813 (make-local-hook 'gnus-select-article-hook) | 826 (if (not (fboundp 'make-local-hook)) |
814 (gnus-add-hook 'gnus-select-article-hook 'grouplens-do-time nil 'local) | 827 (add-hook 'gnus-select-article-hook 'grouplens-do-time) |
815 (make-local-hook 'gnus-exit-group-hook) | 828 (make-local-hook 'gnus-select-article-hook) |
816 (gnus-add-hook 'gnus-exit-group-hook 'bbb-exit-group nil 'local) | 829 (add-hook 'gnus-select-article-hook 'grouplens-do-time nil 'local)) |
830 (if (not (fboundp 'make-local-hook)) | |
831 (add-hook 'gnus-exit-group-hook 'bbb-put-ratings) | |
832 (make-local-hook 'gnus-exit-group-hook) | |
833 (add-hook 'gnus-exit-group-hook 'bbb-put-ratings nil 'local)) | |
817 (make-local-variable 'gnus-score-find-score-files-function) | 834 (make-local-variable 'gnus-score-find-score-files-function) |
818 | 835 (cond ((eq gnus-grouplens-override-scoring 'combine) |
819 (cond | 836 ;; either add bbb-buld-mid-scores-alist to a list |
820 ((eq gnus-grouplens-override-scoring 'combine) | 837 ;; or make a list |
821 ;; either add bbb-buld-mid-scores-alist to a list | 838 (if (listp gnus-score-find-score-files-function) |
822 ;; or make a list | 839 (setq gnus-score-find-score-files-function |
823 (if (listp gnus-score-find-score-files-function) | 840 (append 'bbb-build-mid-scores-alist |
824 (setq gnus-score-find-score-files-function | 841 gnus-score-find-score-files-function )) |
825 (append 'bbb-build-mid-scores-alist | 842 (setq gnus-score-find-score-files-function |
826 gnus-score-find-score-files-function)) | 843 (list gnus-score-find-score-files-function |
827 (setq gnus-score-find-score-files-function | 844 'bbb-build-mid-scores-alist)))) |
828 (list gnus-score-find-score-files-function | 845 ;; leave the gnus-score-find-score-files variable alone |
829 'bbb-build-mid-scores-alist)))) | 846 ((eq gnus-grouplens-override-scoring 'separate) |
830 ;; leave the gnus-score-find-score-files variable alone | 847 (add-hook 'gnus-select-group-hook |
831 ((eq gnus-grouplens-override-scoring 'separate) | 848 '(lambda() |
832 (add-hook 'gnus-select-group-hook | 849 (bbb-build-mid-scores-alist gnus-newsgroup-name)))) |
833 (lambda () | 850 ;; default is to override |
834 (bbb-get-predictions (bbb-get-all-mids) | 851 (t (setq gnus-score-find-score-files-function |
835 gnus-newsgroup-name)))) | 852 'bbb-build-mid-scores-alist))) |
836 ;; default is to override | |
837 (t | |
838 (setq gnus-score-find-score-files-function | |
839 'bbb-build-mid-scores-alist))) | |
840 | |
841 ;; Change how summary lines look | |
842 (make-local-variable 'gnus-summary-line-format) | 853 (make-local-variable 'gnus-summary-line-format) |
854 (setq gnus-summary-line-format | |
855 gnus-summary-grouplens-line-format) | |
843 (make-local-variable 'gnus-summary-line-format-spec) | 856 (make-local-variable 'gnus-summary-line-format-spec) |
844 (setq gnus-summary-line-format gnus-summary-grouplens-line-format) | |
845 (setq gnus-summary-line-format-spec nil) | 857 (setq gnus-summary-line-format-spec nil) |
846 (gnus-update-format-specifications nil 'summary) | |
847 (gnus-update-summary-mark-positions) | |
848 | 858 |
849 ;; Set up the menu. | 859 ;; Set up the menu. |
850 (when (and menu-bar-mode | 860 (when (and menu-bar-mode |
851 (gnus-visual-p 'grouplens-menu 'menu)) | 861 (gnus-visual-p 'grouplens-menu 'menu)) |
852 (gnus-grouplens-make-menu-bar)) | 862 (gnus-grouplens-make-menu-bar)) |