def results(request): c={} # The first part of this function validates the data errors=[] try: c["current_distance"]=request.POST.get("distance") distance=float(c["current_distance"]) units = request.POST.get("distance_type") if units == "miles": distance *= 1609.34 assert distance>0 except: errors.append("distance should be a numeric value greater than 0") try: c["current_loc"]=request.POST.get("location") loc=int(c["current_loc"]) except: errors.append("location should be a zip code in Chicago") try: c["current_price_upper_limit"]=request.POST.get("price_upper_limit") current_price_upper_limit=round(float(c["current_price_upper_limit"])) assert current_price_upper_limit>=0 try: c["current_price_lower_limit"]=request.POST.get("price_lower_limit") current_price_lower_limit=round(float(c["current_price_lower_limit"])) assert current_price_lower_limit<=current_price_upper_limit and current_price_lower_limit>=0 except: errors.append("min price should be a numeric value greater than or equal to 0, and less than or equal to max price") except: errors.append("max price should be a numeric value greater than 0") c["current_date"]=request.POST.get("date") date='"'+c["current_date"].strip()+'"' search_date=re.search('"([\d]{4})-([\d]{2})-([\d]{2})"', date) if bool(search_date)!=True: errors.append("Please enter the date in YYYY-MM-DD format") else: year=search_date.group(1) if year not in ["2013", "2014", "2015", "2016"]: errors.append("no data available for year {}".format(year)) weights=[] for j in range(1,16): try: weights.append(float(request.POST.get("pref_"+str(j)))) except: errors.append("Survey question {} was not filled in".format(j)) try: # Checks if the house types are valid and in the right order house_type1=request.POST.get("house_type1") house_type2=request.POST.get("house_type2") house_type3=request.POST.get("house_type3") assert house_type1 != None try: assert house_type1 != house_type2 and house_type1 != house_type3 except: errors.append("House types repeat") if house_type2 == "" and house_type3 != "": errors.append("Invalid ordering") house_types = ["house_type"] house_types.append(house_type1) if house_type2 != "": house_types.append(house_type2) if house_type3 != "": house_types.append(house_type3) except: errors.append("Need first field for house type preference") listing_type=request.POST.get("listing_type") try: c["current_max_bathroom"]=request.POST.get("max_bathroom") current_max_bathroom=int(c["current_max_bathroom"]) assert current_max_bathroom >= 0 try: c["current_min_bathroom"] = request.POST.get("min_bathroom") current_min_bathroom=int(c["current_min_bathroom"]) assert current_min_bathroom >= 0 and current_min_bathroom <= current_max_bathroom except: errors.append("min bathroom should be an integer value greater than or equal to 0, and less than or equal to max bathroom") except: errors.append("max bathroom should be an integer value greater than or equal to 0") try: c["current_max_bedroom"] = request.POST.get("max_bedroom") current_max_bedroom=int(c["current_max_bedroom"]) assert current_max_bedroom >= 0 try: c["current_min_bedroom"] = request.POST.get("min_bedroom") current_min_bedroom = int(c["current_min_bedroom"]) assert current_min_bedroom >= 0 and current_min_bedroom <= current_max_bedroom except: errors.append("min bedroom should be an integer value greater than or equal to 0, and less than or equal to max bedroom") except: errors.append("max bedroom should be an integer value greater than or equal to 0") questions=[] count=1 with open(current_path + "/search/templates/search/survey.txt") as f: for line in f: questions.append([line, count]) count += 1 c["survey"] = questions if len(errors) > 0: c["errors"] = errors return render(request, 'search/home.html', c) criteria_list = [["price", current_price_lower_limit, current_price_upper_limit], ["bedroom", current_min_bedroom, current_max_bedroom], ["bathroom", current_min_bathroom, current_max_bathroom], house_types] print("Querying zillow...") print("Here are the inputs:", loc, listing_type, criteria_list) house_list = ranking.get_house_list(loc, listing_type, criteria_list) print("Done. Found {} matching properties".format(len(house_list ))) # Adds error message if the number of results is 0 or too large if len(house_list) > 200: errors.append("Too many results, please narrow down your search.") c["errors"]=errors return render(request, 'search/home.html', c) if len(house_list) ==0: errors.append("No results found.") c["errors"]=errors return render(request, 'search/home.html', c) zillow_pref, Yelp_pref, database_pref=weights[:4],weights[4:11], weights[11:] list_of_house_coords=[(j.lat,j.long) for j in house_list] scores=[] # Stores the scores gotten from yelp print("Requesting Yelp") Yelp_results=Yelp.get_yelp_scores(list_of_house_coords,distance,Yelp_pref) # Stores the results gotten from database database_results=sql_stuff.search(date, list_of_house_coords, distance, "search.db") # Extracts the scores from the results database_scores=[] for l in database_results: house_scores=[l[j][1] for j in DATABASE_CATEGORIES] database_scores.append(house_scores) #for when I test at csil #fake_yelp=[] #for k in range(len(house_list)): # new_list=[] # for j in range(7): # new_list.append(0) # fake_yelp.append(new_list) #for i in range(len(fake_yelp)): # total_scores.append(fake_yelp[i]+database_scores[i]) # Creates a list of lists with the yelp and city scores total_scores = [] for i in range(len(Yelp_results)): total_scores.append(Yelp_results[i]+database_scores[i]) # Passes the houses, user input, scores, and preferences into ranking to get the final scores # Also sets the scores of each house object raw_scores_dict = ranking.get_final_scores(house_list, criteria_list, total_scores, zillow_pref, database_pref,Yelp_pref) scores_dict = {} top_ten_address = [] for pref in raw_scores_dict: scores_list = [] for tup in raw_scores_dict[pref]: if pref not in list(scores_dict.keys()): scores_dict[pref] = [tup[1]] else: scores_dict[pref].append(tup[1]) if tup[2] not in top_ten_address: top_ten_address.append(tup[2]) scores = {"zillow":{}, "yelp":{},"crime":{}} # Divides the scores in scores_dict into 3 categories: zillow, yelp, crime for key in scores_dict: for pref in PREF_OPTIONS_DICT: if key in PREF_OPTIONS_DICT[pref]: scores[pref][key] = (scores_dict[key]) # If there are more than 10 results the graphs can get messy looking # We separate out the top 10 to use in graph generation if len(house_list) > 10: list_top_coords = [] list_top_houses = [] for address in top_ten_address: for house in house_list: if address == house.address: list_top_coords.append((house.lat, house.long)) list_top_houses.append(house) top_Yelp_results=Yelp.get_yelp_scores(list_top_coords,distance,Yelp_pref) else: list_top_houses = house_list # Changes the data in scores into Address, value, value, value form to use in the bar chart # Also stores the variable names bar_data_dict = {"zillow":[[]], "yelp":[[]],"crime":[[]]} # For preference category for key in scores: variable_list = PREF_OPTIONS_DICT[key] # For each property in the top 10 for i in range(len(top_ten_address)): value_list = [] # Checks for the variables that the user cares about for variable in PREF_OPTIONS_DICT[key]: if variable in scores[key]: # If the yelp scores were not generated before, generate them if len(house_list) > 10 and key == "yelp": value_list.append(math.ceil(top_Yelp_results[i][YELP_DICT[variable]]*100)) else: # Add the score as 0 if the user does not care value_list.append(scores[key][variable][i]) else: value_list.append(0) # Puts the data in desired form bar_data_dict[key][0].append([top_ten_address[i]] + value_list) # Adds the variable name bar_data_dict[key].append(variable_list) shutil.rmtree(HOUSE_PATH, ignore_errors=True) os.mkdir(HOUSE_PATH) index=0 for i in house_list: os.mkdir(HOUSE_PATH+"/{}".format(i.house_id)) for j in DATABASE_CATEGORIES: with open(HOUSE_PATH+"/{}/{}.csv".format(i.house_id, j), "w") as f: f.write("date,primary type,secondary type,latitude,longitude\n") for k in database_results[index][j][0]: tuple_list=[str(l) for l in k] row_string=",".join(tuple_list) f.write(row_string+"\n") index+=1 with open(HOUSE_PATH+"/attributes.csv", "w") as f: f.write("id,address,price,bedroom,bathroom,latitude,longitude,score,link\n") for j in house_list: address = j.address if "," in address: address = address.replace(',', '') row_string="{},{},{},{},{},{},{},{},{}".format(j.house_id, address, j.price, j.bedroom, j.bathroom, j.lat, j.long, j.score, j.link) f.write(row_string+"\n") # Gets the data from the csv files and puts it in the correct form bar_data = [] all_crimes = {} for i in list_top_houses: for j in DATABASE_CATEGORIES: all_crimes[j]={} with open(HOUSE_PATH+"/{}/{}.csv".format(i.house_id,j), "r") as f: header=f.readline() reader=csv.reader(f) for row in reader: date=row[0] month_year=date[:7] all_crimes[j][month_year]=all_crimes[j].get(month_year, 0)+1 t_labels=list(all_crimes[j].keys()) t_labels.sort() t=range(len(t_labels)) s=[all_crimes[j][k] for k in t_labels] bar_data.append((i.address, j, sum(s))) bar_dict = {} for i in bar_data: if i[0] not in bar_dict: bar_dict[i[0]] = [i[2]] else: bar_dict[i[0]].append(i[2]) bar_list = [] for key in top_ten_address: bar_list.append([key]+ bar_dict[key]) # Replaces the c dictionary with the house_list and fills it with the bar graph data c={'results': house_list} c['database_cat'] = DATABASE_CATEGORIES c['bar_data'] = bar_list c['zbar_data']=bar_data_dict["zillow"][0] c['ybar_data']=bar_data_dict["yelp"][0] c['cbar_data']=bar_data_dict["crime"][0] c['zbar_var']=bar_data_dict["zillow"][1] c['ybar_var']=bar_data_dict["yelp"][1] c['cbar_var']=bar_data_dict["crime"][1] c['current_distance'] = distance c["current_date"]=request.POST.get("date") return render(request, 'search/results.html', c)