def bandura_lucky():
    global g_7digital_cur
    global g_7digital_nexts
    global g_song_features
    global g_nexts_features

    print "bandura_lucky"

    context = packContext( 0 );

    if 1: #request.method == "POST":
        #if request.method == "POST":
        #    updateParamsFromSite( request.form )

        random_match = MX_traverse.pickRandomSong()

        g_next_choice = 0
        g_7digital_nexts = [[random_match]]
        g_nexts_features = list()
        print g_7digital_nexts[0][g_next_choice]
        g_nexts_features.append( tuple(MX_traverse.get_song_by_7digital( g_7digital_nexts[0][g_next_choice] )) )
        print "random choice: " + g_nexts_features[g_next_choice][0]

    render_template("bandura.html", **context);
    return redirect("/bandura")
def bandura_search():
    global g_7digital_cur
    global g_7digital_nexts
    global g_song_features
    global g_nexts_features

    print "bandura_search"

    if request.method == "POST":
        print "'bandura search' called by POST"

        #updateParamsFromSite( request.form )

        context = packContext( 0 );

        search_term = request.form["search_term"]
        if search_term != '':

            # seach the exact term in the DB
            best_match = [MX_traverse.get_song_id_by_token(search_term)]

            if best_match[0]=='':
                # if the exact term wasn't found in the DB, perform a more flexible search using the EchoNest API
                g_7digital_cur = ''
                n_search_results = 2
                while best_match[0]=='' and n_search_results<=1000:
                    n_search_results *= 5              
                    z = py7D.request('track', 'search', q=search_term, pagesize=n_search_results)
                    if int(z['response']['searchResults']['totalItems'])>0:
                        search_results = z['response']['searchResults']['searchResult']
                        search_results2 = list()
                        print "possible matches: " + str(len(search_results))
                        for result in search_results:
                            record=dict()
                            record['track_7digitalid']  = result['track']['@id']
                            record['title']             = result['track']['title']
                            record['artist']            = result['track']['artist']['name']
                            print record['track_7digitalid'], record['title'], record['artist']
                            search_results2.append(record)
                        # intersect the EchoNest results with our DB    
                        best_match = MX_traverse.findInSongsDB( [x['track_7digitalid'] for x in search_results2] )

            if best_match[0]!='':
                g_next_choice = 0
                g_7digital_nexts = [[best_match[0]]]
                g_nexts_features = list()
                g_nexts_features.append( tuple(MX_traverse.get_song_by_7digital( g_7digital_nexts[0][g_next_choice] )) )
                print "best match: " + g_nexts_features[g_next_choice][0]
            else:
                print "no match..."
        else:
            print "No search term..."
    else:
        context = dict()
        "'bandura_search' called by GET"
    render_template("bandura.html", **context);
    return redirect("/bandura")
def bandura():
    global p
    global g_p
    global g_7digital_cur
    global g_7digital_nexts  
    global g_song_features
    global g_nexts_features
    global g_next_choice

    print "bandura"
    context = packContext( 0 );

    if 1: #request.method == "POST":
        if request.method == "POST":
            print "'bandura' called by POST"
            updateParamsFromSite( request.form )

        context = packContext( 0 ); 

        if g_7digital_nexts:
            print "cur song id exists"
            print g_7digital_nexts
            g_7digital_cur   = g_7digital_nexts[0][g_next_choice]
            g_song_features  = g_nexts_features[g_next_choice]
            song_url         = OAuth.get_song_url(g_7digital_cur);
            g_7digital_nexts = MX_traverse.pickNextSongsWrapped( g_7digital_cur );
            g_nexts_features = [MX_traverse.get_song_by_7digital( x ) for x in g_7digital_nexts[0]]
            if g_p['save_playlist']:
                MX_traverse.addSongToPlaylist( g_p['playlist_file'], g_song_features, song_url )

            context['song_url']     = song_url+"#t="+str(g_p['play_interval'][0])+","+str(g_p['play_interval'][1])
            context['id_7digital']  = g_7digital_cur
            context['title']        = g_song_features[p['invkey']['title']]
            context['artist']       = g_song_features[p['invkey']['artist_name']]
                        
            for i in range(len(g_nexts_features)):
                context['n'+str(i)+'_id_7digital'] = g_nexts_features[i][p['invkey']['track_7digitalid']]
                context['n'+str(i)+'_title']       = g_nexts_features[i][p['invkey']['title']]
                context['n'+str(i)+'_artist']      = g_nexts_features[i][p['invkey']['artist_name']]
        else:
            print "cur song id does NOT exists"
    else:
        print "'bandura' called by GET"
    print "rendering bandura"
    return render_template("bandura.html", **context);
