# -*- coding:utf-8 -*-
# author = oulaline

import os
import sys
import codecs
import pandas as pd
import math

class recommender(object):
	def __init__(self, path):
		self.csvpath = path #格式应为'UserID','MusicID','Rating', 要有列头

	def readRatingDate(self, path='../ml-1m/ratings.dat'):  
	    ''''' 
	    读取评分数据并存储为csv文件 
	    :param path:文件路径 
	    :return: DataFrame 
	    '''  
	    f = pd.read_table(path,sep='::',names=['UserID','MusicID','Rating','Timestamp'],engine = 'python')  
	    f.to_csv('../ml-1m/ratings.csv',columns =['UserID','MusicID','Rating'], index=False)  
	    return f 

	def calcuteSimilarbyTag(self, series1,series2):  
	    '''
	    对两用户共同评价的tag计算余弦相似度 
	    :param data1: 数据集1 Series 
	    :param data2: 数据集2 Series 
	    :return: 相似度 
	    '''  
	    #print series1.dtypes
	    series3 = pd.merge(series1,series2,on = ['TagID'])
	    unionLen = len(series3)
	    if unionLen == 0: 
	    	return 0.0  
	    sum1 = (series3['Rating_x'] * series3['Rating_y']).sum()
	    den1 = math.sqrt( (series3['Rating_x'] * series3['Rating_x']).sum())
	    den2 = math.sqrt( (series3['Rating_y'] * series3['Rating_y']).sum())
	    return sum1/(den1*den2)
		
	def calcuteSimilarbyMusic(self, series1,series2):
		'''
		根据两用户听歌的歌曲或歌手的重合度计算相似度
		'''
		unionLen = len(set(series1) & set(series2))
		if unionLen == 0:
			return 0.0
		product = len(series1) + len(series2) - unionLen
		similarity = float(unionLen) / float(product)
		return similarity

	def calcuteUserbyMusic(self, targetID=1,TopN=10):  
	    ''''' 
	    计算targetID的用户与其他用户的相似度 
	    :return:相似度TopN的UserID
	    csv表头为['UserID','MusicID','Rating']
	    'MusicID'在不同的文件中既可指代歌手也可指代歌曲
	    '''  
	    frame = pd.read_csv(self.csvpath)   #返回数据类型： DataFrame 
	    targetUser = frame[frame['UserID'] == targetID]['MusicID']
	    #print "targetUser： \n", targetUser                        #目标用户数据  
	    otherUsersID = [i for i in set(frame['UserID']) if i != targetID]                   #其他用户ID  
	    otherUsers = [frame[frame['UserID'] == i]['MusicID'] for i in otherUsersID]         #其他用户数据  
	  
	    # 根据music计算相似度
	    similarlist = [self.calcuteSimilarbyMusic(targetUser,user) for user in otherUsers]
	    similarSeries = pd.Series(similarlist,index=otherUsersID)
	    return similarSeries.sort_values()[-TopN:].index

	def calcuteUserbyTag(self, targetID=1,TopN=10):
		'''
		表头为['UserID','TagID','Rating']
		'''
		frame=pd.read_csv(self.csvpath)   #返回数据类型： DataFrame
		targetUser = frame[frame['UserID'] == targetID]
		otherUsersID = [i for i in set(frame['UserID']) if i != targetID]
		otherUsers = [frame[frame['UserID'] == i] for i in otherUsersID] 
		
		similarlist = [self.calcuteSimilarbyTag(targetUser,user) for user in otherUsers]
		similarSeries = pd.Series(similarlist,index=otherUsersID)
		return similarSeries.sort_values()[-TopN:].index

if __name__ == "__main__":
	if len(sys.argv) < 2:
		path = '../ml-1m/ratings.csv'
	else:
		path = sys.argv[1]

	rec = recommender(path) 
	sim1 = rec.calcuteUserbyMusic(targetID = 1, TopN = 10)
	for si in sim1:
		print si
	


	path2 = '../ml-1m/tag_ratings.csv'
	rec2 = recommender(path2)
	sim2 = rec2.calcuteUserbyTag(targetID = 1, TopN = 10)
	
	print "asdasd"
	for si in sim2:
		print si





