-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathplt-bacon.rkt
196 lines (182 loc) · 6.42 KB
/
plt-bacon.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#lang racket
(require
web-server/servlet web-server/servlet-env
web-server/formlets web-server/formlets/servlet
net/url
graph)
;; scrape data ----------------------------------------------------------------
(define PLT-PUBS-URL (string->url "http://www.ccs.neu.edu/racket/pubs/"))
(define neu-pubs-port (get-pure-port PLT-PUBS-URL))
;(define neu-pubs-port (open-input-file "plt-pubs.html"))
(define name-pat "([A-Z][a-z\\-]+\\s?)+")
(define word-pat "([A-Za-z\\-]+\\s?)+")
(define names-pat (string-append "(" name-pat ",\\s)+" name-pat))
(define title-pat (string-append "(?<=<cite>)\\s+(" word-pat ")+"))
(define authors-px
(pregexp
(string-append "(?<=:|<div>)\\s*" names-pat ".+?" title-pat)))
(define matches (regexp-match* authors-px neu-pubs-port))
;; authors+title : [Listof author-string ... title-string]
(define authors+title
(for/list ([authors matches])
(define as+title
(string-split (string-trim (bytes->string/utf-8 authors)) #px",\\s+"))
(define last-auth+title
(car (reverse as+title)))
(define first-authors
(reverse (cdr (reverse as+title))))
(define last-auth+title-match
(regexp-split #px"\\s+<br />|\\s+<cite>" last-auth+title))
(define as+t
(append first-authors
(list (first last-auth+title-match)
(string-trim (car (reverse last-auth+title-match))))))
as+t))
;; populate graph -------------------------------------------------------------
(define PLT-GRAPH (unweighted-graph/undirected null))
(define-edge-property PLT-GRAPH papers)
(for ([as+t authors+title])
(define authors (cdr (reverse as+t)))
(define title (car (reverse as+t)))
(for* ([auth1 authors]
[auth2 authors]
#:unless (string=? auth1 auth2))
(define papers-curr (papers auth1 auth2 #:default null))
(add-edge! PLT-GRAPH auth1 auth2)
(papers-set! auth1 auth2 (cons title papers-curr))))
;; print to stdout ------------------------------------------------------------
#;(define (plt-bacon auth erdos bacon)
(define erdos-path (fewest-vertices-path PLT-GRAPH auth erdos))
(define bacon-path (fewest-vertices-path PLT-GRAPH auth bacon))
;; print erdos path
(for ([a1 erdos-path]
[a2 (cdr erdos-path)])
(printf "~a co-authored with ~a:\n" a1 a2)
(for ([p (papers a1 a2)])
(printf " ~a\n" p)))
(define erdos-num (sub1 (length erdos-path)))
(printf "\n** ~a's ~a-number is: ~a\n\n" auth erdos erdos-num)
;; print bacon path
(for ([a1 bacon-path]
[a2 (cdr bacon-path)])
(printf "~a co-authored with ~a:\n" a1 a2)
(for ([p (papers a1 a2)])
(printf " ~a\n" p)))
(define bacon-num (sub1 (length bacon-path)))
(printf "\n** ~a's ~a-number is: ~a\n\n" auth bacon bacon-num)
(printf "## ~a's ~a-~a-number is: ~a\n"
auth erdos bacon
(+ erdos-num bacon-num)))
;; html output ----------------------------------------------------------------
(define (plt-bacon-html auth erdos bacon)
(define erdos-path (fewest-vertices-path PLT-GRAPH auth erdos))
(define bacon-path (fewest-vertices-path PLT-GRAPH auth bacon))
(define erdos-num (sub1 (length erdos-path)))
(define bacon-num (sub1 (length bacon-path)))
`(table
(tr "Computed "
(i ,auth)
"'s "
(b ,erdos) "-" (b ,bacon) " number:")
(tr (br) (hr))
(tr
;; print erdos path
,@(for/list ([a1 erdos-path]
[a2 (cdr erdos-path)])
`(table (tr (i ,(format "~a" a1))
" co-authored with "
(i ,(format "~a" a2))
":")
(tr (ul
,@(for/list ([p (papers a1 a2)])
`(li ,(format "~a" p))))))))
(tr "** "
(i ,(format "~a" auth))
"'s "
(b ,(format "~a" erdos))
"-number is: "
(b ,(format "~a" erdos-num)))
(tr (br) (hr))
(tr (br))
(tr
; ;; print bacon path
,@(for/list ([a1 bacon-path]
[a2 (cdr bacon-path)])
`(table (tr (i ,(format "~a" a1))
" co-authored with "
(i ,(format "~a" a2))
":")
(tr (ul
,@(for/list ([p (papers a1 a2)])
`(li ,(format "~a" p))))))))
(tr "** "
(i ,(format "~a" auth))
"'s "
(b ,(format "~a" bacon))
"-number is: "
(b ,(format "~a" bacon-num)))
(tr (br) (hr))
(tr (br))
(tr
"## "
(i ,(format "~a" auth))
"'s "
(b ,(format "~a-~a" erdos bacon))
"-number is: "
(b ,(format "~a" (+ erdos-num bacon-num))))
(tr (br) (hr))))
;;-----------------------------------------------------------------------------
;; web server front end
(define author-choices
(sort
(filter-not
(λ (v) (regexp-match #px"and\\s|b>|Felleisen\\." v))
(get-vertices PLT-GRAPH))
string<?))
(define author-formlet
(formlet*
`(div
(div "Author Name: "
,{(select-input
author-choices
#:selected? (lambda (x) (string=? x "Chang")))
. =>* . author})
(div "\"Bacon\": "
,{(select-input
author-choices
#:selected? (lambda (x) (string=? x "Felleisen")))
. =>* . bacon})
(div "\"Erdos\": "
,{(select-input
author-choices
#:selected? (lambda (x) (string=? x "Flatt")))
. =>* . erdos})
(div ,{(submit "Compute!") . =>* . res}))
;(list author erdos bacon)))
;; Q: Why is author etc a list?
(let ([response-gen
(λ (embed/url)
(response/xexpr
`(html
(title "Results")
(body (h1 "Results")
(div ,(plt-bacon-html (car author) (car bacon) (car erdos)))
(br) (br)
(a ([href ,(embed/url serve-bacon)]) "Start Again")))))])
(send/suspend/dispatch response-gen))))
;(define (start request) (serve-bacon request))
(provide serve-bacon)
(define (serve-bacon request)
(define (response-generator embed/url)
(response/xexpr
`(html
(head (title "PLT Bacon"))
(body (h1 "PLT Bacon")
(img ([src "plt-bacon.png"]))
,(embed-formlet embed/url author-formlet)))))
(send/suspend/dispatch response-generator))
#;(serve/servlet start
#:launch-browser? #t
#:quit? #f
#:listen-ip #f
#:port 8000)