def setCurrentCalcNext( context = dict() ):
    global p
    global g_p
    global g_7digital_cur
    global g_7digital_nexts
    global g_song_features

    g_7digital_nexts      = MX_traverse.pickNextSongsWrapped( g_7digital_cur );
    g_song_features       = MX_traverse.get_song_by_7digital( g_7digital_cur )
    g_nexts_features      = [MX_traverse.get_song_by_7digital( x ) for x in g_7digital_nexts[0]]
    song_url              = MX_traverse.get_song_url( g_7digital_cur )
    if g_p['save_playlist']:
        g_p['playlist_file'] = g_p['playlist_pref'] + time.strftime("%Y%m%d-%H%M%S") + '.csv'
        MX_traverse.addSongToPlaylist( g_p['playlist_file'], g_song_features, song_url )
    
    context['song_url']    = song_url+'#t='+str(g_p['play_interval'][0])+","+str(g_p['play_interval'][1])
    context['id_7digital'] = g_7digital_cur
    context['title']       = g_song_features[p['invkey']['title']]
    context['artist']      = g_song_features[p['invkey']['artist_name']]

    for i in range(len(g_nexts_features)):
        context['n'+str(i)+'_id_7digital'] = g_nexts_features[i][p['invkey']['track_7digitalid']]
        context['n'+str(i)+'_title']       = g_nexts_features[i][p['invkey']['title']]
        context['n'+str(i)+'_artist']      = g_nexts_features[i][p['invkey']['artist_name']]

    return context
def play_test():
    if request.method == "POST":
#		if request.form["user_play"] == "PlayThis":
        print "this!"
#			echonest_id = request.form["user_play"]
#			id_7digital = get_7digital_id( echonext_id ) 
#			song_url = OAuth.get_song_url(id_7digital)
#			print song_url
#			return render_template("play_specific.html", api_data=song_url)
#	else:
        print "next! " + request.form["user_play"];
#			echonest_id = "SOBOAQC12A8C13E3E9"#request.form["user_play"]
#			echonest_id_next = MX_traverse.pickNextSongWrapped( echonest_id ) #echonext_id
#			print echonest_id, echonest_id_next
        id_7digital = request.form["user_play"]#MX_traverse.get_7digital_id( echonest_id_next ) 
        song_url = OAuth.get_song_url(id_7digital);
#        print song_url
        id_7digital_next = MX_traverse.pickNextSongWrapped( id_7digital );#echonext_id
        request.form["user_play"] = id_7digital_next
        return render_template("play_specific.html", api_data=song_url)
    else:
        print "moshe"
        return render_template("play_test.html")
def constructGraph( conn, p, song_features_table_name, artist_similarities_table_name, graph_table_name, debug_print=False ):
        
    cur = conn.cursor()


    MX_common.resetTable( conn, graph_table_name, ['targeto text', 'similaro text, dist real'] )

        
    # read songs_list
    q = "SELECT \
            song_id \
        FROM "\
            +song_features_table_name +";"
    cur.execute(q)
    songs_list = cur.fetchall()
    
    node_stats = dict()
    node_stats['neighbors_cur_artist'] = list()
    node_stats['neighbors_topo'] = list()
    node_stats['neighbors_metric'] = list()
    node_stats['mean_dist'] = list()
    node_stats['similar_artists'] = list()
    edge_stats = dict()
    edge_stats['dist'] = list()
    edge_stats['vdist'] = list()
    
    # for each song (the focal song), find its neighbors
    for focal_song_id in songs_list[::1]:        
        focal_song_id = focal_song_id[0]
        
        if debug_print:
            print "focal_song: " + focal_song_id        
        
        # fetch all focal song's features
        q = "SELECT \
                * \
            FROM "\
                +song_features_table_name+" "\
            "WHERE \
                song_id='" + focal_song_id + "';"
        cur.execute(q)        
        focal_song_f = cur.fetchall()
    
        # find all songs that are TOPOLOGICALLY close (based on artist similarity):
        
        # find all song of current artist
        q = "SELECT "\
                +"song_id "\
            +"FROM "\
                +song_features_table_name+" "\
            +"WHERE "\
                +"artist_id='" + focal_song_f[0][p['invkey']['artist_id']] + "';"
        cur.execute(q)
        song_ids_cur_artist = cur.fetchall()
    
        node_stats['neighbors_cur_artist'].append(len(song_ids_cur_artist))

        if debug_print:
            for song_id in song_ids_cur_artist:
                print "same artist songs: " + song_id[0]  
    
        
        # find all artists similar to current artist
        q = "SELECT "\
                +"similaro "\
            +"FROM "\
                +artist_similarities_table_name+" "\
            +"WHERE "\
                +"targeto='" + focal_song_f[0][p['invkey']['artist_id']] + "';"
        cur.execute(q)
        artist_ids_topo = cur.fetchall()
    
        node_stats['similar_artists'].append(len(artist_ids_topo))
    
        
        song_ids_topo = list()
        # add all song IDs of the similar artists
        for artist_id in artist_ids_topo:
            # fetch all songs of this artist
            q = "SELECT "\
                    +"song_id "\
                +"FROM "\
                    +song_features_table_name+" "\
                +"WHERE "\
                    +"artist_id='" + artist_id[0] + "';"
            cur.execute(q)
            cur_song_ids = cur.fetchall()
