def get_car_prices(car_df): """ Crawls prices for the recommended cars and the user's car from kbb and adds them as columns to the inputted dataframe. Tries different options for model names to find a match and asks the user for an estimation if the price for their old car is not found. Parameters: car_df (pd.DataFrame): dataframe of cars to be recommended Returns: car_df (pd.DataFrame): dataframe of cars to be recommended with the added price and difference columns old_car_price (float): price of the user's current car """ car_df["price"] = np.nan pm = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where()) old_car_price = None car_df = car_df.reset_index() car_df.loc[:, "model"] = car_df.loc[:, "model"].str.replace("/", " ") for i, row in car_df.iterrows(): make, possible_models, year = get_info_for_price(row) if year < 1992 and i != len(car_df) - 1: continue for _, model in enumerate(possible_models): myurl = f"https://www.kbb.com/{make}/{model}/{year}/" html = pm.urlopen(url=myurl, method="GET").data soup = bs4.BeautifulSoup(html, features="html.parser") title = soup.find_all("title")[0].text if (("Find Your Perfect Car" not in title) and ("Kelley Blue Book | Error" not in title)): break if (("Find Your Perfect Car" in title) or ("Kelley Blue Book | Error" in title) or (str(year) not in title)): continue price_text = soup.find_all("script", attrs={"data-rh": "true"})[-1].text m = re.findall('"price":"([0-9]+)"', price_text)[0] if i == len(car_df) - 1: old_car_price = m car_df.loc[i, "price"] = float(m) old_car_price = q.text( 'No associated price could be found for your car.' '\n What do you believe your car is worth?\n ', validate=lambda text: txt_validator(text), style=Style(S_CONFIG + [('qmark', 'fg:#CF5050')]), qmark='\n❗').skip_if(old_car_price is not None, old_car_price).ask() car_df["difference"] = (float(old_car_price) - car_df.price[car_df.price.notna()]) car_df = car_df.drop(car_df.tail(1).index) return car_df, old_car_price
def get_miles(): """ Asks user for estimation of their current weekly miles. Used to calculate their emission. Returns: float: user's estimated weekly milage """ use_miles = q.text('Estimation for weekly miles driven?\n ', validate=lambda text: txt_validator(text), style=Style(S_CONFIG), qmark='\n⯁ ').ask() return float(use_miles)
def rank_pref(): """ Ranks vehicle attributes that user cares most about from their current car. Uses this information to more accurately recommend a new vehicle. Returns: lst: elements are arranged in order of priority """ CHOICES = [ 'Make', 'Year', 'Transmission', 'Vehicle Class', 'Fuel Type', 'Passenger capacity', 'Luggage Capacity', 'Stop Ranking' ] DICT_MAP = { 'Make': 'make', 'Year': 'year', 'Transmission': 'trany', 'Vehicle Class': 'VClass', 'Fuel Type': 'fuelType', 'Luggage Capacity': 'luggage_volume' } q.print( 'We will now ask you to rank which attributes you like most ' 'about your current vehicle.\nThese choices will be taken into ' 'consideration for car recommendation.\nYou may rank until you ' "feel you have no more preferences or until you've exhausted all " 'options.', style=S_CONFIG[1][1]) i = 1 pref = '' rank_order = [] while len(CHOICES) > 2: pref = q.select('Choose preference: ', choices=CHOICES, style=Style(S_CONFIG), qmark='\n' + str(i)).ask() if pref == 'Stop Ranking': break CHOICES.remove(pref) rank_order.append(pref) i += 1 if len(CHOICES) == 2: rank_order.append(CHOICES[0]) # Rename items in rank list to the less human readable col names return list((pd.Series(rank_order, dtype='object')).map(DICT_MAP))
def unique_helper(c, col, col_desc, base_param, prev=[]): """ Refines id search by checking if transmission, cylinder, or drive data is enough to uniquely identify a given car. Parameters: c (obj): cursor for current connection to database col (str): column we will query for uniqueness col_desc (str): modifies question string to best fit current query base_param (tup): make, model, year used as filters for query. These parameters are built upon as each successive question provides new information prev (lst): contains tuples of form (prev col queried, prev unique_helper result) needed so that later calls to this function may use new information to refine its query Returns: tup:ans (str) - the feature selected by the user that matches their current car. Can also be None if there is only one possible choice of that feature given the query restrictions or if user is unsure cond (str) - (used only the last time the function is called) saves WHERE clause to be used outside the function """ add_cond, param_tup = '', () prev = [tup for tup in prev if tup[1]] if prev: cond_tup, param_tup = zip(*prev) for cond in cond_tup: add_cond += f' AND {cond} = ?' uniq_query = f'SELECT {col} FROM vehicles {WHERE_CMD} {add_cond}' uniq_results = c.execute(uniq_query, base_param + param_tup).fetchall() uniq_results = {str(tup[0]) for tup in uniq_results} uniq = len(uniq_results) == 1 ans = q.select(f"Which matches your car's {col_desc}?\n ", choices=sorted(uniq_results) + ['Not Sure'], style=Style(S_CONFIG), qmark='\n⯁ ').skip_if(uniq).ask() if ans == 'Not Sure': ans = None return ans, add_cond
import os import sys from posixpath import expanduser import subprocess import argparse from pathlib import Path from colored import fg, attr import logging FORMAT = f"%(filename)s: {attr('bold')}%(levelname)s {fg(3)+attr('bold')}%(message)s{attr('reset')} line: %(lineno)s, %(relativeCreated)dms" logging.basicConfig(format=FORMAT, level=logging.DEBUG) logging.disable(logging.WARNING) data_path = os.path.join(Path.home(), ".local/share/trening.json") style = Style(questionary_style) class Trening(object): def __init__(self) -> None: self.data_path = data_path self.load_conf() def load_conf(self) -> None: with open(self.data_path) as f: self.config = json.load(f) self.determine_exercise() self.cycle_rms = self.config[self.current_cycle + "_RMs"] self.one_rm = self.config["exercises"][self.current_exercise]["1RM"]
# Item prefix to identify selected items in a checkbox list INDICATOR_SELECTED = "●" # Item prefix to identify unselected items in a checkbox list INDICATOR_UNSELECTED = "○" # Prefix displayed in front of questions DEFAULT_QUESTION_PREFIX = "?" # Message shown when a user aborts a question prompt using CTRL-C DEFAULT_KBI_MESSAGE = "Cancelled by user" # Default text shown when the input is invalid INVALID_INPUT = "Invalid input" # Default message style DEFAULT_STYLE = Style( [ ("qmark", "fg:#5f819d"), # token in front of the question ("question", "bold"), # question text ("answer", "fg:#FF9D00 bold"), # submitted answer text behind the question ("pointer", ""), # pointer used in select and checkbox prompts ("selected", ""), # style for a selected item of a checkbox ("separator", ""), # separator in lists ("instruction", ""), # user instructions for select, rawselect, checkbox ("text", ""), # any other text ("instruction", ""), # user instructions for select, rawselect, checkbox ] )
def get_id(conn): """ Extracts unique id from database by narrowing down candidates based on user provided information. Some cars continue to have variants even after all questions have been asked. For those that do, the first id fetched by the final query result is the one we will use. Parameters: conn (obj): connection to sqlite database we will be querying Returns: int: identifier for user's current car, used as a means to access other information related to their vehicle for future functions """ c = conn.cursor() make_query = 'SELECT DISTINCT make FROM vehicles' make_results = c.execute(make_query).fetchall() make_results = sorted({tup[0] for tup in make_results}) make_ans = q.autocomplete( "What is your car's make?\n ", choices=make_results, validate=(lambda text: autoc_validator(text, c, 'make')), style=Style(S_CONFIG), qmark='⯁ ').ask() m_y_query = ('SELECT DISTINCT model, year ' 'FROM vehicles WHERE make = ?') m_y_results = set(c.execute(m_y_query, (make_ans, )).fetchall()) m_y_results = sorted(m_y_results, key=lambda tup: (tup[0], -tup[1])) m_y_results = [tup[0] + ' ' + str(tup[1]) for tup in m_y_results] m_y_ans = q.autocomplete( 'What about model and year?\n ', choices=m_y_results, validate=(lambda text: autoc_validator(text, c, 'm_y')), style=Style(S_CONFIG), qmark='\n⯁ ').ask() model, _, year = m_y_ans.rpartition(' ') base_tup = (make_ans, model, int(year)) id_query = f'SELECT id FROM vehicles {WHERE_CMD}' uniq_results = c.execute(id_query, base_tup).fetchall() uniq_results = [tup[0] for tup in uniq_results] id_ = uniq_results[0] uniq = len(uniq_results) == 1 c_msg = ('Your particular car has some variants, would you like to be ' 'more specific?\n You may be prompted to choose transmission, ' 'number of cylinders, or drive type.\n Recommended only if ' 'you are comfortable with these more advanced options.\n ' '(Skipping defaults to No.)\n ') advanced = q.confirm(c_msg, default=False, style=Style(S_CONFIG + [('qmark', 'fg:#CF5050')]), qmark='\n❗').skip_if(uniq).ask() if advanced: t_ans, _ = unique_helper(c, 'trany', 'transmission', base_tup) c_ans, _ = unique_helper(c, 'cylinders', 'number of cylinders', base_tup, [('trany', t_ans)]) d_ans, cond = unique_helper(c, 'drive', 'drive type', base_tup, [('trany', t_ans), ('cylinders', c_ans)]) if d_ans: cond += ' AND drive = ?' add_tup = tuple(val for val in (t_ans, c_ans, d_ans) if val) id_query = 'SELECT id FROM vehicles ' + WHERE_CMD + cond id_ = c.execute(id_query, base_tup + add_tup).fetchone()[0] c.close() return id_
# User interface custom_style_fancy = Style( [ ("qmark", "fg:#673ab7 bold"), # token in front of the question ("question", "bold"), # question text ( "answer", "fg:#f44336 bold", ), # submitted answer text behind the question ( "pointer", "fg:#673ab7 bold", ), # pointer used in select and checkbox prompts ( "highlighted", "fg:#673ab7 bold", ), # pointed-at choice in select and checkbox prompts ("selected", "fg:#cc5454"), # style for a selected item of a checkbox ("separator", "fg:#cc5454"), # separator in lists ( "instruction", "", ), # user instructions for select, rawselect, checkbox ("text", ""), # plain text ( "disabled", "fg:#858585 italic", ), # disabled choices for select and checkbox prompts ], ) # Summary
# Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from questionary import prompt, print from CryptoLibrary.utils import CryptoUtility from questionary import Style custom_style_fancy = Style([ ('qmark', '#fac731 bold'), ('question', 'bold'), ('answer', '#06c8ff bold italic'), ('pointer', '#673ab7 bold'), ('highlighted', '#34AC5E bold'), ('selected', '#0abf5b'), ('separator', '#cc5454'), ('instruction', ''), ('text', ''), ('disabled', '#858585 italic'), ]) __version__ = '0.0.3' class Encrypter(object): def main(self): self.main_menu() def main_menu(self): questions = [{
CUSTOM_STYLE = Style( [ ("qmark", "ansibrightyellow bold"), # token in front of the question ("question", "ansiwhite bold"), # question text ( "answer", "ansibrightmagenta bold", ), # submitted answer text behind the question ( "pointer", "ansibrightblue bold", ), # pointer used in select and checkbox prompts ( "highlighted", "ansibrightblack bold", ), # pointed-at choice in select and checkbox prompts ( "selected", "ansibrightblack", ), # style for a selected item of a checkbox ("separator", "ansibrightmagenta"), # separator in lists ( "instruction", "", ), # user instructions for select, rawselect, checkbox ("text", ""), # plain text ( "disabled", "ansibrightblack italic", ), # disabled choices for select and checkbox prompts ] )
from questionary import Style custom_style_fancy = Style([ ("separator", "fg:#cc5454"), ("qmark", "fg:#673ab7 bold"), ("question", ""), ("selected", "fg:#cc5454"), ("pointer", "fg:#673ab7 bold"), ("highlighted", "fg:#673ab7 bold"), ("answer", "fg:#f44336 bold"), ("text", "fg:#FBE9E7"), ("disabled", "fg:#858585 italic"), ]) custom_style_dope = Style([ ("separator", "fg:#6C6C6C"), ("qmark", "fg:#FF9D00 bold"), ("question", ""), ("selected", "fg:#5F819D"), ("pointer", "fg:#FF9D00 bold"), ("answer", "fg:#5F819D bold"), ]) custom_style_genius = Style([ ("qmark", "fg:#E91E63 bold"), ("question", ""), ("selected", "fg:#673AB7 bold"), ("answer", "fg:#2196f3 bold"), ])