diff --git a/Test/__pycache__/test_one.cpython-39.pyc b/Test/__pycache__/test_one.cpython-39.pyc
deleted file mode 100644
index 71c41fd540580ef134734179b3304732ca9a4e7e..0000000000000000000000000000000000000000
Binary files a/Test/__pycache__/test_one.cpython-39.pyc and /dev/null differ
diff --git a/Test/manualtestplan.pdf b/Test/manualtestplan.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..6456f68175b8d1bde5430333d007ecf7763eca20
Binary files /dev/null and b/Test/manualtestplan.pdf differ
diff --git a/Test/key.env b/src/.env
similarity index 100%
rename from Test/key.env
rename to src/.env
diff --git a/src/api.py b/src/api.py
index 609aa7928205cd777a6bc78f8268b9ed5d84b9a6..dacac10c9dffe092e11ca2181334dfd6bbec8faf 100644
--- a/src/api.py
+++ b/src/api.py
@@ -9,12 +9,67 @@ import requests
 import json
 import pymongo
 import argparse
-from flask import Flask, request, jsonify, render_template
+from query_parser import Query
+from flask import Flask, request, jsonify, render_template, send_from_directory
 from database import get_key, get_collection, valid_champ
 
 
-app = Flask(__name__)
+app = Flask(__name__, static_folder="static")
 
+@app.route('/')
+def home():
+    #file_template = send_from_directory('client', "index.html")
+    #return render_template("index.html")
+    return send_from_directory('templates', "index.html")
+
+@app.route('/PRVisual')
+def pr_champ_vis():
+    #file_template = send_from_directory('client', "index.html")
+    #return render_template("index.html")
+    return send_from_directory('templates', "pr_champion_visual.html")
+
+@app.route('/WRVisual')
+def wr_champ_vis():
+    #file_template = send_from_directory('client', "index.html")
+    #return render_template("index.html")
+    return send_from_directory('templates', "wr_champion_visual.html")
+
+
+"""GET request for search and a query."""
+@app.route('/search')
+def get_search():
+    query = request.args.get("q") # @UndefinedVariable
+    query_parse = Query()
+    
+    if query is None or len(request.args) > 1:
+        bad_input_error = {
+                "status": 400,
+                "error":"Bad Request"
+                }
+        
+        return bad_input_error
+    
+    query_info = query_parse.parse_user_input(query)
+    query_result = query_parse.query_handler(query_info[0], query_info[1], query_info[2])
+    if not query_result:
+        error = {
+                "status": 500,
+                "error":"Internal Server Error",
+                "message":"No entries found with given query"
+                }
+        
+        return error
+        
+    query_result_cleaned = []
+    
+    for i in query_result:
+        tmp = {}
+        for j in i.keys():
+            if j != "_id":
+                tmp[j] = i[j]
+        query_result_cleaned.append(tmp)
+    
+    return  jsonify({'result' : query_result_cleaned})
 @app.route('/champions', methods=['GET'])
 def getAllChampions():
     """
@@ -130,3 +185,6 @@ def delete_champion():
     
     return "deleted champion with name " + _id
 
+if __name__ == '__main__':
+    app.run(debug=False)
+
diff --git a/src/database.py b/src/database.py
index f21622d03304bcaff2c27dad19382fd70121f90c..6f91a9646faa402876876455ad40102e87880716 100644
--- a/src/database.py
+++ b/src/database.py
@@ -13,7 +13,8 @@ def get_key():
     be in src in terminal
     """
     load_dotenv('./key.env')