#            if len(cur_song_ids)>0:
#                cur_song_ids = cur_song_ids[0]
            for song_id in cur_song_ids:
                song_ids_topo.append(song_id)
        
            # stage 2 - goo deeper into the tree of artist_similarities. This requires holding a fifo of nodes / some sort of recursion                
        
        node_stats['neighbors_topo'].append(len(song_ids_topo))

        if debug_print:
            for song_id in song_ids_topo:
                print "similar artists songs: " + song_id[0]        
    
            
        # find all songs that are METRICALLY close (based on song features)
        song_ids_metric = list()
        for key in p['relevant_features']:
            key_range = ( focal_song_f[key] - p['unit_vec'][key]*p['construct_neighborhood_metric_diameter'] , focal_song_f[key] +  )
            q = "SELECT "\
                    +"song_id "\
                +"FROM "\
                    +song_features_table_name+" "\
                +"WHERE "\
                    +key+ ">="+ str(key_range[0]) + " AND "+ key+ "<="+ str(key_range[1])+";"
            cur.execute(q)
            cur_song_ids = cur.fetchall()
            for id in cur_song_ids[0]:
                song_ids_metric.append(id)
    
        node_stats['neighbors_metric'].append(len(song_ids_metric))
    
        
        # combine all potential neighbors song IDs
        song_ids_combined = list(set(song_ids_cur_artist) | set(song_ids_topo) | set(song_ids_metric))   
    
    
        # for each potential neighbor, measure its distance from the focal point
        potential_neighbors = list()
        for neighbor_song_id in song_ids_combined:    
 #           print "song id: "+neighbor_song_id
            # fetch features for each potential neighbor
            q = "SELECT \
                    *\
                FROM "\
                    +song_features_table_name+" "\
                +"WHERE "\
                    +"song_id='" + neighbor_song_id[0] + "';"
            cur.execute(q)   
            neighbor_song_f = cur.fetchall()
        
        
            # calculate distance to current song    
            sdist = MX_traverse.calcDistance(focal_song_f[0], neighbor_song_f[0], p['distance_type_construct'])
    
            # filter songs that are too distant    
            if sdist[0] < p['maximal_overall_distance']:
                potential_neighbors.append((neighbor_song_id[0],sdist[0], sdist[1]))
        
        # sort potential neighbors by distance    
    #    potential_neighbors = sorted(potential_neighbors, key=lambda x: x[1])
    
        if len(potential_neighbors)>0:
            node_stats['mean_dist'].append( np.mean([x[1] for x in potential_neighbors]) )
        else:
            node_stats['mean_dist'].append(-1)
    
    
        # add potential neighbors and truncate, if there are too many, based on distance
        for neighborhood_type in neighboorhoodtypes:
            for neighbor in potential_neighbors[neighborhood_type][0:min(max_MXG_neighbors[neighborhood_type], len(potential_neighbors[neighborhood_type]))]:
    #            print "n0 " + neighbor[0]
    #            print "n1 " + str(neighbor[1])
                q = "INSERT INTO "\
                        +graph_table_name+" \
                        (targeto, similaro, dist) \
                    VALUES \
                        ('"+ focal_song_id +"', '"+ neighbor[0] +"', '"+ str(neighbor[1]) +"');"
                cur.execute(q)
                q = "INSERT INTO "\
                        +graph_table_name+" \
                        (targeto, similaro, dist) \
                    VALUES \
                        ('"+ neighbor[0] +"', '"+ focal_song_id +"', '"+ str(neighbor[1]) +"');"
                cur.execute(q)
                
                edge_stats['dist'].append( neighbor[1] )
                edge_stats['vdist'].append( neighbor[2] )
            
            
    #            MXG_target.append( song_id[0] )
    #            MXG_source.append( potential_neighbors[0] )
    
    
    return node_stats, edge_stats
#			return render_template("play_specific.html", api_data=song_url)
#	else:
        print "next! " + request.form["user_play"];
#			echonest_id = "SOBOAQC12A8C13E3E9"#request.form["user_play"]
#			echonest_id_next = MX_traverse.pickNextSongWrapped( echonest_id ) #echonext_id
#			print echonest_id, echonest_id_next
        id_7digital = request.form["user_play"]#MX_traverse.get_7digital_id( echonest_id_next ) 
        song_url = OAuth.get_song_url(id_7digital);
#        print song_url
        id_7digital_next = MX_traverse.pickNextSongWrapped( id_7digital );#echonext_id
        request.form["user_play"] = id_7digital_next
        return render_template("play_specific.html", api_data=song_url)
    else:
        print "moshe"
        return render_template("play_test.html")



@app.errorhandler(404)
def page_not_found(error):
    return "Sorry, this page was not found.", 404  




# always the last function !!!!!!
if __name__ == "__main__":
    print "init"
    MX_traverse.init_globals()
    app.run(host="0.0.0.0", port=int("4070"))