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>&nbsp;</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)