Browse Source

Merge branch 'master' of github.com:nisstyre56/TextbookEngine

master
wes 8 years ago
parent
commit
209447edad
  1. 7
      src/archive.py
  2. 10
      src/mcmaster/classes.py
  3. 7
      src/scripts/book.tag
  4. 1
      src/scripts/class.tag
  5. 5
      src/scripts/results.tag
  6. 3
      src/scripts/row.tag
  7. 76
      src/scripts/search.tag
  8. 6
      src/search.py
  9. 14
      src/styles/bootstrap.min.css
  10. 64
      src/styles/search.scss
  11. 56
      src/templates/search.html
  12. 18
      src/visualize.py
  13. 1
      src/website.py

7
src/archive.py

@ -5,14 +5,14 @@ from json import loads, dumps
import requests as req
searchUrl = "https://archive.org/advancedsearch.php?q={0}&fl%5B%5D=avg_rating&fl%5B%5D=description&fl%5B%5D=identifier&fl%5B%5D=type&sort%5B%5D=&sort%5B%5D=&sort%5B%5D=&rows=50&page=1&output=json&callback=callback&save=yes#raw"
searchUrl = "https://archive.org/advancedsearch.php?q={0}&fl%5B%5D=avg_rating&fl%5B%5D=description&fl%5B%5D=identifier&fl%5B%5D=mediatype&fl%5B%5D=type&fl%5B%5D=type&sort%5B%5D=&sort%5B%5D=&sort%5B%5D=&rows=50&page=1&output=json&callback=callback&save=yes#raw"
def searchIA(title, author):
"""
Do a search on The Internet Archive for a book
"""
print("running a search")
requrl = searchUrl.format(quote(title + " " + author))
requrl = searchUrl.format(quote(title) + " AND " + quote(author))
try:
results = loads(req.get(requrl).text[9:][0:-1])
except ValueError:
@ -24,7 +24,8 @@ def searchIA(title, author):
return []
docs = results["response"]["docs"]
urls = []
for result in results["response"]["docs"][0:3]:
for result in [r for r in results["response"]["docs"][0:10] if r["mediatype"] == "texts"]:
print(result)
urls.append("https://archive.org/details/%s" % result["identifier"])
return urls

10
src/mcmaster/classes.py

