Spaces:
Sleeping
Sleeping
| import os | |
| import plotly.express as px | |
| import plotly.graph_objects as go | |
| import pandas as pd | |
| from dash import Dash, html, dcc, Input, Output, callback, dash_table | |
| import plotly.express as px | |
| import numpy as np | |
| from plotly.subplots import make_subplots | |
| import core | |
| df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder_unfiltered.csv') | |
| debug = False | |
| external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] | |
| app = Dash(__name__, external_stylesheets=external_stylesheets) | |
| app.layout = html.Div([ | |
| dcc.Location(id='url', refresh=False), | |
| html.Div(id='page-content') | |
| ], style={ | |
| 'background-color': '#333', # Dark background color | |
| 'color': '#fff', # Text color | |
| 'min-height': '100vh', # Ensure it covers the full viewport height | |
| 'padding': '20px' # Add some padding | |
| }) | |
| server = app.server | |
| raw_wine_similarity_df = pd.read_csv('data/sogrape_wine.csv') | |
| raw_wine_similarity_df = raw_wine_similarity_df.iloc[:3, :] | |
| wine_similarity_df = pd.read_csv('data/wine_similarity.csv') | |
| wine_list = wine_similarity_df['NAME'].unique() | |
| # wine_list.sort() | |
| geo = pd.read_csv('data/processed_wineyards.csv') | |
| wine_regions=list(geo['Region'].unique()) + ['all'] | |
| wine_country = list(geo['Country'].unique()) + ['all'] | |
| # local_type = list(geo['LOCAL TYPE'].unique()) + ['all'] | |
| user_rating_df = pd.read_csv('data/simulated_ratings.csv') | |
| user_rating_df.set_index('user', inplace=True) | |
| user_rating_df['user'] = user_rating_df.index | |
| user_ids = user_rating_df['user'] | |
| raw_ratings = pd.read_csv('data/raw_simulated_ratings.csv') | |
| # crop to 5 rows and 7 columns | |
| raw_ratings = raw_ratings.iloc[:5, :7] | |
| TEMPORARY_WINE_RECOMMENDATION_FORM_INFO = {} | |
| ## Layout ## | |
| dashboard_layout = html.Div([ | |
| html.H1(children='Wineyards around the world', style={'textAlign': 'center', 'color': '#fff', 'padding': '20px'}), | |
| html.Div( | |
| [ | |
| html.Div( | |
| [ | |
| html.H4(children='Country', style={'textAlign': 'center', 'color': '#fff'}), | |
| dcc.Dropdown(wine_country, wine_country[-1], id='dropdown-wc', style={'color': '#000'}), | |
| ], className='six columns', style={'padding': '10px'} | |
| ), | |
| html.Div( | |
| [ | |
| html.H4(children='Region', style={'textAlign': 'center', 'color': '#fff'}), | |
| dcc.Dropdown(['all'], 'all', id='dropdown-wr', style={'color': '#000'}), | |
| ], className='six columns', style={'padding': '10px'} | |
| ) | |
| ], className='row', style={'background-color': '#444', 'border-radius': '10px', 'margin': '10px'}), | |
| dcc.Graph(id='world-map-fig', style={'margin': '20px'}), | |
| html.Div( | |
| [ | |
| html.Div( | |
| [ | |
| html.H4(children='Wine Recommender', style={'textAlign': 'center', 'color': '#fff'}), | |
| dcc.Dropdown(wine_list, wine_list[0], id='dropdown-selection', style={'color': '#000'}), | |
| html.P(id='wine-recommendation', style={'textAlign': 'center', 'color': '#fff'}), | |
| ], className='three columns', style={'padding': '10px'} | |
| ), | |
| html.Div( | |
| [ | |
| html.P(children='Data Example', style={'textAlign': 'left', 'color': '#fff'}), | |
| dash_table.DataTable( | |
| data=raw_wine_similarity_df.to_dict('records'), | |
| columns=[{'id': c, 'name': c} for c in raw_wine_similarity_df.columns], | |
| style_header={'backgroundColor': '#444', 'color': '#fff'}, | |
| style_cell={'backgroundColor': '#333', 'color': '#fff'} | |
| ) | |
| ], className='nine columns', style={'padding': '10px'} | |
| ) | |
| ], className='row', style={'background-color': '#444', 'border-radius': '10px', 'margin': '10px'}), | |
| html.H4(children="Wine Recommender based on users' feedback", style={'textAlign': 'center', 'color': '#fff', 'padding': '20px'}), | |
| html.Div( | |
| [ | |
| html.Div( | |
| [ | |
| dcc.Dropdown(user_ids, user_ids[0], id='dropdown-selection-user', style={'color': '#000'}), | |
| html.P(id='wine-recommendation-from-user', style={'textAlign': 'center', 'color': '#fff'}), | |
| ], className='six columns', style={'padding': '10px'} | |
| ), | |
| html.Div( | |
| [ | |
| html.P(children='Data Example', style={'textAlign': 'left', 'color': '#fff'}), | |
| dash_table.DataTable( | |
| data=raw_ratings.to_dict('records'), | |
| columns=[{'id': c, 'name': c} for c in raw_ratings.columns], | |
| style_header={'backgroundColor': '#444', 'color': '#fff'}, | |
| style_cell={'backgroundColor': '#333', 'color': '#fff'} | |
| ) | |
| ], className='six columns', style={'padding': '10px'} | |
| ), | |
| ], className='row', style={'background-color': '#444', 'border-radius': '10px', 'margin': '10px'}), | |
| html.H4(children="Wine Preferences Form", style={'textAlign': 'center', 'color': '#fff', 'padding': '20px'}), | |
| html.Div( | |
| [ | |
| html.Div( | |
| [ | |
| dcc.Dropdown(wine_list, wine_list[0], id='dropdown-selection-wine-form', style={'color': '#000'}), | |
| dcc.Input(id='input-wine-rating', type='number', placeholder='Enter wine rating', min=1, max=5, style={'margin-top': '10px'}), | |
| ], className='six columns', style={'padding': '10px'} | |
| ), | |
| html.Div( | |
| [ | |
| html.Button('Submit', id='submit-button', n_clicks=0, style={'margin-top': '10px', 'background-color': '#444', 'color': '#fff'}), | |
| ], className='six columns', style={'padding': '10px'} | |
| ), | |
| ], className='row', style={'background-color': '#444', 'border-radius': '10px', 'margin': '10px'}), | |
| html.Div(id='recommended-wine-rating-info', style={'textAlign': 'center', 'color': '#fff', 'padding': '10px'}), | |
| html.P(id='recommend-wine-from-form-text', style={'textAlign': 'center', 'color': '#fff'}), | |
| html.Div( | |
| [ | |
| html.Button('Reset', id='recommend-wine-from-form-reset', n_clicks=0, style={'margin': '10px', 'background-color': '#444', 'color': '#fff'}), | |
| html.Button('Recommend Wine', id='recommend-wine-from-form', n_clicks=0, style={'margin': '10px', 'background-color': '#444', 'color': '#fff'}), | |
| ], style={'textAlign': 'center'} | |
| ), | |
| html.Div(id='recommended-wine-form-output', style={'textAlign': 'center', 'color': '#fff', 'padding': '10px'}), | |
| ], style={ | |
| 'background-image': 'url("/assets/background.jpg")', | |
| 'background-size': 'cover', | |
| 'font-family': 'Fantasy', | |
| 'color': '#999', | |
| 'padding': '20px' | |
| }) | |
| def reset_form(n_clicks): | |
| if n_clicks > 0: | |
| TEMPORARY_WINE_RECOMMENDATION_FORM_INFO.clear() | |
| return 0 | |
| def update_output(n_clicks, wine_name, rating, text_value): | |
| if n_clicks > 0: | |
| print(f"Text Value: {text_value}") | |
| TEMPORARY_WINE_RECOMMENDATION_FORM_INFO[wine_name] = rating | |
| if not text_value: | |
| text_value = "|" | |
| text_value += f"{wine_name}: {rating} | " | |
| return f'You rated {wine_name} with a score of {rating}', 0, text_value | |
| return '', 0, text_value | |
| def recommend_wine_from_form(n_clicks): | |
| if n_clicks > 0: | |
| user = "temporary_user" | |
| user_rating_df.loc[user] = TEMPORARY_WINE_RECOMMENDATION_FORM_INFO | |
| user_rating_df.fillna(0, inplace=True) | |
| user_rating_df['user'] = user_rating_df.index | |
| user_rating_df['cluster'] = core.get_most_similar_user_clust(user_rating_df, user) | |
| wine_recommendation_from_user = core.recommend_wine_from_users(user_rating_df, user, 3) | |
| wine_recommendation_from_user = f"Based on user form, we recommend: "+"; ".join(wine_recommendation_from_user) | |
| return wine_recommendation_from_user, 0 | |
| return '', 0 | |
| def set_wine_type_options(selected_wine_type): | |
| # Return the options based on the selected wine country | |
| pattern = r'.*' if selected_wine_type == 'all' else rf'{selected_wine_type}' | |
| return list(geo[geo['Country'].str.match(pattern, na=False)]['Region'].unique()) + ['all'] | |
| wiki_layout = html.Div([ | |
| dcc.Link('Dashboard', href='/'), | |
| html.H1('About this project'), | |
| html.Div([ | |
| html.Div([ | |
| html.H3('What is this project about?'), | |
| html.P('We are a group of 4 Computer Science Engineering Students with a solid Artificial Intelligence background.'), | |
| html.P('This project aims to showcase AI applications for improving Wine Tourism for SOGRAPE.'), | |
| html.H3('\'Bout us'), | |
| html.Img(src='/assets/tourdevino_logo.webp', style={'width': '40%', 'height': 'auto', 'display': 'block', 'margin-left': 'auto', 'margin-right': 'auto'}), | |
| html.P('This project was developed by a team of 4, in the context of the SOGRAPE 2024 hackathon.'), | |
| html.P('The team members are:'), | |
| html.H4('Rui Melo'), | |
| html.H4('André Catarino'), | |
| html.H4('Dinis Costa'), | |
| html.H4('Paulo Fidalgo'), | |
| ], className='six columns'),], className='row'), | |
| ], | |
| style={'background-color': '#333', 'font-family': 'Fantasy', 'color': '#999', 'padding': '10px'} | |
| ) | |
| # Update the index | |
| def display_page(pathname): | |
| if pathname == '/': | |
| return dashboard_layout | |
| elif pathname == '/wiki': | |
| return wiki_layout | |
| else: | |
| return '404' | |
| # You could also return a 404 "URL not found" page here | |
| def update_recommendation(value): | |
| if value: | |
| recommended_wines = core.get_top_5_similar_wines(value, wine_similarity_df)[1:] | |
| return f"Based on ´{value}´, we recommend: "+"; ".join(recommended_wines) | |
| return '' | |
| def update_graph(wr,wc, user_value): | |
| ## Wine Recommendation from users feedback | |
| wine_recommendation_from_user = core.recommend_wine_from_users(user_rating_df, user_value, 3) | |
| wine_recommendation_from_user = f"Based on user information, we recommend: "+"; ".join(wine_recommendation_from_user) | |
| ### World Map of wineyards ### | |
| geo_df = pd.read_csv('data/processed_wineyards.csv') | |
| wr = r'.*' if wr == 'all' else rf'{wr}' | |
| wc = r'.*' if wc == 'all' else rf'{wc}' | |
| geo_df = geo_df[geo_df['Region'].str.contains(wr, case=False, na=False, regex=True) & geo_df['Country'].str.contains(wc, case=False, na=False, regex=True)] | |
| world_map_fig = px.scatter_map(geo_df, | |
| lat=geo_df['coord_x'], | |
| lon=geo_df['coord_y'], | |
| hover_name=geo_df['name'], | |
| zoom=4, | |
| hover_data={ | |
| 'IsTouristic': True, | |
| 'Wine Type': True, | |
| 'Country': True, | |
| 'Region': True, | |
| 'Address': True, | |
| }, | |
| title='Wineyards around the world', | |
| ) | |
| world_map_fig.update_layout(height=800, width=1200) | |
| return world_map_fig, wine_recommendation_from_user | |
| if __name__ == "__main__": | |
| app.run_server(host="0.0.0.0", port="8050", debug=debug) |