# Definition of price.
price <- function(rating, age) {
	peakAge <- rating- 50
	price <- rating / 2
	ret <- sapply(1:length(rating), function(i){
				if (age[i] > peakAge[i]) {
					p <- price[i] * (5 - (age[i] - peakAge[i]) / 2)
				} else {
					p <- price[i] * 5 * (age[i] + 1) / peakAge[i]
				}
				return(ifelse(p<0, 0, p))
			})
	return(ret)
}

# Create a price dataset.
wineSet1 <- function(n=300) {
	randVector <- runif(n * 2)
	rating <- randVector[1:n] * 50 + 50
	age <- randVector[(n+1):(n*2)] * 50
	price <- price(rating, age) * (runif(1) * 0.2 + 0.9)
	data <- cbind(rating, age, price)
	return(data)
}

getDistances <- function(data, v1) {
	#distances <- sqrt(sum(sweep(data[,1:2],2,v1,FUN="-")^2))
	distances <- apply(data[,c(1,2)], 1, function(v2) sqrt(sum((v2 - v1) ^ 2)))
	distanceFrame <- cbind(distances,c(1:row(data)))#data.frame(distance=distances, index=1:nrow(data))
	ord=order(distanceFrame[,1])
	return(distanceFrame[ord,])
}

# KNN estimate. 
knnEstimate <- function(data, v1, k=3) {
	v <- unlist(v1)
	idx <- order(sqrt(colSums((t(data[,1:2]) - v) ^ 2)))[1:k]
	return(mean(data[idx,3]))
}
# Divide data set into training set and test set.
divideData <- function(data, test = 0.1) {
	testIndices <- which(runif(nrow(data)) < test)
	return(list(test=data[testIndices,], train=data[-testIndices,]))
}

testAlgorithm <- function(algF, trainSet, testSet) {
	errorVector <- apply(testSet, 1, function(row) {
				#print(paste(row[3], algF(trainSet, row[1:2])))
				return(row[3] - algF(trainSet, row[1:2]))
			} )
	return(mean(errorVector ^ 2))
}

crossValidate <- function(algF, data, trials=100, test=0.1) {
	errorVector <- sapply(1:trials, function(i) {
				#print(paste('Trail', i))
				dataSets <- divideData(data, test)
				v <- testAlgorithm(algF, dataSets[['train']], dataSets[['test']])
				return(v)
			})
	return(sum(errorVector) / trials)
}

data <- wineSet1()
print(crossValidate(weightedKNN, data))
