-
Notifications
You must be signed in to change notification settings - Fork 0
/
recommendations.py
144 lines (111 loc) · 5.95 KB
/
recommendations.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import json
from data import data_items, data_categories
from classes.stack import Stack
from quicksort import quicksort
def load_transformed_dict(file_path):
with open(file_path, "r") as json_file:
return json.load(json_file)
data_items = data_items
data_categories = data_categories
items_in_categories = load_transformed_dict("data.json")
categories = set([category for category in items_in_categories.keys()])
sorted_categories = quicksort(list(categories), 0, len(categories) -1)
selected_categories = Stack()
def welcome():
number_items = len(set([item for items in items_in_categories.values() for item in items]))
print(f"\nWelcome to {data_items} recommendation software where there are {number_items} {data_items} to choose from!")
print(f"Recommendations are chosen from the {data_categories} that you select. So let's get started...\n")
def get_category_list():
initial = validate_input(input(f"Type in the first letter of the {data_categories} that you are interested in, then press enter, to see if it's here: "), "initial")
possible_categories = [tag for tag in sorted_categories if tag.startswith(initial)]
if not possible_categories:
print(f"There were no {data_categories} matches starting with {initial}. Please try again...")
return get_category_list()
print(f"There are the following {data_categories} matches starting with the letter {initial}: {', '.join(possible_categories)}")
user_answer = validate_input(input(f"\nDo you wish to select a {data_categories} from the above list? (Y/N): "), "Y/N")
if user_answer == "N":
return get_category_list()
return get_categories(possible_categories)
def get_categories(possible_categories):
if len(possible_categories) == 1:
selected_categories.push(possible_categories[0])
print(f"Finding recommendations for the {data_categories}: {selected_categories.peek()}")
return selected_categories
category = validate_input(input(f"Type in the first few letters of the {data_categories} you wish to select from the above list: "), "letters")
category_match = [tag for tag in possible_categories if tag.startswith(category)]
if not category_match:
print(f"There were no {data_categories} matches starting with the letters {category}. Please try again...")
return get_categories(possible_categories)
if len(category_match) > 1:
print(f"There were too many matches, please try to type more letters to select a single {data_categories}.")
return get_categories(possible_categories)
selected_categories.push(category_match[0])
return selected_categories
def get_recommendations(selected_categories):
if not selected_categories:
print("ERROR: NO GENRE SELECTED") # should already be caught by len(genre_match) == 0 in get_genre()
return
number_categories = selected_categories.size
current_category = selected_categories.top_item
recommendations = None
category_str = ""
while current_category:
current_category_value = current_category.get_value()
category_str += f"{current_category_value}, "
if current_category_value in items_in_categories:
current_items = set(items_in_categories[current_category_value])
if recommendations is None:
recommendations = current_items
else:
recommendations.intersection_update(current_items)
current_category = current_category.get_next_node()
if recommendations is None:
print(f"\nNo recommendations found for the selected {data_categories}.")
start_again()
return
sorted_recommendations = quicksort(list(recommendations), 0, len(recommendations) - 1)
print(f"\nFinding {data_items} recommendations that match the {data_categories} - {category_str[:-2]}:")
if not sorted_recommendations and number_categories > 1:
last_category = selected_categories.pop()
print(f"There were no {data_items} recommendations for those {data_categories}. \nRemoving the last {data_categories} added: {last_category}")
return get_recommendations(selected_categories)
if len(sorted_recommendations) > 5:
print(f"There are {len(sorted_recommendations)} {data_categories} recommendations for those {data_categories}(s).")
filter_more = validate_input(input(f"Do you wish to filter recommendations by another {data_categories}? (Y/N): "), "Y/N")
if filter_more == "N":
display_recommendations(sorted_recommendations)
start_again()
else:
category_match = get_category_list()
get_recommendations(category_match)
else:
display_recommendations(sorted_recommendations)
start_again()
def start_again():
user_answer = validate_input(input("\nDo you wish to start a new recommendation search? (Y/N): "), "Y/N")
if user_answer == "N":
exit()
else:
genre_match = get_category_list()
get_recommendations(category_match)
def validate_input(user_answer, input_type):
user_answer = user_answer.strip().capitalize()
if input_type == "Y/N":
while user_answer not in {"Y", "N"}:
user_answer = input("Please type in Y or N?: ").strip().upper()
elif input_type == "initial":
while len(user_answer) != 1 or not user_answer.isalpha():
user_answer = input("Please type in a single letter: ").strip().upper()
elif input_type == "letters":
while not user_answer.isalpha():
user_answer = input("Please type in letters only: ").strip().capitalize()
else:
raise ValueError("ERROR: Invalid input_type specified.")
return user_answer
def display_recommendations(sorted_recommendations):
for item in sorted_recommendations:
print(f" {item}")
selected_categories.clear_all()
welcome()
category_match = get_category_list()
get_recommendations(category_match)