diff --git a/Project/cats/cats.py b/Project/cats/cats.py index 1e1b533b..0cbe0484 100644 --- a/Project/cats/cats.py +++ b/Project/cats/cats.py @@ -37,7 +37,25 @@ def pick(paragraphs, select, k): '' """ # BEGIN PROBLEM 1 - "*** YOUR CODE HERE ***" + if k >= len(paragraphs): + return "" + count = 0 + """ + for i in paragraphs: + # print("i is : ", i) + if(select(i)): + count += 1 + if(count - 1 == k): + return i + return '' + """ + for i in range(len(paragraphs)): + if(select(paragraphs[i])): + count += 1 + if(count - 1 == k): + return paragraphs[i] + + return '' # END PROBLEM 1 @@ -57,7 +75,13 @@ def about(subject): assert all([lower(x) == x for x in subject]), "subjects should be lowercase." # BEGIN PROBLEM 2 - "*** YOUR CODE HERE ***" + def f(paragraphs): + for word in split(remove_punctuation(paragraphs)): + # print("word is ",word) + if lower(word) in subject: + return True + return False + return f # END PROBLEM 2 @@ -87,7 +111,17 @@ def accuracy(typed, source): typed_words = split(typed) source_words = split(source) # BEGIN PROBLEM 3 - "*** YOUR CODE HERE ***" + if len(typed_words) == 0 and len(source_words) == 0: + return 100.0 + if len(typed_words) == 0 or len(source_words) == 0: + return 0.0 + n = min(len(typed_words),len(source_words)) + count = 0 + for i in range(n): + # print("type words is : " ,typed_words[i]," source_words : ",source_words[i]) + if(typed_words[i] == source_words[i]): + count += 1 + return count / len(typed_words) * 100 # END PROBLEM 3 @@ -105,7 +139,8 @@ def wpm(typed, elapsed): """ assert elapsed > 0, "Elapsed time must be positive" # BEGIN PROBLEM 4 - "*** YOUR CODE HERE ***" + word_len = len(typed) + return word_len / 5 * 60 / elapsed # END PROBLEM 4 @@ -166,7 +201,18 @@ def autocorrect(typed_word, word_list, diff_function, limit): 'testing' """ # BEGIN PROBLEM 5 - "*** YOUR CODE HERE ***" + fin_word = "" + diff = 1e6 + for word in word_list: + temp = diff_function(typed_word,word,limit) + if word == typed_word : + return typed_word + if abs(temp) < diff: + fin_word = word + diff = abs(temp) + if diff > limit: + return typed_word + return fin_word # END PROBLEM 5 @@ -193,7 +239,15 @@ def furry_fixes(typed, source, limit): 5 """ # BEGIN PROBLEM 6 - assert False, 'Remove this line' + if limit < 0: + return 1 + if len(typed) == 0 or len(source) == 0: + return abs(len(typed) - len(source)) + if typed[0] == source[0]: + return furry_fixes(typed[1:],source[1:],limit) + else: + return 1 + furry_fixes(typed[1:],source[1:],limit - 1) + # END PROBLEM 6 @@ -214,23 +268,24 @@ def minimum_mewtations(typed, source, limit): >>> minimum_mewtations("ckiteus", "kittens", big_limit) # ckiteus -> kiteus -> kitteus -> kittens 3 """ - assert False, 'Remove this line' - if ___________: # Base cases should go here, you may add more base cases as needed. + + + if limit < 0: # Base cases should go here, you may add more base cases as needed. # BEGIN - "*** YOUR CODE HERE ***" + return 1 # END # Recursive cases should go below here - if ___________: # Feel free to remove or add additional cases - # BEGIN - "*** YOUR CODE HERE ***" - # END - else: - add = ... # Fill in these lines - remove = ... - substitute = ... + if len(typed) == 0 or len(source) == 0: # BEGIN - "*** YOUR CODE HERE ***" + return abs(len(typed) - len(source)) # END + if typed[0] == source[0]: + return minimum_mewtations(typed[1:],source[1:],limit) + + add = minimum_mewtations(typed,source[1:],limit - 1) + remove = minimum_mewtations(typed[1:],source,limit - 1) + substitute = minimum_mewtations(typed[1:],source[1:],limit - 1) + return 1 + min(add,remove,substitute) # Ignore the line below @@ -275,7 +330,16 @@ def report_progress(typed, source, user_id, upload): 0.2 """ # BEGIN PROBLEM 8 - "*** YOUR CODE HERE ***" + count = 0 + index = 0 + min_len = min(len(typed),len(source)) + while index < min_len and typed[index] == source[index]: + count += 1 + index += 1 + res = count / len(source) + d = {'id': user_id, 'progress': res} + upload(d) + return res # END PROBLEM 8 @@ -299,7 +363,12 @@ def time_per_word(words, timestamps_per_player): """ tpp = timestamps_per_player # A shorter name (for convenience) # BEGIN PROBLEM 9 - times = [] # You may remove this line + times = [[] for _ in range(len(tpp))] + for i in range(len(tpp)): + j = 0 + while j + 1 < len(tpp[i]): + times[i].append(tpp[i][j + 1] - tpp[i][j]) + j += 1 # END PROBLEM 9 return {'words': words, 'times': times} @@ -326,7 +395,18 @@ def fastest_words(words_and_times): player_indices = range(len(times)) # contains an *index* for each player word_indices = range(len(words)) # contains an *index* for each word # BEGIN PROBLEM 10 - "*** YOUR CODE HERE ***" + fast_word = [[] for _ in player_indices] + for i in word_indices: + play_index = 0 + play_word = words[i] + play_time = times[0][i] + for j in player_indices: + if times[j][i] < play_time: + play_index = j + play_time = times[j][i] + fast_word[play_index].append(play_word) + return fast_word + # END PROBLEM 10 diff --git a/Project/hog/gui_files/.gitignore b/Project/hog/gui_files/.gitignore new file mode 100644 index 00000000..72e8ffc0 --- /dev/null +++ b/Project/hog/gui_files/.gitignore @@ -0,0 +1 @@ +* diff --git a/Project/hog/gui_files/__init__.py b/Project/hog/gui_files/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Project/hog/gui_files/__init__.py @@ -0,0 +1 @@ + diff --git a/Project/hog/gui_files/__pycache__/__init__.cpython-38.pyc b/Project/hog/gui_files/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 00000000..fe91e8a0 Binary files /dev/null and b/Project/hog/gui_files/__pycache__/__init__.cpython-38.pyc differ diff --git a/Project/hog/gui_files/__pycache__/common_server.cpython-38.pyc b/Project/hog/gui_files/__pycache__/common_server.cpython-38.pyc new file mode 100644 index 00000000..c990d51d Binary files /dev/null and b/Project/hog/gui_files/__pycache__/common_server.cpython-38.pyc differ diff --git a/Project/hog/gui_files/common_server.py b/Project/hog/gui_files/common_server.py new file mode 100644 index 00000000..ccbe8b81 --- /dev/null +++ b/Project/hog/gui_files/common_server.py @@ -0,0 +1,303 @@ +import argparse +import json +import socketserver +import ssl +import time +import traceback +import webbrowser +import os +from functools import wraps +from http import HTTPStatus, server +from http.server import HTTPServer +from urllib.error import URLError +from urllib.parse import unquote, urlparse, parse_qs +from urllib.request import Request, urlopen + +STATIC_PATHS = {} +PATHS = {} +# +CONTENT_TYPE_LOOKUP = dict( + html="text/html", + css="text/css", + js="application/javascript", + svg="image/svg+xml", + gif="image/gif", + ico="image/x-icon", +) + + +def path_optional(decorator): + def wrapped(func_or_path): + if callable(func_or_path): + return decorator("/" + func_or_path.__name__)(func_or_path) + else: + + def actual_decorator(f): + return decorator(func_or_path)(f) + + return actual_decorator + + return wrapped + + +def route(path): + """Register a route handler.""" + + if callable(path): + return route("/" + path.__name__)(path) + + if not path.startswith("/"): + path = "/" + path + + def wrap(f): + if "." in path: + STATIC_PATHS[path] = f + else: + PATHS[path] = f + return f + + return wrap + + +class Handler(server.BaseHTTPRequestHandler): + """HTTP handler.""" + + def do_GET(self): + try: + parsed_url = urlparse(unquote(self.path)) + path = parsed_url.path + query_params = parse_qs(parsed_url.query) + + if path in STATIC_PATHS: + out = bytes(STATIC_PATHS[path](**snakify(query_params)), "utf-8") + else: + path = GUI_FOLDER + path[1:] + if "scripts" in path and not path.endswith(".js"): + path += ".js" + if path == GUI_FOLDER: + path = GUI_FOLDER + "index.html" + with open(path, "rb") as f: + out = f.read() + except FileNotFoundError: + self.send_response(HTTPStatus.NOT_FOUND) + self.end_headers() + except Exception as e: + print(e) + self.send_response(HTTPStatus.INTERNAL_SERVER_ERROR) + self.end_headers() + else: + self.send_response(HTTPStatus.OK) + self.send_header("Content-type", CONTENT_TYPE_LOOKUP[path.split(".")[-1]]) + self.end_headers() + self.wfile.write(out) + + def do_POST(self): + content_length = int(self.headers["Content-Length"]) + raw_data = self.rfile.read(content_length).decode("utf-8") + data = json.loads(raw_data) + path = unquote(self.path) + + try: + result = PATHS[path](**snakify(data)) + except Exception as e: + print(e) + self.send_response(HTTPStatus.INTERNAL_SERVER_ERROR) + self.end_headers() + raise + else: + self.send_response(HTTPStatus.OK) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(bytes(json.dumps(result), "utf-8")) + + def log_message(self, *args, **kwargs): + pass + + +class Server: + def __getattr__(self, item): + def f(**kwargs): + if IS_SERVER: + return PATHS["/" + item](**kwargs) + else: + return multiplayer_post(item, kwargs) + + return f + + +Server = Server() + + +def multiplayer_post(path, data, server_url=None): + """Post DATA to a multiplayer server PATH and return the response.""" + if not server_url: + server_url = DEFAULT_SERVER + data_bytes = bytes(json.dumps(data), encoding="utf-8") + request = Request(server_url + "/" + path, data_bytes, method="POST") + try: + response = urlopen(request, context=ssl._create_unverified_context()) + text = response.read().decode("utf-8") + if text.strip(): + return json.loads(text) + except Exception as e: + traceback.print_exc() + print(e) + return None + + +def multiplayer_route(path, server_path=None): + """Convert a function that takes (data, send) into a route.""" + if not server_path: + server_path = path + + def wrap(f): + def send(data): + return multiplayer_post(server_path, data) + + def routed_fn(data): + response = f(data, send) + return response + + route(path)(routed_fn) + return f + + return wrap + + +@path_optional +def forward_to_server(path): + def wrap(f): + @wraps(f) + def wrapped(*args, **kwargs): + if IS_SERVER: + return f(*args, **kwargs) + else: + return multiplayer_post(path, kwargs) + + return wrapped + + return wrap + + +def server_only(f): + @wraps(f) + def wrapped(*args, **kwargs): + if IS_SERVER: + return f(*args, **kwargs) + else: + raise Exception("Method not available locally!") + + return wrapped + + +def sendto(f): + def wrapped(data): + return f(**data) + + return wrapped + + +def start_server(): + global IS_SERVER + IS_SERVER = True + from flask import Flask, request, jsonify, send_from_directory, Response + + app = Flask(__name__, static_url_path="", static_folder="") + for route, handler in PATHS.items(): + + def wrapped_handler(handler=handler): + return jsonify(handler(**snakify(request.get_json(force=True)))) + + app.add_url_rule(route, handler.__name__, wrapped_handler, methods=["POST"]) + + for route, handler in STATIC_PATHS.items(): + + def wrapped_handler(route=route, handler=handler): + query_params = parse_qs(request.query_string.decode()) + return Response( + handler(**snakify(query_params)), + mimetype=CONTENT_TYPE_LOOKUP[route.split(".")[-1]], + ) + + app.add_url_rule( + route, handler.__name__ + route, wrapped_handler, methods=["GET"] + ) + + @app.route("/") + def index(): + return send_from_directory("", "index.html") + + return app + + +def start_client(port, default_server, gui_folder, standalone): + """Start web server.""" + global DEFAULT_SERVER, GUI_FOLDER, IS_SERVER + DEFAULT_SERVER = default_server + GUI_FOLDER = gui_folder + IS_SERVER = False + + socketserver.TCPServer.allow_reuse_address = True + httpd = HTTPServer(("localhost", port), Handler) + if not standalone: + webbrowser.open("http://localhost:" + str(port), new=0, autoraise=True) + try: + httpd.serve_forever() + except KeyboardInterrupt: + httpd.socket.close() + + +def snakify(data): + out = {} + for key, val in data.items(): + snake_key = [] + for x in key: + if x != x.lower(): + snake_key += "_" + snake_key += x.lower() + out["".join(snake_key)] = val + return out + + +@route("/kill") +def kill(): + if not IS_SERVER: + print("Exiting GUI") + exit(0) + + +def start(port, default_server, gui_folder, db_init=None): + global DEFAULT_SERVER + DEFAULT_SERVER = default_server + + parser = argparse.ArgumentParser(description="Project GUI Server") + parser.add_argument( + "-s", help="Stand-alone: do not open browser", action="store_true" + ) + parser.add_argument("-f", help="Force Flask app", action="store_true") + args, unknown = parser.parse_known_args() + + import __main__ + + if "gunicorn" not in os.environ.get("SERVER_SOFTWARE", "") and not args.f: + request = Request( + "http://127.0.0.1:{}/kill".format(port), + bytes(json.dumps({}), encoding="utf-8"), + method="POST", + ) + try: + urlopen(request) + print("Killing existing gui process...") + time.sleep(1) + except URLError: + pass + + start_client(port, default_server, gui_folder, args.s) + else: + if db_init: + db_init() + app = start_server() + if args.f: + app.run(port=port, threaded=False, processes=1) + else: + return app diff --git a/Project/hog/gui_files/empty.py b/Project/hog/gui_files/empty.py new file mode 100644 index 00000000..e69de29b diff --git a/Project/hog/gui_files/favicon.gif b/Project/hog/gui_files/favicon.gif new file mode 100644 index 00000000..6d6ed815 Binary files /dev/null and b/Project/hog/gui_files/favicon.gif differ diff --git a/Project/hog/gui_files/index.html b/Project/hog/gui_files/index.html new file mode 100644 index 00000000..431f094c --- /dev/null +++ b/Project/hog/gui_files/index.html @@ -0,0 +1 @@ +
P(o,n))void 0!==u&&0>P(u,o)?(e[r]=u,e[l]=n,r=l):(e[r]=o,e[i]=n,r=i);else{if(!(void 0!==u&&0>P(u,n)))break e;e[r]=u,e[l]=n,r=l}}}return t}return null}function P(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var _=[],N=[],j=1,R=null,I=3,A=!1,D=!1,L=!1;function F(e){for(var t=C(N);null!==t;){if(null===t.callback)O(N);else{if(!(t.startTime<=e))break;O(N),t.sortIndex=t.expirationTime,T(_,t)}t=C(N)}}function z(e){if(L=!1,F(e),!D)if(null!==C(_))D=!0,r(M);else{var t=C(N);null!==t&&a(z,t.startTime-e)}}function M(e,n){D=!1,L&&(L=!1,i()),A=!0;var r=I;try{for(F(n),R=C(_);null!==R&&(!(R.expirationTime>n)||e&&!o());){var l=R.callback;if(null!==l){R.callback=null,I=R.priorityLevel;var u=l(R.expirationTime<=n);n=t.unstable_now(),"function"===typeof u?R.callback=u:R===C(_)&&O(_),F(n)}else O(_);R=C(_)}if(null!==R)var c=!0;else{var s=C(N);null!==s&&a(z,s.startTime-n),c=!1}return c}finally{R=null,I=r,A=!1}}function U(e){switch(e){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var W=l;t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){D||A||(D=!0,r(M))},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_getFirstCallbackNode=function(){return C(_)},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=W,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_scheduleCallback=function(e,n,o){var l=t.unstable_now();if("object"===typeof o&&null!==o){var u=o.delay;u="number"===typeof u&&0l?(e.sortIndex=u,T(N,e),null===C(_)&&e===C(N)&&(L?i():L=!0,a(z,u-l))):(e.sortIndex=o,T(_,e),D||A||(D=!0,r(M))),e},t.unstable_shouldYield=function(){var e=t.unstable_now();F(e);var n=C(_);return n!==R&&null!==R&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime