cs 220 project 6

profileanaaa121212
p6_test.py

#!/usr/bin/python import os, json, math MAX_FILE_SIZE = 500 # units - KB REL_TOL = 6e-04 # relative tolerance for floats ABS_TOL = 15e-03 # absolute tolerance for floats PASS = "PASS" TEXT_FORMAT = "text" # question type when expected answer is a str, int, float, or bool TEXT_FORMAT_NAMEDTUPLE = "text namedtuple" # question type when expected answer is a namedtuple TEXT_FORMAT_UNORDERED_LIST = "text list_unordered" # question type when the expected answer is a list where the order does *not* matter TEXT_FORMAT_ORDERED_LIST = "text list_ordered" # question type when the expected answer is a list where the order does matter TEXT_FORMAT_ORDERED_LIST_NAMEDTUPLE = "text list_ordered namedtuple" # question type when the expected answer is a list of namedtuples where the order does matter TEXT_FORMAT_SPECIAL_ORDERED_LIST = "text list_special_ordered" # question type when the expected answer is a list where order does matter, but with possible ties. Elements are ordered according to values in special_ordered_json (with ties allowed) TEXT_FORMAT_DICT = "text dict" # question type when the expected answer is a dictionary TEXT_FORMAT_LIST_DICTS_ORDERED = "text list_dicts_ordered" # question type when the expected answer is a list of dicts where the order does matter expected_json = {"1": (TEXT_FORMAT_UNORDERED_LIST, ['Brooklyn', 'Manhattan', 'Queens', 'Staten Island', 'Bronx']), "2": (TEXT_FORMAT, 152.7206871868289), "3": (TEXT_FORMAT, 358), "4": (TEXT_FORMAT_UNORDERED_LIST,['One Bedroom Mini studio - Free WIFI', 'Great Chelsea Location, Couch/2nd bed, Free WiFi', 'Private 2 BR APT: Free WIFI & JACUZZI', 'PRIVATE 1BR APT: Free WIFI & DIRECT TV', 'Landmark 1 Bedroom has 2 beds, Free WiFi', 'Modern and Safe Place,Free Wifi', 'Newly renovated 2 bedroom with FREE WIFI', '*NO GUEST SERVICE FEE* Beekman Tower Studio with Queen Bed & Free Wifi', '*NO GUEST SERVICE FEE* Beekman Tower One Bedroom Suite with Queen Bed & Free Wifi', 'Sunny Hudson Yards/ Chelsea Studio, Free WiFi', 'Private Bedroom in MANHATTAN (Free Wifi)', 'J- LUXURY SHARED ROOM, AC FREE WIFI+CABLE GARDEN', 'J- *LUXURY SHARED ROOM AC FREE WIFI CABLE, GARDEN', 'J- **LUXURY SHARED ROOM 2PPL FREE WIFI+CABLE+AC', '5min walk to L train - Free WiFi & Cleaning', 'J- HOTEL STYLE SHARE ROOM FOR 2PPL FREE WIFI CABLE', 'Explore NYC From Our Private Studio w/Free Wifi', 'Staten Island - Free Wifi, Parking Space, Near NYC', 'BIG BEDROOM CLOSE TO LA GUARDIA AIRPORT FREE WIFI', 'J- COZY ROOM FOR 1 FEMALE FREE WIFI & COFFEE']), "5": (TEXT_FORMAT_UNORDERED_LIST, ['HUGE LUX 2FLOOR 2 BDRMSOHO LOFTw/HOME CINEMA', 'Cinema Studio on Duplex Apt.', 'Cool apartment in Brooklyn with free cinema & gym', 'Cinema + gym included with room', 'TV-PHOTO-FILM-CINEMA-ART GALLERY-MUSIC STUDIO-LOFT', 'Premium Chelsea 1BR w/ Gym, W/D, Doorman, Sundeck, Cinema, by Blueground', 'Stunning Chelsea 1BR w/ Gym, W/D, Doorman, Sundeck, Cinema, by Blueground', 'Sunny private room featured in film', "Downtown Filmmaker's Loft by WTC", 'Film Location', 'Brooklyn townhouse for filming', 'WoodyAllen FilmSet-Like Digs (Apt)', 'WoodyAllen FilmSet-Like Digs (Room)', 'Film / photography location in unique apartment', 'The Otheroom Bar/Event/Filming Space -read details', 'Victorian Film location', 'Modern Townhouse for Photo, Film & Daytime Events', 'Shoot. Film. Sleep. Unique Loft Space in Brooklyn.', 'Clean music/film themed bedroom', 'Music Recording Mixing Film Photography Art']), "6": (TEXT_FORMAT, 'Homey 1BR in Fun, Central West Village w/ Doorman by Blueground'), "7": (TEXT_FORMAT_ORDERED_LIST, ['Contemporary bedroom in brownstone with nice view', 'Cozy yet spacious private brownstone bedroom', 'Spacious comfortable master bedroom with nice view']), "8": (TEXT_FORMAT_ORDERED_LIST, ['Upper West Side', 'Greenpoint', 'Astoria']), "9": (TEXT_FORMAT, 1672), "10": (TEXT_FORMAT, 65.0), "11": (TEXT_FORMAT, 46.02133741379495), "12": (TEXT_FORMAT, 75), "13": (TEXT_FORMAT, 100), "14": (TEXT_FORMAT, 93.10344827586206), "15": (TEXT_FORMAT, 0.9856466156705752), "16": (TEXT_FORMAT, 0.27323293295076073), "17": (TEXT_FORMAT, 'Arden Heights'), "18": (TEXT_FORMAT_UNORDERED_LIST,['Cute & Cozy Lower East Side 1 bdrm', 'QT STUDIO FOR ROMANTIC COUPLES', 'Lower East Side 1bedroom apt in NYC', 'Two Bridges District Chinatown NYC', 'Fun LES 1br, close to everything!', 'Amazing Downtown With Rooftop', 'Sunny Central Location!', 'Cozy Apartment in Lower Manhattan', 'Gorgeous Loft in the LES/Chinatown!', 'Spacious 2 Bedroom Lower East Side', 'Lovely 2-bedroom 1bath in Chinatown & Little Italy']), "19": (TEXT_FORMAT_UNORDERED_LIST, ['PRIVATE Room on Historic Sugar Hill', 'Bright Room With A Great River View', '1 Pvt. Room in Upper West Manhattan']), "20": (TEXT_FORMAT, 30)} special_ordered_json = {} def check_cell_text(qnum, actual): format, expected = expected_json[qnum[1:]] try: if format == TEXT_FORMAT: return simple_compare(expected, actual) elif format in [TEXT_FORMAT_ORDERED_LIST, TEXT_FORMAT_LIST_DICTS_ORDERED]: return list_compare_ordered(expected, actual) elif format == TEXT_FORMAT_UNORDERED_LIST: return list_compare_unordered(expected, actual) elif format == TEXT_FORMAT_SPECIAL_ORDERED_LIST: return list_compare_special(expected, actual, special_ordered_json[qnum[1:]]) elif format == TEXT_FORMAT_DICT: return dict_compare(expected, actual) else: if expected != actual: return "expected %s but found %s " % (repr(expected), repr(actual)) except: if expected != actual: return "expected %s" % (repr(expected)) return PASS def simple_compare(expected, actual, complete_msg=True): msg = PASS if type(expected) == type: if expected != actual: if type(actual) == type: msg = "expected %s but found %s" % (expected.__name__, actual.__name__) else: msg = "expected %s but found %s" % (expected.__name__, repr(actual)) elif type(expected) != type(actual) and not (type(expected) in [float, int] and type(actual) in [float, int]): msg = "expected to find type %s but found type %s" % (type(expected).__name__, type(actual).__name__) elif type(expected) == float: if not math.isclose(actual, expected, rel_tol=REL_TOL, abs_tol=ABS_TOL): msg = "expected %s" % (repr(expected)) if complete_msg: msg = msg + " but found %s" % (repr(actual)) else: if expected != actual: msg = "expected %s" % (repr(expected)) if complete_msg: msg = msg + " but found %s" % (repr(actual)) return msg def list_compare_ordered(expected, actual, obj="list"): msg = PASS if type(expected) != type(actual): msg = "expected to find type %s but found type %s" % (type(expected).__name__, type(actual).__name__) return msg for i in range(len(expected)): if i >= len(actual): msg = "expected missing %s in %s" % (repr(expected[i]), obj) break if type(expected[i]) in [int, float, bool, str]: val = simple_compare(expected[i], actual[i]) elif type(expected[i]) in [list]: val = list_compare_ordered(expected[i], actual[i], "sub" + obj) elif type(expected[i]) in [dict]: val = dict_compare(expected[i], actual[i]) elif type(expected[i]).__name__ == obfuscate1(): val = simple_compare(expected[i], actual[i]) if val != PASS: msg = "at index %d of the %s, " % (i, obj) + val break if len(actual) > len(expected) and msg == PASS: msg = "found unexpected %s in %s" % (repr(actual[len(expected)]), obj) if len(expected) != len(actual): msg = msg + " (found %d entries in %s, but expected %d)" % (len(actual), obj, len(expected)) if len(expected) > 0 and type(expected[0]) in [int, float, bool, str]: if msg != PASS and list_compare_unordered(expected, actual, obj) == PASS: try: msg = msg + " (list may not be ordered as required)" except: pass return msg def list_compare_helper(larger, smaller): msg = PASS j = 0 for i in range(len(larger)): if i == len(smaller): msg = "expected %s" % (repr(larger[i])) break found = False while not found: if j == len(smaller): val = simple_compare(larger[i], smaller[j - 1], False) break val = simple_compare(larger[i], smaller[j], False) j += 1 if val == PASS: found = True break if not found: msg = val break return msg def list_compare_unordered(expected, actual, obj="list"): msg = PASS if type(expected) != type(actual): msg = "expected to find type %s but found type %s" % (type(expected).__name__, type(actual).__name__) return msg try: sort_expected = sorted(expected) sort_actual = sorted(actual) except: msg = "unexpected datatype found in %s; expected entries of type %s" % (obj, obj, type(expected[0]).__name__) return msg if len(actual) == 0 and len(expected) > 0: msg = "in the %s, missing" % (obj) + expected[0] elif len(actual) > 0 and len(expected) > 0: val = simple_compare(sort_expected[0], sort_actual[0]) if val.startswith("expected to find type"): msg = "in the %s, " % (obj) + simple_compare(sort_expected[0], sort_actual[0]) else: if len(expected) > len(actual): msg = "in the %s, missing " % (obj) + list_compare_helper(sort_expected, sort_actual) elif len(expected) < len(actual): msg = "in the %s, found un" % (obj) + list_compare_helper(sort_actual, sort_expected) if len(expected) != len(actual): msg = msg + " (found %d entries in %s, but expected %d)" % (len(actual), obj, len(expected)) return msg else: val = list_compare_helper(sort_expected, sort_actual) if val != PASS: msg = "in the %s, missing " % (obj) + val + ", but found un" + list_compare_helper(sort_actual, sort_expected) return msg def list_compare_special_init(expected, special_order): real_expected = [] for i in range(len(expected)): if real_expected == [] or special_order[i-1] != special_order[i]: real_expected.append([]) real_expected[-1].append(expected[i]) return real_expected def list_compare_special(expected, actual, special_order): expected = list_compare_special_init(expected, special_order) msg = PASS expected_list = [] for expected_item in expected: expected_list.extend(expected_item) val = list_compare_unordered(expected_list, actual) if val != PASS: msg = val else: i = 0 for expected_item in expected: j = len(expected_item) actual_item = actual[i: i + j] val = list_compare_unordered(expected_item, actual_item) if val != PASS: if j == 1: msg = "at index %d " % (i) + val else: msg = "between indices %d and %d " % (i, i + j - 1) + val msg = msg + " (list may not be ordered as required)" break i += j return msg def dict_compare(expected, actual, obj="dict"): msg = PASS if type(expected) != type(actual): msg = "expected to find type %s but found type %s" % (type(expected).__name__, type(actual).__name__) return msg try: expected_keys = sorted(list(expected.keys())) actual_keys = sorted(list(actual.keys())) except: msg = "unexpected datatype found in keys of dict; expect a dict with keys of type %s" % ( type(expected_keys[0]).__name__) return msg val = list_compare_unordered(expected_keys, actual_keys, "dict") if val != PASS: msg = "bad keys in %s: " % (obj) + val if msg == PASS: for key in expected: if expected[key] == None or type(expected[key]) in [int, float, bool, str]: val = simple_compare(expected[key], actual[key]) elif type(expected[key]) in [list]: val = list_compare_ordered(expected[key], actual[key], "value") elif type(expected[key]) in [dict]: val = dict_compare(expected[key], actual[key], "sub" + obj) if val != PASS: msg = "incorrect val for key %s in %s: " % (repr(key), obj) + val return msg def check(qnum, actual): msg = check_cell_text(qnum, actual) if msg == PASS: return True print("<b style='color: red;'>ERROR:</b> " + msg) def check_file_size(path): size = os.path.getsize(path) assert size < MAX_FILE_SIZE * 10**3, "Your file is too big to be processed by Gradescope; please delete unnecessary output cells so your file size is < %s KB" % MAX_FILE_SIZE