% Soft Computing Homework 8
% <your name>

% run: appraiser(0) - evaluating test_houses
%    or
% run: appraiser(1) - leave one out testing

function appraiser(testing)
%function appraiser(testing) implements CBR system
%where input is:
%testing - 0 - evaluating test_houses, 1 - leave one out testing

fprintf(1,'working\n');

load house_database.dat;
load test_houses.dat;
leave_one_out_testing = testing;	% if you are doing leave one out testing (0 - no, 1 - yes)
k = 4; 					% find 4 closest cases
dimensions = 7;                 	% number of attributes in a houses description
total_estimate_error = 0;		% used for leave one out testing

knn_found=[];
labeled_cases=house_database;
if leave_one_out_testing == 0
   input=test_houses;
   steps = 1;
else
   input=house_database;
   steps = 33;
   fprintf(1,'lat \tlong \tlot \tliving\tbed \tbath \tquality\tprice \test. \terror\n');
end

for n=1:steps:length(input(:,1));
   i=1;
   knn_set=[];

   while (i < length(labeled_cases(:,1))),
      %compute distance from input to all labeled cases

      %
      % TO DO: modify statement below to take all attributes into consideration.
      %        create a function to do this. 
      %

      candidate_dist=abs(input(n,1)-labeled_cases(i,1)) + abs(input(n,2)-labeled_cases(i,2));


      % if the test case is the house being evaluated then disregard it
      if leave_one_out_testing == 1 & (input(n,1) == labeled_cases(i,1)) & (input(n,2) == labeled_cases(i,2))
	candidate_dist = 100000;
      end
  
      if  (i <= k)
         %include input in set of knn
         knn_set=[knn_set;[labeled_cases(i,:),candidate_dist]];
      elseif (candidate_dist <= min(knn_set(:,dimensions+2)) | max(knn_set(:,dimensions+2)) > candidate_dist)
         %if distance of candidate to labeled case is smaller than the previous nearest neighbor
         % then replace farthest of knn with input
         max_neighbor_dist = max(knn_set(:,dimensions+2));
         replaced_flag = 0; 
         for j=1:k
            if knn_set(j,dimensions+2)==max_neighbor_dist & replaced_flag == 0
	       replaced_flag = 1;
               knn_set(j,:)=[labeled_cases(i,:),candidate_dist];
            end
         end
      end
      i=i+1;
   end

   %
   % TO DO: adapt the value of the cases based on difference from test case
   %        an example adjustment for bedrooms is given below
   %

   adapted_knn_set = knn_set;
   for i = 1:k
      bed_adjust = 1000 * (input(n,5) - adapted_knn_set(i,5));
      adapted_knn_set(i,8) = adapted_knn_set(i,8) + bed_adjust;
   end

 
   %
   % TO DO: aggregate the values of the cases to get a single value for the test house
   %

   estimated_value = round(sum(adapted_knn_set(:,dimensions + 1)) / k);

   %
   % Extra Credit TO DO: determine your confidence in the estimate
   %

   confidence_value = 'Medium';

   if leave_one_out_testing == 0 

     fprintf(1,'TEST HOUSE %d\n', n);
     fprintf(1,'lat \tlong \tlot \tliving\tbed \tbath \tquality\n');
     fprintf(1,'%d\t%d\t%d\t%d\t%d\t%3.1f\t%d\n',input(n,:));


     % show the non-adapted set of cases
     fprintf(1,'\n\nNON-ADAPTED CASES\n');
     fprintf(1,'lat \tlong \tlot \tliving\tbed \tbath \tquality\tvalue \tsimilarity\n');
     for i = 1:k
       fprintf(1,'%d\t%d\t%d\t%d\t%d\t%3.1f\t%d\t%d\t%d\n',knn_set(i,:));
     end

     % show the adapted set of cases
     fprintf(1,'\nADAPTED CASES\n');
     fprintf(1,'lat \tlong \tlot \tliving\tbed \tbath \tquality\tvalue \tsimilarity\n');
     for i = 1:k
       fprintf(1,'%d\t%d\t%d\t%d\t%d\t%3.1f\t%d\t%d\t%d\n',adapted_knn_set(i,:));
     end

     % print out the estimated value
     fprintf(1,'\nESTIMATED VALUE = %d\n', estimated_value); 

     fprintf(1,'CONFIDENCE IS %s\n\n\n', confidence_value); 

   else      % leave_one_out_testing == 1 

      fprintf(1,'%d\t%d\t%d\t%d\t%d\t%3.1f\t%d\t%d\t',input(n,:));
      estimate = round(sum(adapted_knn_set(:,dimensions + 1)) / k);
      estimate_error = abs(estimate - input(n,8));
      fprintf(1,'%d\t%d', estimate, estimate_error); 
      fprintf(1,'\n'); 
      total_estimate_error = total_estimate_error + estimate_error;
   end

end

if leave_one_out_testing == 1 
   fprintf(1,'average error = %d\n', total_estimate_error / (length(input(:,1)) / steps));
end