-    return os.getenv("SECRET_KEY")
+    #return os.getenv("SECRET_KEY")
+    return "mongodb+srv://JohnIm:4MY7jaApcsPmj4Kl@cluster0.0fsik.mongodb.net/Cluster0?ssl=true&ssl_cert_reqs=CERT_NONE"
 
 def database_handler(ret_arr1):
     """
diff --git a/src/query_parser.py b/src/query_parser.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9aaa90e55eca60bda010d0c63a6478c81c97125
--- /dev/null
+++ b/src/query_parser.py
@@ -0,0 +1,152 @@
+import re
+from database import get_collection
+class Query(object):
+    '''
+    classdocs
+    '''
+
+
+    def __init__(self):
+        print("query start")
+        
+    def parse_user_input(self, input_string):
+        form = re.compile(r"^[a-zA-Z]+\.[a-zA-Z\_]+\:.*$")
+        f = re.search(form, input_string)
+        if f is None:
+            raise ValueError('bad format, q not in form of obj.field:content')
+        
+        
+        obj_pattern = re.compile(r"^[a-zA-Z]+\.")
+        obj = re.search(obj_pattern, input_string)
+        
+        if obj is None:
+            raise ValueError('Object:bad format')
+        else:
+            obj = obj.group(0)
+            
+        field_pattern = re.compile(r"\.[a-zA-Z\_]+\:")
+        field = re.findall(field_pattern, input_string)
+        
+        if field is None:
+            raise ValueError('field, invalid format')
+        elif len(field) > 1:
+            raise ValueError('too many operators')
+        else:
+            field = field[0]
+        field_value_pattern = re.compile(r'\:((\s[>,<]{1}\s[0-9]+)|(\"[a-zA-Z0-9]+\")|([a-zA-Z0-9]+\s[a-zA-Z0-9]*)|(\sNOT\s[a-zA-Z0-9]+)|([a-zA-Z0-9]+\sAND\s[a-zA-Z0-9]+)|([a-zA-Z0-9]+\sOR\s[a-zA-Z0-9]+))$')
+        content = re.search(field_value_pattern, input_string)
+        
+        if content is None:
+            raise ValueError('content invalid format, [<,>] operators should be used with numbers, AND, NOT, OR needs keywords')
+        else:
+            content = content.group(0)
+    
+        return obj, field, content
+    
+    def valid_parse(self, obj, field):
+        obj_tmp = obj.replace('.',"")
+        obj_tmp = obj_tmp.strip()
+        
+        if obj_tmp != "champion":
+            raise ValueError('Object, bad value')
+        
+        
+        
+        field_tmp = field.replace('.',"")
+        field_tmp = field_tmp.replace(':',"")
+        field_tmp = field_tmp.strip()
+        
+        model_dict = {"name": "Lex",
+                "win_rate" : "79%",
+                "pick_rate" : "48%",
+                "champ_tier" : "Tier 4",
+                "counter_champs" : ["Azir","Yasuo", "Yone"],
+                "strong_against" : ["Zed", "Akali", "Alistar"],
+                }
+        
+        if obj_tmp == "champion" and field_tmp not in model_dict.keys():
+            raise ValueError('Field, bad value for author')
+        
+        return None
+    
+    def query_handler(self, obj, field, content):
+        self.valid_parse(obj, field)
+        obj = obj.replace('.',"")
+        obj = obj.strip()
+        
+        field = field.replace('.',"")
+        field = field.replace(':',"")
+        field = field.strip()
+        content = content.replace(":","")
+        print(obj, field, content)
+        print(content)
+        if "<" in content:
+            return self.handle_less(obj, field, content)
+        elif ">" in content:
+            return self.handle_greater(obj, field, content)
+        elif '"' in content:
+            return self.handle_quotes(obj, field, content)
+        elif "AND" in content:
+            return self.handle_and(obj, field, content)
+        elif "OR" in content:
+            return self.handle_or(obj, field, content)
+        elif "NOT" in content:
+            return self.handle_not(obj, field, content)
+        else:
+            return self.handle_standard(obj, field, content)
+        
+    def is_num(self, input_string):
+        for c in input_string:
+            if c.isdigit():
+                input_string = int(input_string)
+                return input_string
+        return input_string
+        
+    def clean_content(self, content, tmp):
+        cont = content.replace(tmp,"")
+        cont = cont.strip()
+        return cont
+    
+    def handle_greater(self, obj, field, content):
+        tmp = ">"
+        cont = self.clean_content(content,tmp)
+        collection_list = []
+        collection = self.get_collection(obj)
+        
+        for i in collection.find():
+            if int(i[field]) > int(cont):
+                collection_list.append(i)
+                
+        return collection_list
+    
+    def handle_less(self, obj, field, content):
+        tmp = "<"
+        cont = self.clean_content(content,tmp)
+        collection_list = []
+        collection = self.get_collection(obj)
+        
+        for i in collection.find():
+            if float(i[field].strip('%')) < float(cont):
+                collection_list.append(i)
+        return collection_list
+    
+    
+    def handle_standard(self,obj, field, content):
+        cont = content
+        collection_list = []
+        collection = self.get_collection(obj)
+        
+        for i in collection.find():
+            if cont in i[field]:
+                collection_list.append(i)
+            
+        return collection_list
+    
+    def get_collection(self, obj):
+        return get_collection()
+    
+if __name__ == '__main__':
+    D = Query()
+    obj, f, c = D.parse_user_input('champion.win_rate: < 79')
+    print(obj, f, c)
+    print(D.query_handler(obj, f, c))
\ No newline at end of file
diff --git a/src/scraper.py b/src/scraper.py
index e6ab765ab6f728025cd1f046961fc1536764511b..3314a094296bf0a00a87b137def00228683f9bf1 100644
--- a/src/scraper.py
+++ b/src/scraper.py
@@ -9,7 +9,8 @@ class Scraper:
     #This Function is the Constructor of the Scrape Class
     def __init__(self):
         print("scraper start")
-    
+    #got help from https://stackoverflow.com/questions/53652731/getting-http-404-error-when-web-scraping-in-python-3-7 for the headers for user-agent
+    #https://stackoverflow.com/questions/61991072/getting-error-404-while-scraping-using-beautiful-soup-even-though-the-site-exis
     #this function scrapes the links of all champion pages of all the champions on op.gg
     def scrape_champion_links(self):
         url = 'https://na.op.gg/champion/statistics'
diff --git a/src/static/script.js b/src/static/script.js
new file mode 100644
index 0000000000000000000000000000000000000000..71528b4f098eaaae086833c7f9c9cc80cd815400
--- /dev/null
+++ b/src/static/script.js
@@ -0,0 +1,141 @@
+function handleGetChamp(name) {
+	console.log(name)
+	var u = "http://127.0.0.1:5000/champion?name="+name
+	console.log(u)
+	fetch(u)
+		.then(response => {
+		console.log(response)
+			if (!response.ok) {
+				throw Error("ERROR");
+			}
+			return response.json();
+    	}).then(data=> {
+    		console.log(data)
+				var counters = data.map(counterChamps => {
+					temp = []
+					for (x = 0; x < counterChamps.counter_champs.length; x++) {
+						temp.push(`<p>counter_champs : ` + counterChamps.counter_champs[x]  + `</p>`)
+					}
+	                return temp
+	            });
+	            var strong = data.map(strongChamps => {
+					temp2 = []
+					for (x = 0; x < strongChamps.counter_champs.length; x++) {
+						temp.push(`<p>strong_against : ` + strongChamps.strong_against[x]  + `</p>`)
+					}
+	                return temp2
+	            });
+				const html = data.map(champ => {
+					var s = '<p>name : ' + champ.name + '</p>'
+					+ '<p>win_rate : ' + champ.win_rate + '</p>'
+					+ '<p>pick_rate : ' + champ.pick_rate + '</p>'
+					+ '<p>champ_tier : ' + champ.champ_tier + '</p>'
+					return s + temp + temp2;
+				});
+			document.querySelector('#championGet').innerHTML = "";
+			document.querySelector('#championGet').insertAdjacentHTML('afterbegin', html);
+		}).catch(error=> {
+			const returnObject = '<p>Error: ' + 'Not a valid name' + '</p>'
+			document.querySelector('#championGet').insertAdjacentHTML('afterbegin', returnObject);
+		});	
+}
+
+function handleGetQuery(querystring) {
+	var u = "http://127.0.0.1:5000/search?q=" + querystring
+	console.log(u)
+	var dict = [];
+	fetch(u)
+		.then(response => {
+			if (!response.ok) {
+				throw Error("ERROR");
+			}
+			return response.json();
+    	}).then(data=> {
+			console.log(data)
+			for (x = 0; x < data.result.length; x++) {
+				var counters = data.result.map(counterChamps => {
+					temp = []
+					for (x = 0; x < counterChamps.counter_champs.length; x++) {
+						temp.push(`<p>counter_champs : ` + counterChamps.counter_champs[x]  + `</p>`)
+					}
+	                return temp
+	            });
+	            var strong = data.result.map(strongChamps => {
+					temp2 = []
+					for (x = 0; x < strongChamps.counter_champs.length; x++) {
+						temp.push(`<p>strong_against : ` + strongChamps.strong_against[x]  + `</p>`)
+					}
+	                return temp2
+	            });
+				const html = data.result.map(champ => {
+					var s = '<p>name : ' + champ.name + '</p>'
+					+ '<p>win_rate : ' + champ.win_rate + '</p>'
+					+ '<p>pick_rate : ' + champ.pick_rate + '</p>'
+					+ '<p>champ_tier : ' + champ.champ_tier + '</p>'
+					return s + temp + temp2;
+				});
+				document.querySelector('#championGet').innerHTML = "";
+				document.querySelector('#championGet').insertAdjacentHTML('afterbegin', html);
+			}
+		}).catch(error=> {
+			console.log(error)
+			const returnObject = '<p>Error: ' + 'Not a valid name' + '</p>'
+			document.querySelector('#championGet').insertAdjacentHTML('afterbegin', returnObject);
+		});	
+}
+
+function test(querystring) {
+	var u = "http://127.0.0.1:5000/search?q=" + querystring
+	console.log(u)
+	var dict = [];
+	fetch(u)
+		.then(response => {
+			if (!response.ok) {
+				throw Error("ERROR");
+			}
+			return response.json();
+    	}).then(data=> {
+			console.log(data)
+			for (x = 0; x < data.result.length; x++) {
+				const html = data.result.map(champ => {
+					dict.push({
+					name : champ.name,
+					win_rate : champ.win_rate,
+					pick_rate : champ.pick_rate,
+					champ_tier : champ.champ_tier
+					})
+				});
+				addTable(dict)
+			}
+		})
+}
+					
+function addTable(arr2) {
+  arr = arr2
+  setTimeout(function(){
+	  var myTableDiv = document.getElementById("myDynamicTable");
+	
+	  var table = document.createElement('TABLE');
+	  table.border = '1';
+	
+	  var tableBody = document.createElement('TBODY');
+	  table.appendChild(tableBody);
+	
+	  for (var i = 0; i < 3; i++) {
+	    var tr = document.createElement('TR');
+	    tableBody.appendChild(tr);
+	    for (var j = 0; j < 4; j++) {
+	      var td = document.createElement('TD');
+	      td.width = '75';
+	      td.appendChild(document.createTextNode(arr[j]['name']));
+	      tr.appendChild(td);
+	    }
+	  }
+	  myTableDiv.appendChild(table);
+	  }, 5000);
+}
+
+
+function clearValues() {
+	document.querySelector('#championGet').innerHTML = "";
+}
diff --git a/src/templates/index.html b/src/templates/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..beb30977865faffffaa3c811d18b1964473c9832
--- /dev/null
+++ b/src/templates/index.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+	<head>
+		<title>Start Page</title>
+	</head>
+	<body>
+		<h1> A League of Legends Statistics Website</h1><br>
+		<nav>
+			<a href="/PRVisual">Top Champions by Pick Rate</a> |
+			<a href="/WRVisual">Top Champions by Win Rate</a>
+		</nav><br><br>
+		 <form>
+	  		  <label>Champion Name:</label><br><br>
+	
+			  <input type="text" id="field" name="name" style="height:50px; width:712px"><br><br>
+			  <button type = "button" onclick="handleGetChamp(field.value)" style="height:50px; width:720px">Get Champ</button><br><br><br><br>
+			  <label>Query (Ex : champion.win_rate: > 55):</label><br><br>
+			  <input type="text" id="field2" name="wr" style="height:50px; width:712px"><br><br>
+			  <button type = "button" onclick="test(field2.value)" style="height:50px; width:720px">Get Query</button><br><br><br><br>
+			  <button type = "button" onclick="clearValues()" style="height:50px; width:720px">Clear Results</button><br><br>
+		  </form>
+		<table>
+		<thead></thead>
+		<tbody></tbody>
+		</table>
+		<h1> Results Below </h1>
+		<div id="championGet"></div>
+		<div id="myDynamicTable"></div>
+	</body>
+	<script src="../static/script.js"></script>
+</html>
\ No newline at end of file
diff --git a/src/templates/pr_champion_visual.html b/src/templates/pr_champion_visual.html
new file mode 100644
index 0000000000000000000000000000000000000000..dfe217fa5cc8ab04efadc3ced80edda7e8918478
--- /dev/null
+++ b/src/templates/pr_champion_visual.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+	<head>
+		<title>Pick Rate Page</title>
+	</head>
+	<body>
+		<h1> Top k Champions by Pick Rate </h1>
+		<nav>
+			<a href="/">homepage</a> 
+			
+		</nav>
+		<h1>Pick k below</h1>
+		<label>k:</label>
+		<input type="text" id="k" name="k"><br><br>
+		<button>Generate Graph</button>
+			  
+	</body>
+</html>
\ No newline at end of file
diff --git a/src/templates/wr_champion_visual.html b/src/templates/wr_champion_visual.html
new file mode 100644
index 0000000000000000000000000000000000000000..8edde44fccc2a6a58586d7bba32e29ae6df9d83a
--- /dev/null
+++ b/src/templates/wr_champion_visual.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+	<head>
+		<title>Win Rate Page</title>
+	</head>
+	<body>
+		<h1> Top k Champions by Win Rate </h1>
+		<nav>
+			<a href="/">homepage</a> 
+			
+		</nav>
+		<h1>Pick k below</h1>
+		<label>k:</label>
+		<input type="text" id="k" name="k"><br><br>
+		<button>Generate Graph</button>
+			  
+	</body>
+</html>
\ No newline at end of file