@ -207,7 +207,7 @@ def parseColumns(subject, html):
classInfo = (list(getSectionInfo(table)) for table in
islice((table for table in parsed.xpath(".//table")
if table.xpath("@id") and
search(r"ICField[0-9]+\$scroll", table.xpath("@id")[0])), 1, sys.maxint))
search(r"ICField[0-9]+\$scroll", table.xpath("@id")[0])), 1, sys.maxsize))
classNames = ((subject, span.text_content().strip()) for span in parsed.xpath(".//span")
if span.xpath("@id") and
@ -238,7 +238,7 @@ class MosReq(object):
self.codes_ = []
def getlist(self, subject):
sys.stderr.write("Getting " + subject + "\n")
sys.stderr.write("Getting %s\n" % subject.decode("UTF-8"))
first_req = requests.get(searchurl, cookies=self.cookies).content
# for some reason Mosaic wants us to request it twice, ??????????????????
self.statenum = getStateNum(first_req)
@ -252,7 +252,7 @@ class MosReq(object):
self.statenum = getStateNum(first_req)
except IndexError:
pass
if "Your search will return over" in first_req:
if b"Your search will return over" in first_req:
return requests.post(searchurl,
data=payload2.format(self.statenum, self.semester),
@ -295,7 +295,8 @@ def request(codes, lists, semester):
code = codes.get()
try:
lists.put(requester.classes(code))
except:
except exception:
print(exception)
codes.task_done()
return
codes.task_done()
@ -335,6 +336,7 @@ class CourseInfo(object):
for cl in chain.from_iterable(sections):
new_sections = []
for sec in cl[1]:
print(sec)
if len(sec.day) > 1:
for day in sec.day:
new_sections.append(copy.deepcopy(sec))

7
src/scripts/book.tag

@ -2,21 +2,21 @@
<div class="text-clip toast">
<p>
<button onclick={getresources} class="btn btn-link">
{ booktitle }
{ booktitle } {bookauthor !== "Ccw" ? "by " + bookauthor : ""}
</button>
<dd>
<div if={ loading } class="loading">
</div>
<p if={ iarchive }>
<a target="_blank" href="{ iarchive }">
<button class="centered btn btn-link">
<button class="centered btn">
Internet Archive Result
</button>
</a>
</p>
<p if={ openlib }>
<a target="_blank" href="{ openlib }">
<button class="centered btn btn-link">
<button class="centered btn">
Open Library Result
</button>
</a>
@ -27,6 +27,7 @@
</dd>
</p>
</div>
<script>
this.iarchive = false;
this.openlib = false;

1
src/scripts/class.tag

@ -34,4 +34,5 @@ showbooks() {
this.update();
</script>
</class>

5
src/scripts/results.tag

@ -1,6 +1,9 @@
<results>
<div if={notLoading} class="courses container">
<row class="course-row columns" each={ rows } data="{ this }" classrow={ row }></row>
<row if={rows.length > 0} class="course-row columns" each={ rows } data="{ this }" classrow={ row }></row>
<div if={rows.length <= 0} class="empty">
No Results, Sorry!
</div>
</div>
<script>
clicker() {

3
src/scripts/row.tag

@ -4,6 +4,9 @@
data="{ this }">
</class>
<script>
this.classrow = opts.classrow
</script>
</row>

76
src/scripts/search.tag

@ -1,51 +1,62 @@
<search>
<form class="form-horizontal search-form" onsubmit={ submit.bind(this) } type="submit"method="get">
<form class="form-horizontal search-form" onsubmit={ submit } type="submit"method="get">
<div class="form-group">
<div class="container">
<div class="container">
<div class="columns">
<div if={ false }
class="help-toast toast toast-primary">
<button onclick={ clearhelp }
class="btn btn-clear float-right">
</button>
Type keywords of your course's name or the course code (e.g. PSYCH 2B03)
</div>
</div>
<div class="columns">
<div class="col-sm-8 form-item">
<input onfocus={ showHelp }
class="form-input"
placeholder="Description"
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<input onfocus={ showhelp }
class="form-input search"
placeholder="Course Description"
type="text"
name="title"/>
</div>
<div class="col-sm-2 form-item">
<select class="form-select" aria-labelledby="dLabel" name="sem">
<option value="Fall">Fall</option>
<option value="Winter" selected>Winter</option>
<option value="Spring/Summer">Spring/Summer</option>
</select>
</div>
<div class="col-sm-2 form-item">
<button class="btn btn-primary" type="submit">Search</button>
name="title">
</input>
</div>
</div>
<div class="columns">
<div class="col-sm-6 col-md-6 col-lg-6">
<select class="semester form-select float-right" aria-labelledby="dLabel" name="sem">
<option value="Fall" selected>Fall</option>
<option value="Winter">Winter</option>
<option value="Spring/Summer">Spring/Summer</option>
</select>
</div>
<div class="col-sm-6 col-md-6 col-lg-6">
<button
class="search-btn btn btn-primary float-left tooltip tooltip-bottom"
data-tooltip="Search by keywords"
type="submit">
Search
</button>
</div>
</div>
</div>
</div>
</form>
<div if={ opts.showHelp }
class="help-toast toast toast-primary">
<button onclick={ clearHelp }
class="btn btn-clear float-right">
</button>
Type keywords of your course's name or the course code (e.g. PSYCH 2B03)
</div>
<div if={ opts.booksLoading } class="search-load">
</div>
</search>
<script>
this.showedHelp = false;
this.waiting = false;
function showHelp() {
showhelp() {
if (!this.showedHelp) {
this.opts.showHelp = true;
this.update();
if (!waiting) {
waiting = true;
if (!this.waiting) {
this.waiting = true;
window.setTimeout(
(function() {
this.waiting = false;
@ -55,7 +66,7 @@ function showHelp() {
}
}
function clearHelp() {
clearhelp() {
this.showedHelp = true;
this.opts.showHelp = false;
this.update();
@ -66,7 +77,7 @@ function clearHelpTemp() {
this.update();
}
function submit(ev) {
submit(ev) {
ev.preventDefault();
this.showedHelp = true;
this.opts.showHelp = false;
@ -84,3 +95,6 @@ function submit(ev) {
this.update();
}).bind(this));
}
</script>
</search>

6
src/search.py

@ -20,8 +20,8 @@ es = elasticsearch.Elasticsearch()
def summarize(text):
splitted = text.split(" ")
if len(splitted) > 4:
return " ".join(splitted[0:4]) + ".."
if len(splitted) > 6:
return " ".join(splitted[0:6]) + ".."
return text
def sectionToJSON(section):
@ -204,7 +204,7 @@ def searchTerms(terms):
if obj.books:
secs["books"] = [
{
"booktitle" : summarize(book[0]),
"booktitle" : book[0],
"bookauthor" : book[1],
"bookprice" : book[2]
}

14
src/styles/bootstrap.min.css

File diff suppressed because one or more lines are too long

64
src/styles/search.scss

@ -4,6 +4,10 @@ header {
color: $blue;
}
.form-group {
margin: auto;
}
.wraptext {
white-space: pre-wrap !important;
}
@ -77,17 +81,52 @@ a {
margin-right: 0px !important;
}
.form-item {
padding-left: 5px;
padding-right: 5px;
margin-right: -15px;
.search {
max-width: 60%;
margin-bottom: 10px;
margin-left: auto;
margin-right: auto;
@media (max-width: 735px) {
max-width: 80%;
}
@media (max-width: 480px) {
max-width: 100%;
margin-bottom: 10px;
}
}
.semester {
margin-bottom: 10px;
margin-right: 5px;
@media (max-width: 480px) {
max-width: 100%;
margin-bottom: 10px;
}
}
.search-btn {
margin-bottom: 10px;
margin-left: 5px;
@media (max-width: 480px) {
max-width: 100%;
margin-bottom: 10px;
}
}
.search-controls {
margin-top: 5px;
margin-left: 20%;
}
.title {
font-weight: bolder;
@media (min-width: 480px) {
margin-left: 80px;
}
float: right;
margin-right: 10%;
}
.header-text {
margin: auto;
max-width: 80%;
}
.ui-autocomplete {
@ -135,13 +174,18 @@ a {
}
.logo {
margin-top: 20px;
margin-left: -175px;
float: left;
margin-left: -20%;
margin-top: 15px;
@media (max-width: 480px) {
margin-left: 45% !important;
}
}
.page-top {
font-size: 15px;
width: 50% !important;
margin: auto;
width: 80% !important;
}
.help-toast {

56
src/templates/search.html

@ -1,50 +1,44 @@
{% extends "bootstrap/base.html" %}
{% block head %}
{{super()}}
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<header class="text-center nav navbar">
<section class="centered page-top navbar-section">
<div class="container">
<section class="page-top navbar-section">
<div class="container header-text">
<div class="columns">
<div class="title column col-md-9"><h1>TextBook Commons</h1></div>
<div class="logo column col-md-3">
<figure class="avatar avatar-xl">
<div class="col-sm-9 col-md-9 col-lg-9 text-center">
<h1 class="title">TextBook Commons</h1>
</div>
<div class="col-sm-3 col-md-3 col-lg-3">
<figure class="logo avatar avatar-xl">
<img src="https://mgoal.ca/goal.png" />
</figure>
</div>
</div>
<div class="columns">
<div class="title col-sm-12 col-md-12 col-lg-12">
<h5>Search for your course and start saving money on your books</h5>
</div>
</div>
</div>
<h5>Search for your course and start saving money on your books</h5>
<search></search>
</section>
</header>
{% endblock %}
<html>
<figure class="avatar avatar-xl">
<img src="https://mgoal.ca/goal_small.png" />
</figure>
<body>
{% block content %}
<body>
<results></results>
{% endblock %}
<footer class="footer">
</footer>
{% block styles %}
{{super()}}
<link rel="stylesheet" href="/styles/spectre.min.css">
<link rel="stylesheet" href="/styles/search.min.css">
{% endblock %}
{% block scripts %}
{{super()}}
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/riot/2.6.7/riot+compiler.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>
<script type="text/javascript" src="/scripts/tags.min.js"></script>
<script type="text/javascript" src="/scripts/search.min.js"></script>
{% endblock %}
</body>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/riot/2.6.7/riot+compiler.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>
<script type="text/javascript" src="/scripts/tags.min.js"></script>
<script type="text/javascript" src="/scripts/search.min.js"></script>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous">
</script>
</body>
</html>

18
src/visualize.py

@ -9,24 +9,8 @@ from operator import attrgetter
import pygal
import csv
class Textbook(object):
def __init__(self, dept, code, title, author, price):
self.dept = dept
self.code = code
self.title = title
self.author = author
self.price = float(price)
def __repr__(self):
return "Dept = %s, Code = %s, %s by %s, costs $%s" % (self.dept,
self.code,
self.title,
self.author,
self.price)
def courses():
with open("./books.csv", "r") as books:
with open("./mcmaster/courses.csv", "r") as books:
booksreader = csv.reader(books)
for row in booksreader:
yield row

1
src/website.py

@ -142,7 +142,6 @@ def ClassSearch(configfile=None):
app = Flask(__name__)
app.register_blueprint(blueprint, url_prefix="/search")
Bootstrap(app)
#app.config["scripts"] = "./scripts"
#app.config["styles"] = "./styles"
return app

Loading…
Cancel
Save