diff --git a/.gitignore b/.gitignore index 0485ba8f6b07aff0aaa8ae8d20e6723bcb365a36..0dcb91398ab645ba5745e3f1904af17c845e4194 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ \.DS_Store + +*.pyc diff --git a/tweet_havester/__pycache__/general_process.cpython-37.pyc b/tweet_havester/__pycache__/general_process.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8018862355bf6199d19eef0f2404937d361da5d Binary files /dev/null and b/tweet_havester/__pycache__/general_process.cpython-37.pyc differ diff --git a/tweet_havester/__pycache__/tweepy_search.cpython-37.pyc b/tweet_havester/__pycache__/tweepy_search.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26a16ae86d26beeec6c17682d00b640f4ed31c2d Binary files /dev/null and b/tweet_havester/__pycache__/tweepy_search.cpython-37.pyc differ diff --git a/tweet_havester/__pycache__/tweepy_stream.cpython-37.pyc b/tweet_havester/__pycache__/tweepy_stream.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3c196dc734728bffd04af690dbb764be92b9924 Binary files /dev/null and b/tweet_havester/__pycache__/tweepy_stream.cpython-37.pyc differ diff --git a/tweet_havester/general_process.py b/tweet_havester/general_process.py index b8f95b04e024bc3876f6a6552d8bb9591e328926..5e093654770980ec40cb413d509230b63c316ffb 100644 --- a/tweet_havester/general_process.py +++ b/tweet_havester/general_process.py @@ -15,13 +15,15 @@ def data_process(tweet,model): return None location = tweet['location'] create_time = tweet['create_time'] - + flag = False for city in cities: #the location contains target city names if city in location.lower(): #generalize city name location=city - + flag = True + if(not flag): + return None p_tweet={ '_id':id, "create_time":create_time, diff --git a/tweet_havester/init_db.py b/tweet_havester/init_db.py new file mode 100644 index 0000000000000000000000000000000000000000..5edc9b130eda671f290ca66b98281ec3e2cb9b13 --- /dev/null +++ b/tweet_havester/init_db.py @@ -0,0 +1,24 @@ +import couchdb +import sys + +def run(server_path): + couch = couchdb.Server(server_path) + couch.create('tweet_2014_raw') + couch.create('raw_tweets') + couch.create('tweet_2014_results') + couch.create('tweet_results') + couch.create('user_id') + print("create all db successful") + + +if __name__ == "__main__": + a=sys.argv + if(len(a) == 4): + ip = a[1] + username = a[2] + password = a[3] + path = 'http://' + username +':' + password +'@'+ip+':5984/' + else: + path = 'http://admin:password@127.0.0.1:5984/' + run(path) + pass diff --git a/tweet_havester/tweepy_search.py b/tweet_havester/tweepy_search.py index fe18c6bc3648654673b92e870080c4ecf504944d..830c22392ddcbeb584b53aea5c33cf068f123f55 100644 --- a/tweet_havester/tweepy_search.py +++ b/tweet_havester/tweepy_search.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import json import os +import time import couchdb import tweepy from tweepy import OAuthHandler @@ -56,7 +57,7 @@ class TweetSearchHavester(): # print(dic) try: p_dic = gp.data_process(dic,self.model) - print(p_dic) + # print(p_dic) if p_dic != None: process_db.save(p_dic) db.save(dic) @@ -67,17 +68,27 @@ class TweetSearchHavester(): -if __name__ == '__main__': - couch = couchdb.Server('http://admin:password@127.0.0.1:5984/') +def run(server_path): + couch = couchdb.Server(server_path) db = couch['user_id'] # couch.create('test_db') - city = ["melbourne","sydney","perth","adelaide","brisbane"] + dict = {} + with open('./tweet_havester_config.json','r') as f: + dict = json.load(f) + cities = [] + for city in dict: + cities.append(city) switch = 0 count = 0 ids = list() a = TweetSearchHavester(couch) - while True: - print("start a new round") + while True: + ids = list() + # if user id pool less than 40, won't start for query search + if(len(db) < 40): + time.wait(100) + continue + print("start a new round on search") for id in db: data = db[id] if(not data['isSearched']): @@ -88,7 +99,7 @@ if __name__ == '__main__': if(count > 20): switch = (switch+1)%5 count = 0 - a.run(ids,city[switch]) + a.run(ids,cities[switch]) for id in ids: data = db[id] data['isSearched'] = True diff --git a/tweet_havester/tweepy_stream.py b/tweet_havester/tweepy_stream.py index c2abc3b21cf69a61b7ca01100fcefcc2cc376927..cfd8180d5d7efcff276c4ff110e37a7b7a1a6139 100644 --- a/tweet_havester/tweepy_stream.py +++ b/tweet_havester/tweepy_stream.py @@ -12,6 +12,7 @@ import general_process as gp class listener(StreamListener): def __init__(self,path): + StreamListener.__init__(self) self.couch = couchdb.Server(path) self.model = joblib.load("./train_model.m") def convertValue(self,origin): @@ -34,10 +35,9 @@ class listener(StreamListener): content = json.loads(data) dic = self.convertValue(content) id_doc = {"_id":str(dic["user_id"]),"user_name":content['user']['name'],"isSearched":False} - # print(id_doc) p_dic = gp.data_process(dic,self.model) if p_dic != None: - process_db.save(p_dic) + pc_db.save(p_dic) id_db.save(id_doc) db.save(dic) # print("success") @@ -52,44 +52,38 @@ class listener(StreamListener): class TweetStreamHavester(): def __init__(self,server_path): self.server_path = server_path - def process(self,city): + def process(self,city,dict): #args是关键字参数,需要加上名字,写成args=(self,) - print("start streaming"+city) - th = threading.Thread(target=TweetStreamHavester.run, args=(self,city)) + print("start streaming city: "+city) + th = threading.Thread(target=TweetStreamHavester.run, args=(self,city,dict)) th.start() th.join() - def run(self, city): - dict = {} - with open('./tweet_havester_config.json','r') as f: - dict = json.load(f) - api_token = dict[city]["API"]["stream"] - stream_area = dict[city]["bound"] - consumer_key = api_token["consumer_key"] - consumer_secret = api_token["consumer_secret"] - access_token = api_token["access_token"] - access_token_secret = api_token["access_token_secret"] - auth = OAuthHandler(consumer_key,consumer_secret) - auth.set_access_token(access_token,access_token_secret) - twitterStream = Stream(auth,listener(self.server_path)) - twitterStream.filter(locations=stream_area,is_async = True) + def run(self, city, dict): + api_token = dict[city]["API"]["stream"] + stream_area = dict[city]["bound"] + consumer_key = api_token["consumer_key"] + consumer_secret = api_token["consumer_secret"] + access_token = api_token["access_token"] + access_token_secret = api_token["access_token_secret"] + auth = OAuthHandler(consumer_key,consumer_secret) + auth.set_access_token(access_token,access_token_secret) + twitterStream = Stream(auth,listener(self.server_path)) + twitterStream.filter(locations=stream_area,is_async = True) - f.close() -if __name__ == "__main__": - couch = couchdb.Server('http://admin:password@127.0.0.1:5984/') - # couch.create('raw_tweets') - # couch.create('new_stream_tweet') - server_path = 'http://127.0.0.1:5984/' +def run(server_path): + couch = couchdb.Server(server_path) + # server_path = 'http://127.0.0.1:5984/' a = TweetStreamHavester(server_path) - try: - a.process("melbourne") - a.process("sydney") - a.process("adelaide") - a.process("brisbane") - a.process("perth") - except Exception as e: - print(e) - pass + with open('./tweet_havester_config.json','r') as f: + dict = json.load(f) + for city in dict: + try: + a.process(city,dict) + except Exception as e: + print(e) + pass + f.close() diff --git a/tweet_havester/tweet_havester.py b/tweet_havester/tweet_havester.py new file mode 100644 index 0000000000000000000000000000000000000000..949b4d5511e01f436fad606bc966c04441379adb --- /dev/null +++ b/tweet_havester/tweet_havester.py @@ -0,0 +1,19 @@ +import tweepy_search as tSearch +import tweepy_stream as tStream +import time +import sys + +if __name__ == "__main__": + server_path = "" + a=sys.argv + if(len(a) == 4): + ip = a[1] + username = a[2] + password = a[3] + server_path = 'http://' + username +':' + password +'@'+ip+':5984/' + else: + server_path = 'http://'+a[1] +':5984/' + tStream.run(server_path) + # wait for streamming for a while to start searching + # time.sleep(200) + tSearch.run(server_path) diff --git a/web_app_django/docker-compose.yml b/web_app_django/docker-compose.yml index 62f28395bd378c7256a4bea4d1feb6f507fb3da1..9f999787d62ae266993cc1d59409aeaa4264c587 100644 --- a/web_app_django/docker-compose.yml +++ b/web_app_django/docker-compose.yml @@ -11,11 +11,11 @@ services: - "5984:5984" web: build: . - command: python /ccc-assignment2-team69/web_app_django/manage.py runserver 0.0.0.0:8000 + command: python /ccc-assignment2-team69/web_app_django/manage.py runserver 0.0.0.0:5555 volumes: - .:/ccc-assignment2-team69/web_app_django/ ports: - - 8000:8000 + - 5555:5555 depends_on: - couchdb diff --git a/web_app_django/tweet/static/css/hover_window.css b/web_app_django/tweet/static/css/hover_window.css new file mode 100644 index 0000000000000000000000000000000000000000..a67af38423d1b954790cce0e53c5ec7f14995454 --- /dev/null +++ b/web_app_django/tweet/static/css/hover_window.css @@ -0,0 +1,38 @@ +.window_info { + padding: 1rem 1.25rem; + margin-bottom: 1rem; + border-radius: .25rem; + background-color: rgba(50, 138, 175, 0.9); + width: auto; + min-width: 12rem; + border-width: 0; + /* right: 1rem; */ + box-shadow: 0 4px 6px 0 rgba(50, 138, 175, 0.6); + } +.window_info tr .content { + text-align: left; + color: rgb(234, 238, 232); + max-width: 200px; +} +.window_info tr .label { + text-align: left; + color: rgb(236, 225, 123); + max-width: 8rem; +} + +.marker_wrap{ + display: flex; + background-color: rgba(2, 123, 179, 0.747); + width: auto; + height: 2rem; + border: none; + border-radius: 0.3rem; + text-align: left; +} +.marker_label{ + margin: auto; + flex: 1; + padding: 0 5px; + color: rgb(255, 255, 255); + line-height: 1.5rem; +} diff --git a/web_app_django/tweet/static/css/img.css b/web_app_django/tweet/static/css/img.css deleted file mode 100644 index 9affde1e30b56ab70a203b6af540820e5f785d6f..0000000000000000000000000000000000000000 --- a/web_app_django/tweet/static/css/img.css +++ /dev/null @@ -1,20 +0,0 @@ - -a.snapchat{ - position: relative; - background: lightgrey; - } - - a.snapchat img { - position: absolute; - opacity: 0; - width: 100px; - height: 100px; - left: 0; - top: -20px; - transition: opacity .5s, top .5s; - } - - a.snapchat:hover img { - opacity: 1; - top: 20px; - } \ No newline at end of file diff --git a/web_app_django/tweet/static/css/style.css b/web_app_django/tweet/static/css/style.css new file mode 100644 index 0000000000000000000000000000000000000000..c3bdda7353c4d750e09d71ff5688641a8efb7c67 --- /dev/null +++ b/web_app_django/tweet/static/css/style.css @@ -0,0 +1,640 @@ +html { + font-size: 12px; + } + .amap-copyright{ + box-sizing: content-box + } + * { + box-sizing: border-box + } + .input-textarea{ + color:grey; + height:8em; + overflow:auto; + border-radius:0.4rem; + border:1px solid #ced4da; + margin-bottom:1rem; + } + body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + line-height: 1.5; + font-weight: 300; + color: #111213; + } + + hr { + margin: 0.5rem 0; + box-sizing: content-box; + height: 0; + overflow: visible; + border: 0; + border-top: 1px solid rgba(0, 0, 0, .1) + } + + p { + margin-top: 0; + margin-bottom: 0; + } + + label { + display: inline-block; + margin-bottom: 0.4rem; + } + + label, .btn { + margin-left: 0; + font-size: 1rem; + } + + button, input, select { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; + overflow: visible; + text-transform: none + } + + [type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner { + padding: 0; + border-style: none; + } + + input[type=checkbox], input[type=radio] { + box-sizing: border-box; + padding: 0; + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding: 0; + margin: 0 0.5rem 0 0; + } + + h4 { + font-family: inherit; + line-height: 1.8; + font-weight: 300; + color: inherit; + font-size: 1.1rem; + margin-top: 0; + margin-bottom: .5rem + } + + .btn { + /* display: inline-block; */ + margin: 0.25rem; + flex: 1; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border: 1px solid transparent; + transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; + background-color: transparent; + background-image: none; + color: #25A5F7; + border-color: #25A5F7; + padding: .25rem .5rem; + line-height: 1.5; + border-radius: 1rem; + -webkit-appearance: button; + cursor:pointer; + } + + .btn:hover { + color: #fff; + background-color: #25A5F7; + border-color: #25A5F7 + } + + .btn:hover { + text-decoration: none + } + + + .input-item { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: center; + align-items: center; + width: 100%; + height: 3rem; + } + + .input-item:last-child { + margin-bottom: 0; + } + + .input-item>select, .input-item>input[type=text], .input-item>input[type=date] { + position: relative; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + width: 1%; + margin-bottom: 0; + } + + .input-item>select:not(:last-child), .input-item>input[type=text]:not(:last-child), .input-item>input[type=date]:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 + } + + .input-item>select:not(:first-child), .input-item>input[type=text]:not(:first-child), .input-item>input[type=date]:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0 + } + + .input-item-prepend { + margin-right: -1px; + } + + .input-item-text, input[type=text],input[type=date], select { + height: calc(2.2rem + 2px); + } + + .input-item-text { + width: 6rem; + text-align: justify; + padding: 0.4rem 0.7rem; + display: inline-block; + text-justify: distribute-all-lines; + /*ie6-8*/ + text-align-last: justify; + /* ie9*/ + -moz-text-align-last: justify; + /*ff*/ + -webkit-text-align-last: justify; + /*chrome 20+*/ + -ms-flex-align: center; + align-items: center; + margin-bottom: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: .25rem; + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + + .input-item-text input[type=checkbox], .input-item-text input[type=radio] { + margin-top: 0 + } + + + .input-card { + display: flex; + flex-direction: column; + min-width: 0; + height: auto; + word-wrap: break-word; + background-color:rgba(0, 0, 0, 0.6); + color: white; + background-clip: border-box; + border-radius: .25rem; + width: 22rem; + border-width: 0; + border-radius: 0.4rem; + box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5); + position: absolute; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 0.75rem 1.25rem; + } + + + .input-text { + line-height: 2rem; + margin-right: 2rem; + } + + .info hr { + margin-right: 0; + margin-left: 0; + border-top-color: grey; + } + + .info { + padding: .75rem 1.25rem; + margin-bottom: 1rem; + border-radius: .25rem; + /* position: fixed; */ + top: 1rem; + background-color: white; + width: auto; + min-width: 22rem; + border-width: 0; + right: 1rem; + box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5); + } + + + .code { + left: 1.5rem; + right: 1.5rem; + top: 1.5rem; + bottom: 1.5rem; + overflow: auto; + margin-bottom: 0rem; + } + + .code .btn { + top: 1rem; + position: absolute; + right: 1rem; + } + + .code .result { + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 0.5rem; + padding: 1rem; + bottom: 1rem; + position: absolute; + top: 5.5rem; + right: 1rem; + left: 1rem; + overflow: auto; + } + + .code .status { + color: #80adff; + display: inline-block; + font-size: 14px; + } + + .code h4 { + display: inline-block; + max-width: 20rem; + margin-right: 1rem; + margin-bottom: 1rem; + } + + select, input[type=text], input[type=date] { + display: inline-block; + width: 100%; + padding: .375rem 1.75rem .375rem .75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center; + background-size: 8px 10px; + border: 1px solid #ced4da; + border-radius: .25rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none + } + + + + input[type=text],input[type=date] { + background: #fff; + padding: .375rem .75rem; + } + + select:focus, input[type=text]:focus, input[type=date]:focus { + border-color: #80bdff; + outline: 0; + box-shadow: 0 0 0 .1rem rgba(128, 189, 255, .1) + } + + .btn:focus { + outline: 0; + box-shadow: none; + } + + select:focus::-ms-value, input[type=text]:focus::-ms-value,input[type=date]:focus::-ms-value { + color: #495057; + background-color: #fff + } + + + /* native toastr */ + .native-toast { + position: fixed; + background-color: rgba(50, 50, 50, .8); + border-radius: 33px; + color: white; + left: 50%; + text-align: center; + padding: 6px 12px; + opacity: 0; + z-index: 99999; + transition: transform .25s, opacity .25s, top .25s; + box-sizing: border-box; + } + + .native-toast-bottom { + bottom: 50px; + -ms-transform: translateX(-50%) translateY(50px); + transform: translateX(-50%) translateY(50px) + } + + .native-toast-bottom.native-toast-shown { + opacity: 1; + -ms-transform: translateX(-50%) translateY(0); + transform: translateX(-50%) translateY(0); + } + + .native-toast-bottom.native-toast-edge { + bottom: 0; + } + + .native-toast-top { + top: 50px; + -ms-transform: translateX(-50%) translateY(-50px); + transform: translateX(-50%) translateY(-50px) + } + + .native-toast-top.native-toast-shown { + opacity: 1; + -ms-transform: translateX(-50%) translateY(0); + transform: translateX(-50%) translateY(0); + } + + .native-toast-top.native-toast-edge { + top: 0; + } + + .native-toast-center { + top: 0; + -ms-transform: translateX(-50%) translateY(-50px); + transform: translateX(-50%) translateY(-50px) + } + + .native-toast-center.native-toast-shown { + opacity: 1; + top: 50%; + -ms-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + } + + .native-toast-edge { + border-radius: 0; + width: 100%; + text-align: left; + } + + @media screen and (min-width: 40rem) { + .native-toast:not(.native-toast-edge) { + max-width: 18rem; + } + } + + /* + max-width does not seem to work in small screen? + */ + + /*@media screen and (max-width: 768px) { + .native-toast:not(.native-toast-edge) { + max-width: 400px; + } + } + + @media screen and (max-width: 468px) { + .native-toast:not(.native-toast-edge) { + max-width: 300px; + } + }*/ + + /* types */ + + .native-toast-error { + background-color: #d92727; + color: white; + } + + .native-toast-success { + background-color: #62a465; + color: white; + } + + .native-toast-warning { + background-color: #fab01b; + color: white; + } + + .native-toast-info { + background-color: rgb(82, 98, 189); + color: white; + } + + [class^="native-toast-icon-"] { + vertical-align: middle; + margin-right: 8px + } + + [class^="native-toast-icon-"] svg { + width: 16px; + height: 16px; + } + + /********************** custom for project **********************/ + /* 标题框 */ + .title-banner{ + position: fixed; + width: 42rem; + top: 2rem; + left: 0; + height: 6rem; + background: rgba(21, 84, 110, 0.749); + /* border-radius: 0 0.4rem 0.4rem 0; */ + display: flex; + align-items: center; + } + .title-content{ + margin: auto; + text-align: center; + } + .title-content p{ + color: whitesmoke; + font-size: 1.7rem; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-weight: 350; + } + + /* 城市选择框 */ + .selection-hub{ + position: fixed; + left: 2rem; + top: 0; + padding-top: 20%; + width: 20rem; + } + .selection-window{ + display: flex; + flex-flow: column; + align-items: center; + height: 11rem; + border: transparent; + margin: 4rem 0; + padding: 0.5rem; + background-color:rgba(9, 75, 116, 0.264); + box-shadow: 0 4px 6px 0 rgba(50, 138, 175, 0.749); + border-radius: 0.4rem; + } + .selection-window .title{ + position: absolute; + padding: 0.7rem 2rem; + background: rgba(4, 42, 66, 0.75); + transform: translate(0,-60%) + } + .selection-window .title p{ + font-size: 1.5rem; + padding: 0.3rem; + color: rgb(236, 225, 123); + font-weight: 400; + } + .selection-window .content{ + width: 60%; + margin: auto; + } + .select_lg { + align-items: center; + border: none; + outline: none; + height: 5rem; + line-height: 3rem; + padding-left: 2rem; + background-color: rgba(50, 138, 175, 0.749); + color:rgb(255, 255, 255); + font-size: 2rem; + } + .info-hub{ + position: fixed; + right: 2rem; + top: 0; + padding-top: 5%; + width: 40rem; + height: 40rem; + display: -webkit-flex; + display: flex; + flex-flow: column; + /* align-items: center; */ + } + .sub_window { + flex: auto; + min-width: 15rem; + margin: 2rem 0; + height: auto; + word-wrap: break-word; + background-color:rgba(2, 123, 179, 0.747); + color: white; + background-clip: border-box; + border-radius: .25rem; + border-width: 0; + border-radius: 0.4rem; + box-shadow: 0 4px 6px 0 rgba(50, 138, 175, 0.749); + padding: 0.75rem 1.25rem; + } + .sub_window .title{ + display: block; + color: rgb(253, 253, 253); + position: absolute; + transform: translate(7%, -70%); + font-size: 1.35rem; + width: 33rem; + padding: 0.75rem 1rem; + text-align: left; + background: rgba(4, 42, 66, 0.75); + font-weight: 420; + } + .sub_window .rcm_list{ + margin-top: 2rem; + } + .rcm_list .table-header{ + width: 100%; + display: flex; + flex-flow: row; + } + .rcm_list .table-header li{ + flex: 1; + text-align: center; + font-size: 1.5rem; + color: rgb(236, 225, 123); + } + .rcm_list .table-content{ + font-size: 1.2rem; + display: flex; + flex-flow: column; + } + .rcm_list .line-info{ + flex: 1; + width: 100%; + display: flex; + flex-flow: row; + } + .rcm_list .line-info p{ + flex: 1; + text-align: center; + } + + .sub_window .horzontal-spliter{ + margin-top: 2rem; + display: flex; + flex-flow: row; + } + .horzontal-spliter .sublist{ + padding-left: 0.75rem; + display: flex; + flex-flow: column; + } + .sublist .list-item{ + width: 100%; + flex: 1; + display: flex; + flex-flow: row; + align-items: center; + margin-left: 1rem; + } + .sublist .list-item p{ + text-align: center; + padding-left: 0.75rem; + } + + #circle { + width: 10px; + height: 10px; + background: rgb(209,209,255); + -moz-border-radius: 50px; + -webkit-border-radius: 50px; + border-radius: 50px; + } + #circle2 { + width: 10px; + height: 10px; + background: rgb(94,211,229); + -moz-border-radius: 50px; + -webkit-border-radius: 50px; + border-radius: 50px; + } + #circle3 { + width: 10px; + height: 10px; + background: rgb(110, 190, 160); + -moz-border-radius: 50px; + -webkit-border-radius: 50px; + border-radius: 50px; + } + + .chart{ + width: 15rem; + height: 15rem; + color: rgb(110, 190, 160) + } + + + + + + \ No newline at end of file diff --git a/web_app_django/tweet/static/images/circle.png b/web_app_django/tweet/static/images/circle.png deleted file mode 100644 index 8510accf77434e3815005f1923478ea1216b05bf..0000000000000000000000000000000000000000 Binary files a/web_app_django/tweet/static/images/circle.png and /dev/null differ diff --git a/web_app_django/tweet/static/img.js b/web_app_django/tweet/static/img.js deleted file mode 100644 index 365ba8ff7cea14745fbad73073a63042e5b4bb4f..0000000000000000000000000000000000000000 --- a/web_app_django/tweet/static/img.js +++ /dev/null @@ -1,13 +0,0 @@ - -<script> - - $(document).ready(function(){ - $("#Image").mouseover(function(){ - $("#Image").show(); - }); - $("#Image").mouseout(function(){ - $("#Image").hide(); - }); - }); - -</script> diff --git a/web_app_django/tweet/static/js/district.js b/web_app_django/tweet/static/js/district.js new file mode 100644 index 0000000000000000000000000000000000000000..36245a3f2bf20e183fe07123322cab60c29645b3 --- /dev/null +++ b/web_app_django/tweet/static/js/district.js @@ -0,0 +1,8 @@ +var districts = [ + { 'name': 'Melbourne', 'center': '144.946014,-37.815018' ,'size': melval*0.01,'rate':melrate} , + { 'name': 'Sydney', 'center': '151.209900,-33.865143','size':sydval*0.01,'rate':sydrate }, + { 'name': 'Brisbane', 'center': '153.021072,-27.470125' ,'size':brival*0.01,'rate':brirate}, + { 'name': 'Adelaide', 'center': '138.599503,-34.921230' ,'size':adeval*0.01,'rate':aderate}, + { 'name': 'Perth', 'center': '115.857048,-31.953512' ,'size':perval*0.01,'rate':perrate} + +]; \ No newline at end of file diff --git a/web_app_django/tweet/static/js/img.js b/web_app_django/tweet/static/js/img.js deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/web_app_django/tweet/static/js/infoshow.js b/web_app_django/tweet/static/js/infoshow.js new file mode 100644 index 0000000000000000000000000000000000000000..9ff31867182916e5c3843b6ea723b2eebf691e9d --- /dev/null +++ b/web_app_django/tweet/static/js/infoshow.js @@ -0,0 +1,79 @@ +var infoWin; +var tableDom; +var rcmWins =[]; +/** + * 封装便捷的撞题 + * @param {AMap.Map} map + * @param {Array} event + * @param {Object} content + */ + + +function openInfoWin(map, event, content) { + if (!infoWin) { + infoWin = new AMap.InfoWindow({ + isCustom: true, //使用自定义窗体 + offset: new AMap.Pixel(70, -10), + }); + } + + var x = event.offsetX; + var y = event.offsetY; + var lngLat = map.containerToLngLat(new AMap.Pixel(x, y)); + // console.log(lngLat) + + if (!tableDom) { + let infoDom = document.createElement('div'); + infoDom.className = 'window_info'; + tableDom = document.createElement('table'); + infoDom.appendChild(tableDom); + infoWin.setContent(infoDom); + } + + var trStr = ''; + for (var name in content) { + var val = content[name]; + trStr += + '<tr>' + + '<td class="label">' + name + '</td>' + + '<td> </td>' + + '<td class="content">' + val + '</td>' + + '</tr>' + } + + tableDom.innerHTML = trStr; + infoWin.open(map, lngLat); +} + +function closeInfoWin() { + if (infoWin) { + infoWin.close(); + } +} + +function showRcmWin(map,points){ + var coor; + var name; + if(points.length > 0){ + for(city in points){ + coor = points[city]["center"].split(',') + name = points[city]["name"] + var rcmWin = new AMap.Marker({ + position:coor, + content: "<div class = 'marker_wrap' ><div class='marker_label'><p>" +name + "</p></div></div>", + offset: new AMap.Pixel(-5, -35), + }); + rcmWins.push(rcmWin) + + } + map.getMap().add(rcmWins) + } + return rcmWins +} + +function closeRcmWin(map,rcmWins){ + rcmWins.forEach(marker => { + map.remove(marker); + }); + rcmWins = [] +} \ No newline at end of file diff --git a/web_app_django/tweet/templates/index.html b/web_app_django/tweet/templates/index.html index 4fb600e2347e796bd266ba02002d4e332feca253..95e22d666334e025a91b1b6e2eb96a4c6110214b 100644 --- a/web_app_django/tweet/templates/index.html +++ b/web_app_django/tweet/templates/index.html @@ -1,43 +1,279 @@ {% load static %} <!DOCTYPE html> <html lang="zh-CN"> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>COMP90024 Team:69</title> + <!-- <link href="http://a.amap.com/Loca/static/manual/example/style/demo.css" rel="stylesheet"> --> + <style> + html, + body, + #container { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + } + </style> +</head> +<body> +<div id="container" class="container"> +</div> + <div class="title-banner"> + <div class="title-content"> + <p>The Analysis of the sin of Wrath</p> + <p>based on tweets across the major cities in Australia</p> + </div> + </div> +<div class="info-hub"> + <div class="sub_window" style="width:auto"> + <div class="title"> + <p>Hate Speech Rate VS number of assault violence </p> + </div> + <div id="chart" class="chart" ></div> + </div> +</div> - - <body> + - {% if cityInfo %} - {% for city in cityInfo %} - <td>{{city.key}}</td> - <td> {{city.value}}</td> - - {% endfor %} - {% for city1 in cityTotal %} - <td>{{city1.melbourne}}</td> - <td> {{city1.sydney}}</td> - <td> {{city1.adelaide}}</td> - <td> {{city1.perth}}</td> - <td> {{city1.brisbane}}</td> - - {% endfor %} - - <td>{{NswCount}}</td> - <td>{{VicCount}}</td> - <td>{{SaCount}}</td> - {% for cityOld in cityTotalOld %} - <td>{{cityOld.melbourne}}</td> - <td> {{cityOld.sydney}}</td> - <td> {{cityOld.adelaide}}</td> - - {% endfor %} - {%else%} - <hr>NO DATA</hr> + +{% if cityInfo %} + +{% for city in cityInfo %} - - {% endif %} - </body> - - + {% if city.key == "melbourne" %} + <script type="text/javascript"> + var melval = "{{city.value}}"; + </script> + {% endif %} + + {% if city.key == "sydney" %} + <script> + var sydval = "{{city.value}}"; + </script> + {% endif %} + + + {% if city.key == "adelaide" %} + <script> + var adeval = "{{city.value}}"; + + </script> + {% endif %} + + {% if city.key == "brisbane" %} + <script> + var brival = "{{city.value}}"; + + </script> + {% endif %} + + {% if city.key == "perth" %} + <script> + var perval = "{{city.value}}"; + </script> + {% endif %} + + {% endfor %} + + + {% for city1 in cityTotal %} + <script type="text/javascript"> + var melrate = "{{city1.melbourne}}"; + var sydrate = "{{city1.sydney}}"; + var aderate = "{{city1.adelaide}}"; + var brirate = "{{city1.brisbane}}"; + var perrate = "{{city1.perth}}"; + </script> + + {% endfor %} + <script src="{% static 'js/district.js' %}"></script> + + <td>{{NswCount}}</td> +<script> + var nswcount = "{{NswCount}}"; +</script> +<td>{{VicCount}}</td> +<script> + var viccount = "{{VicCount}}"; +</script> +<td>{{SaCount}}</td> +<script> + var sacount = "{{SaCount}}"; +</script> +{% for cityOld in cityTotalOld %} +<td>{{cityOld.melbourne}}</td> +<script> + var melold = "{{cityOld.melbourne}}"; +</script> +<td> {{cityOld.sydney}}</td> +<script> + var sydold = "{{cityOld.sydney}}"; +</script> +<td> {{cityOld.adelaide}}</td> +<script> + var adeold = "{{cityOld.adelaide}}"; +</script> + {% endfor %} +{%else%} +<hr>NO DATA</hr> + + + +{% endif %} +<!--<script src="./script/loca.js"></script>--> +<link rel="stylesheet" href="{% static 'css/style.css' %}"/> +<link rel="stylesheet" href="{% static 'css/hover_window.css' %}"/> +<script src="https://webapi.amap.com/maps?v=1.4.12&key=393144ee0738b91f3e93b0c6d0c36562"></script> +<script src="http://webapi.amap.com/loca?v=1.2.0&key=393144ee0738b91f3e93b0c6d0c36562"></script> +<script src= "{% static 'js/infoshow.js' %}"></script> +<script src = "https://www.gstatic.com/charts/loader.js"></script> +<script type = "text/javascript"> + google.charts.load('current', {packages: ['corechart']}); + </script> +<!-- <script src=".\infoshow.js"></script> --> +<script src = "{% static 'js/district.js' %}"></script> + +<script> + var rcmWins =[]; + var map = Loca.create('container', { + mapStyle: 'amap://styles/070f548e06917955722ed5b9ac9a06f2', + zoom: 4.5, + center: [145, -28] + }); + + var layer = Loca.visualLayer({ + eventSupport: true, // selectStyle 配置需要开启 eventSupport: true + container: map, + type: 'point', + shape: 'circle' + }); + rcmWins = showRcmWin(map,districts) + + + layer.setData(districts, { + lnglat: 'center' + }); + + layer.setOptions({ + style: { + radius: function(data){ + return 15+data.value.size/4 + }, + color: '#FDE834', + // borderColor: '#c5001f', + // borderWidth: 1.5, + opacity: 0.7 + }, + + }); + + layer.render(); + + var layer0 = Loca.visualLayer({ + eventSupport: true, // selectStyle 配置需要开启 eventSupport: true + container: map, + type: 'point', + shape: 'circle' + }); + + layer0.on('mousemove', function (ev) { + // 事件类型 + var type = ev.type; + // 当前元素的原始数据 + var rawData = ev.rawData; + + // 原始鼠标事件 + var originalEvent = ev.originalEvent; + + openInfoWin(map.getMap(), originalEvent, { + 'City': rawData.name, + 'Hate Speech Rate': rawData.rate + }); + }); + + layer0.on('mouseleave', function (ev) { + closeInfoWin(); + }); - </html> \ No newline at end of file + layer0.setData(districts, { + lnglat: 'center' + }); + + layer0.setOptions({ + style: { + radius:8, + color: '#e2431e', + opacity: 0.8 + }, + selectStyle: { + radius: 10, + color: 'white', + opacity: 0.8 + } + }); + + layer0.render(); + + + function drawChart() { + // Define the chart to be drawn. + var data = new google.visualization.DataTable(); + var nsw = parseFloat(nswcount); + var vic = parseFloat(viccount); + var sa = parseFloat(sacount); + var syd =parseFloat(sydold); + var mel = parseFloat(melold); + var ade = parseFloat(adeold); + data.addColumn('string', 'State'); + data.addColumn('number', 'Criminal Stastics from Aurin'); + data.addColumn('number', 'Hate Speech Percentage'); + + data.addRows([ + ['New South Wales', nsw, syd], + ['Victoria', vic, mel], + ['South Australia', sa, ade] + ]); + + // Set chart options + var options = { + hAxis: { + title: '', + textStyle: {color: 'white'} + }, + vAxis: { + title: '', + textStyle: {color: 'white'} + }, + series: { + 0: { color: '#e2431e' }, + 1: { color: '#FDE834' }, + }, + chartArea:{left:50,top:50,width:'55%',height:'65%'}, + 'width':450, + 'height':350, + pointsVisible: true, + backgroundColor:"transparent", + // colors: ['#f07f09'] + legend: {position: 'labeled', textStyle: {color: 'white', fontSize: 12}} + }; + + // Instantiate and draw the chart. + var chart = new google.visualization.ColumnChart(document.getElementById('chart')); + chart.draw(data, options); + } + google.charts.setOnLoadCallback(drawChart); + + +</script> + + +</body> +</html> + + + \ No newline at end of file diff --git a/web_app_django/tweet/views.py b/web_app_django/tweet/views.py index 6423e190d218622d031d10ffd0bfb95ef002bf21..26af4560d7992d41369cd13f8870b086af44921f 100644 --- a/web_app_django/tweet/views.py +++ b/web_app_django/tweet/views.py @@ -69,7 +69,9 @@ def index(request): #print(doc.value[element]) countDomesitc += doc.value[element] countDomesitc += len(countId) + countDomesitc = (countDomesitc/7410000)*100 print(countDomesitc) + context['NswCount'] = countDomesitc #print(docs[doc]['features']) @@ -91,6 +93,8 @@ def index(request): continue else: count += properties[element] + + count = (count/5740000)*100 print(count) context['VicCount'] = count docsSa = SERVER['aurin_sa'] @@ -104,6 +108,7 @@ def index(request): if not properties[element] == None: #print(countForSa) countForSa += properties[element] + countForSa = (countForSa/1677000)*100 print(countForSa) context['SaCount'] = countForSa @@ -111,7 +116,7 @@ def index(request): - docs = SERVER['tweet_2014_raw'] + docs = SERVER['tweet_2014_results'] cityInfoOld = [] cityTotalOld = [] cityPercentageOld = {} @@ -123,7 +128,7 @@ def index(request): for data in cityInfoOld: if data.key == doc.key: number = (data.value/doc.value)*100 - percentage = str(round(number,2))+"%" + percentage = round(number,2) #print(percentage) cityPercentageOld[data.key] = percentage cityTotalOld.append(cityPercentageOld)