function [prediction, mre] = myKernelEstimator(myRow, train, kernelType, sortedEffortValues,hIndicator)

% now calculate and store the probability value for each instance in the
% neighborhood of our test instance
probValues = zeros(size(sortedEffortValues,1),1);

myBandwidths = [1/sqrt(size(train,1));2;4;8;50];
h = myBandwidths(hIndicator);

% size of sample and test

n = size(train, 1);
t = size(sortedEffortValues,1);

% effort values being mapped to 0-1
trainEffort = train(:,size(train,2));
trainEffort = (trainEffort - min(trainEffort))/(max(trainEffort) - min(trainEffort));
sortedEffortValuesBackup = sortedEffortValues; % store before scaling
sortedEffortValues = (sortedEffortValues - min(sortedEffortValues)) / (max(sortedEffortValues) -min(sortedEffortValues));


for counter = 1:t
    effToEstimate = sortedEffortValues(counter);
    % initialize prob value
    probValue = 0;
    
    %%%% GAUSSIAN KERNEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if strcmp(kernelType, 'gaussian') == 1
        if (effToEstimate/h) > 1
            probValue = 0;
        else
            for i = 1:n
                u = (effToEstimate - trainEffort(i))/h;
                probValue = probValue + ((1/(2*pi)) * exp(-0.5 * (u)^2));
            end
            probValue = probValue / (n * h);
            % below line is matlab version of the above 5 lines
%         probValue = ksdensity(trainEffort, effToEstimate,'width',h,'kernel','normal');
        end
    end
    
    %%% EPANECHNIKOV KERNEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if strcmp(kernelType,'epanechnikov') == 1
        % calculate the badwidth
        % bandwidth used here is acc. to Scott's rule over whole train dataset
%         h = sqrt(5)*std(train(:,size(train,2)))*(size(train,1)^(-0.2));
%         h = sqrt(5)*var(train(:,size(train,2)))*(size(train,1)^(-0.2));
        if (effToEstimate/h) > 1
            probValue = 0;
        else
            for i = 1:n
                u = (effToEstimate - trainEffort(i))/h;
                probValue = probValue + (0.75 * (1 - (u)^2));
            end
            probValue = abs(probValue) / (n * h);
            % below line is matlab version of the above 5 lines
%             probValue = ksdensity(trainEffort, effToEstimate,'width',h,'kernel','epanechnikov');
        end
    end
    
    
    %%% UNIFORM KERNEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if strcmp(kernelType,'uniform') == 1
        if (effToEstimate/h) > 1
            probValue = 0;
        else
            for i = 1:n
                u = (effToEstimate - trainEffort(i))/h;
                probValue = probValue + (0.5);
            end
            probValue = probValue / (n * h);
             % below line is matlab version of the above 5 lines
%             probValue = ksdensity(trainEffort, effToEstimate,'width',h,'kernel','box');
        end
    end
    
    %%% TRIANGULAR KERNEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if strcmp(kernelType,'triangular') == 1
        if (effToEstimate/h) > 1
            probValue = 0;
        else
            for i = 1:n
                u = (effToEstimate - trainEffort(i))/h;
                probValue = probValue + (1 - abs(u));
            end
            probValue = probValue / (n * h);
        end
    end
    
    
    %%% QUARTIC KERNEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if strcmp(kernelType,'quartic') == 1
        if (effToEstimate/h) > 1
            probValue = 0;
        else
            for i = 1:n
                u = (effToEstimate - trainEffort(i))/h;
                probValue = probValue + (15/16) * (1 - u^2)^2;
            end
            probValue = probValue / (n * h);
        end
    end
    
    
    %%% TRIWEIGHT KERNEL
    if strcmp(kernelType,'triweight') == 1
        if (effToEstimate/h) > 1
            probValue = 0;
        else
            for i = 1:n
                u = (effToEstimate - trainEffort(i))/h;
                probValue = probValue + (35/32) * (1 - u^2)^3;
            end
            probValue = probValue / (n * h);
        end
    end
    
    
    %%% COSINE KERNEL
    if strcmp(kernelType,'cosine') == 1
        if (effToEstimate/h) > 1
            probValue = 0;
        else
            for i = 1:n
                u = (effToEstimate - trainEffort(i))/h;
                probValue = probValue + (pi/4) * cos((pi/2) * u);
            end
            probValue = probValue / (n * h);
        end
    end
    
    probValues(counter) = probValue;
end

% now convert prob values into weights
if strcmp(kernelType, 'mendes') == 1
     %%%% MENDES KERNEL %%%% 
     % since mendes kernel is basically a weighting scheme, its
     % implementation goes here (unlike others kernels)
     weights = [size(sortedEffortValues,1):-1:1]'/size(sortedEffortValues,1);
elseif (max(probValues) - min(probValues)) == 0
    weights = 1 / size(probValues,1);
else
    weights = (probValues - min(probValues)) ./ (max(probValues) - min(probValues));
end

% now calculate prediction and related mre
prediction = mean(sortedEffortValuesBackup .* weights);
% prediction = median(sortedEffortValuesBackup .* probValues)/sum(probValues);
mre = abs(myRow(:,size(myRow,2)) - prediction)/myRow(:,size(myRow,2));

end