# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

import os
import sys
r_path_data = "../new_codebase/src/models/kmeans/"
sys.path.append(r_path_data)
from kmeans import *

import pandas as pd

result=get_cluster_results('ovasarhelyi','pre-summer', 'all', features, nc=4)

# # Airport  arrival

# +
import geopandas as gpd
from shapely.geometry import Point

airport_cities_d = {"airport": ['Pisa', 'Florence'], 
         "lat": [43.7228, 43.7696], "lon": [10.4017, 11.2558]}

def create_airports(data):
    """
    Exmaple: 
    data = airport_cities_d = {"airport": ['Pisa', 'Florence'], 
         "lat": [43.7228, 43.7696], "lon": [10.4017, 11.2558]}
    """
    
    airport_cities = pd.DataFrame(data)
    geometry = [Point(xy) for xy in zip(airport_cities.lon, airport_cities.lat)]
    airport_cities = airport_cities.drop(['lon', 'lat'], axis=1)
    crs = {'init': 'epsg:4326'}
    geo_airport_cities = gpd.GeoDataFrame(airport_cities, crs=crs, geometry=geometry)
    return geo_airport_cities
    


# -

def get_airport_start_end(result, geo_airport_cities):
    crs={'init': 'epsg:4326'}
    geometry_st = [Point(xy) for xy in zip(result.start_lon, result.start_lat)]
    geometry_end = [Point(xy) for xy in zip(result.end_lon, result.end_lat)]
    geo_st = gpd.GeoDataFrame(geometry_st, crs=crs, geometry=geometry_st)[['geometry']]
    geo_end = gpd.GeoDataFrame(geometry_end, crs=crs, geometry=geometry_end)[['geometry']]
    geo_st.crs = crs
    geo_end.crs = crs
    st_airport = pd.DataFrame(geo_st.within(geo_airport_cities['geometry'].unary_union.buffer(0.1)))
    st_airport.index=result.index
    result['geometry_st'] = st_airport
    end_airport = pd.DataFrame(geo_end.within(geo_airport_cities['geometry'].unary_union.buffer(0.1)))
    end_airport.index=result.index
    result['geometry_end'] = end_airport
    st_florence = pd.DataFrame(geo_st.within(geo_airport_cities['geometry'].loc[1].buffer(0.1)))
    st_florence.index=result.index
    result['geometry_st_fl'] = st_florence
    end_florence = pd.DataFrame(geo_end.within(geo_airport_cities['geometry'].loc[1].buffer(0.1)))
    end_florence.index=result.index
    result['geometry_end_fl'] = end_florence
    st_pisa = pd.DataFrame(geo_st.within(geo_airport_cities['geometry'].loc[0].buffer(0.1)))
    st_pisa.index=result.index
    result['geometry_st_pisa'] = st_pisa
    end_pisa = pd.DataFrame(geo_end.within(geo_airport_cities['geometry'].loc[0].buffer(0.1)))
    end_pisa.index=result.index
    result['geometry_end_pisa'] = end_pisa
    return result



def add_airport_arrivals(result, airport_cities_d):
    geo_airport_cities=create_airports(airport_cities_d)
    result=get_airport_start_end(result, geo_airport_cities)
    return result


def cluster_airport_result(result, i, var):
    cus=result[result[var]==i]
    arrive_by_plane=np.round(cus['geometry_st'].sum()/len(cus)*100,2)
    left_by_plane=np.round(cus['geometry_end'].sum()/len(cus)*100,2)
    arrive_fl=np.round(cus['geometry_st_fl'].sum()/len(cus)*100,2)
    arrive_pis= np.round(cus['geometry_st_pisa'].sum()/len(cus)*100,2)
    st_end_fl=pd.crosstab(cus['geometry_st_fl'],cus['geometry_end_fl']).apply(lambda x: x / x.sum()*100, 1).round(2)[True][True]
    st_end_pis=pd.crosstab(cus['geometry_st_pisa'],cus['geometry_end_pisa']).apply(lambda x: x / x.sum()*100, 1).round(2)[True][True]
    res=f'{arrive_by_plane}% arrived to, and {left_by_plane}% left by plane from Tuscany. '
    res=res+f'{arrive_fl}%  arrived to Florence airport and {arrive_pis}% landed in Pisa. '
    res=res+f'{st_end_fl}% of those who arrived to Florence by plane left from the same airport. '
    res=res+f'{st_end_pis}% of those who arrived to Pisa airport left by plane from Pisa too. '
    return res


