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))