# # Descriptives

def calculate_cluster_size(kmeans_res, var):
    cluster_results=pd.DataFrame(kmeans_res[var].value_counts())
    ratio=np.round(cluster_results/cluster_results.sum()*100, 2).rename(columns={var:"ratio"})
    return cluster_results.join(ratio)


def cluster_size(result, var):
    a=calculate_cluster_size(result, var)
    a['cus']=a.index
    return a


def create_basic_description(result, season, country, var):
    if country!='all':
        return f'In the {season} season {(len(result))} tourists visited Tuscany from {country}, we managed to cluster {np.round(len(result[pd.notnull(result[var])])/len(result)*100,2)} % of them.'
    else:
        return f'In the {season} season {(len(result))} tourists visited Tuscany, we managed to cluster {np.round(len(result[pd.notnull(result[var])])/len(result)*100,2)} % of them.'


def get_top_nationalities(result, n):
    nat_freq=pd.DataFrame(result['country'].value_counts())
    ratios=nat_freq[:n]/nat_freq.sum()*100
    res='The most common visitors are from'
    for i in range(0,len(ratios)):
        if i!=len(ratios)-1:
            res=res+f' {ratios.index[i]} ({np.round(ratios.country[i],2)}%),'
        else:
            res=res+f' and {ratios.index[i]} ({np.round(ratios.country[i],2)}%).'
    return res


def get_cluster_baiscs(result, var):
    clusters=calculate_cluster_size(result, var)
    res=f'We have {len(clusters)} clusters,'
    for i in zip(range(0,len(clusters)), ['first', 'second', "third", 'forth', 'fifth'][:len(clusters)]):
        if i[0]!=len(clusters)-1:
            #print(i)
            res=res+f' the {i[1]} cluster represents {clusters.ratio[i[0]]}%,'
        else:
            res=res+f' and the {i[1]} cluster is {clusters.ratio[i[0]]}%.'
    return res


def get_cluster_country_distr(result, var):
    return pd.crosstab(result.country, result[var]).apply(lambda x: x / x.sum()*100, 0).round(2)


def hours_tusc(result, var):
    return np.round(pd.DataFrame(result.groupby(var)[['hrs_in_tusc']].mean())/24)


def get_places_at_least4_hours(result, cluster, var):
    hours=get_hours_by_cities(result, var)
    four_hours_top=hours.sort_values(cluster, ascending=False)
    cities=four_hours_top[four_hours_top[cluster]>4].index
    if len(cities)==0:
        res='but nowhere more than 4 hours. '
    else:
        res='and out of it at least a half day in'
        i=0
        for city in cities:
            i+=1
            if city=='coast':
                city='the coast'
            if i!=len(cities) and len(cities)!=1:
                res=res+f' {city.title()},'
            elif i==len(cities) and i!=1:
                res=res+f' and {city.title()}. '
            else:
                res=res+f' {city.title()}. '
    return res


def get_hours_by_cities(result, var):
    return pd.DataFrame(result.groupby(var)[['arezzo', 'florence', 'grosseto', 'livorno',
       'lucca', 'pisa', 'pistoia', 'siena', 'coast']].mean()/60).T


def cluster_mcc_ratio(result, nc, n, var):
    rel1=get_cluster_country_distr(result, var)
    hours=hours_tusc(result, var)
    res=""
    for i in zip(range(0,nc), [" first", ' second', ' third', ' forth', ' fifth'][:nc]):
        res=res+f"By the number of uniqiue visitors the{i[1]} cluster's top {n} countries are; "
        rel=rel1.sort_values(i[0],ascending=False)[:n]
        for j in range(0,n):
            if j!=n-1:
                res=res+f'{rel[i[0]].index[j]} ({rel[i[0]][j]}%), '
            else:
                res=res+f'and {rel[i[0]].index[j]} ({rel[i[0]][j]}%). '
                res=res+f'This cluster spends in average {int(hours.hrs_in_tusc[i[0]])} days in Tuscany, '
                res=res+get_places_at_least4_hours(result, i[0], var)
                res=res+ cluster_airport_result(result, i[0], var)
    return res


"""var="label"
print(create_basic_description(result, season, country, var))
print(get_top_nationalities(result, 6))
print(get_cluster_baiscs(result, var))
print(cluster_mcc_ratio(result,4, 5, var))"""


def get_kmeans_description(result, season, country, var):
    result=add_airport_arrivals(result,airport_cities_d)
    if country=='all':
        print(create_basic_description(result, season, country, var)+' '+
        get_top_nationalities(result, 6) +" "+get_cluster_baiscs(result, var)+ ' \n'+
        cluster_mcc_ratio(result,4, 5, var))
    else:
        print(create_basic_description(result, season, country, var)+" "+
        trajectory_cluster_description(result, var))


# # Trajectory

path_to_result='/mnt/data/ovasarhelyi/TPT_tourism/new_codebase/src/models/sequence_analysis/data/clustering_results/'

d=pd.read_csv(path_to_result+'cluster_results_hungary_winter.csv')

season, country

import sys
r_path_data = "../new_codebase/src/utils/load_data/"
sys.path.append(r_path_data)
from load_dataframes import *


def trajectory_cluster_description(result, var):
    hours=hours_tusc(result, var)
    nc=len(hours)
    res=''
    if var=='label':
        st=0
    else:
        st=1
    for i in zip(range(st,nc), [" first", ' second', ' third', ' forth', ' fifth'][:nc]):
        res=res + f'The {i[1]} cluster '
        res=res + f'spends in average {int(hours.hrs_in_tusc[(i[0])])} days in Tuscany, '
        res=res+get_places_at_least4_hours(result, i[0], var)
        res=res+ cluster_airport_result(result, i[0], var)
    return res 


def join_customer_features(traj_result, username,season, country):
    user_features=get_k_means_data(username,season, country).set_index("customer_nr")
    features_with_trajectory=user_features.join(traj_result.set_index('customer_nr')[["cluster"]])
    return features_with_trajectory


def write_file(country, season, final):
    if var=='label':
        path='../new_codebase/results/kmeans/'
    elif var=='cluster':
        path='../new_codebase/results/kmeans/'
    file_name=country+"_"+season
    newpath=path+file_name+'/'
    if not os.path.exists(newpath):
        os.makedirs(newpath)
    f = open(newpath+file_name+".txt","w")   
    f.write(final)
    f.close()


def get_trajectory_description(traj_result, username, season, country, var, print_it=True):
    result=join_customer_features(traj_result, username, season, country)
    result=add_airport_arrivals(result, airport_cities_d)
    final=create_basic_description(result, season, country, var)+" "+trajectory_cluster_description(result, var)
    if print_it==True:
         write_file(country, season, final, var)
    print(final)


# # TEST

# +
traj_result=d
username='ovasarhelyi'
country = 'hungary'
season = 'winter'
var = 'cluster'

get_trajectory_description(traj_result, username, season, country, var, True)
# -

season='pre-summer'
country='all'
get_kmeans_description(result,season, country, "label")

season='winter'
country='hungary'
result=get_cluster_results('ovasarhelyi',season, country, features, nc=4)
get_kmeans_description(result,season, country, "label")

StarcoderdataJupyterScriptsDedupFiltered