
package com.uwetrottmann.shopr.algorithm;

import com.uwetrottmann.shopr.algorithm.model.Item;

import java.util.ArrayList;
import java.util.List;

public class AdaptiveSelection {

    private static final int NUM_RECOMMENDATIONS = 5;

    public static void main(String[] args) {
        adaptiveSelection();
    }

    private static void adaptiveSelection() {
        /*
         * TODO: Build an actual cycle with item output and user input.
         */
        Query query = new Query();
        Critique critique = new Critique();
        critique.item(null);
        boolean isAbort = false;

        while (!isAbort) {
            List<Item> recommendations = itemRecommend(query, NUM_RECOMMENDATIONS, critique);
            critique = userReview(recommendations, query);
            queryRevise(query, critique);
        }
    }

    /**
     * Takes the current query, number of recommended items to return, the last
     * critique. Returns a list of recommended items based on the case-base.
     */
    private static List<Item> itemRecommend(Query query, int numItems, Critique lastCritique) {
        /*
         * The caseBase will later be stored in a database (due to its size).
         * Think about optimizations which could be applied.
         */
        // Filter case-base to match hard-limits (location, opening hours)
        List<Item> caseBase = Utils.getLimitedCaseBase();

        List<Item> recommendations;

        if (lastCritique.item() != null && lastCritique.feedback().isPositiveFeedback()) {
            /*
             * Positive progress: user liked one or more features of one of the
             * recommended items.
             */
            /*
             * REFINE: Show similar recommendations by sorting the case-base in
             * decreasing similarity to current query. Return top k items.
             */
            Utils.sortBySimilarityToQuery(query, caseBase);
            recommendations = new ArrayList<Item>(caseBase.subList(0, numItems - 1));
        } else {
            /*
             * Negative progress: user disliked one or more of the features of
             * one recommended item. Or: first run.
             */
            // REFOCUS: show diverse recommendations
            int bound = 10;
            recommendations = BoundedGreedySelection
                    .boundedGreedySelection(query, caseBase, numItems, bound);
        }

        // Carry the critiqued so the user may critique it further.
        if (lastCritique.item() != null) {
            recommendations.add(lastCritique.item());
        }

        return recommendations;
    }

    /**
     * Takes the list of recommended items and elicits a critique on a feature
     * of one item from the user. Returns the liked/disliked item and which
     * feature value (! not just which feature !) was liked/disliked.
     * 
     * @param recommendations
     * @return
     */
    private static Critique userReview(List<Item> recommendations, Query query) {
        Utils.dumpToConsole(recommendations, query);

        int selection = Integer.valueOf(System.console().readLine(
                "Enter the number of item to critique: "));

        boolean isPositiveCritique = Integer.valueOf(System.console().readLine(
                "Like (1) or Dislike(0)? ")) == 1;

        // TODO: allow multiple attributes
        int attribute = Integer.valueOf(System.console().readLine(
                "Color (0) or type (1)?: "));

        Critique critique = new Critique();
        critique.item(recommendations.get(selection));
        critique.feedback(new Feedback().isPositiveFeedback(isPositiveCritique)
                .attribute(attribute));

        return null;
    }

    /**
     * Takes a liked/disliked item, which feature value was liked/disliked, the
     * current query. Returns a new query modified according to the given user
     * critique.
     */
    private static void queryRevise(Query query, Critique critique) {
        // TODO implement weighting, right now only replacing with item
        // attributes
        switch (critique.feedback().attribute()) {
            case 0:
                query.attributes().color(critique.item().attributes().color());
                break;
            case 1:
                query.attributes().type(critique.item().attributes().type());
                break;
        }
    }

}

@@ -86,24 +86,117 @@
 odel.Item;%0A%0A
+import java.io.BufferedReader;%0Aimport java.io.IOException;%0Aimport java.io.InputStreamReader;%0A
 import java.
@@ -2952,61 +2952,8 @@
 ed.%0A
-     * %0A     * @param recommendations%0A     * @return%0A
     
@@ -3104,83 +3104,108 @@
     
-int selection = Integer.valueOf(System.console().readLine(%0A                
+BufferedReader in = new BufferedReader(new InputStreamReader(System.in));%0A%0A        System.out.print(
 %22Ent
@@ -3237,27 +3237,25 @@
 critique: %22)
-);%0A
+;
 %0A        boo
@@ -3255,34 +3255,58 @@
     
-boolean isPositiveCritique
+int selection;%0A        try %7B%0A            selection
  = I
@@ -3320,32 +3320,18 @@
 valueOf(
-System.console()
+in
 .readLin
@@ -3324,32 +3324,36 @@
 eOf(in.readLine(
+));%0A
 %0A               
@@ -3349,20 +3349,33 @@
         
-    
+System.out.print(
 %22Like (1
@@ -3393,16 +3393,88 @@
 e(0)? %22)
+;%0A            boolean isPositiveCritique = Integer.valueOf(in.readLine()
 ) == 1;%0A
@@ -3474,16 +3474,20 @@
  == 1;%0A%0A
+    
         
@@ -3533,114 +3533,123 @@
     
-int attribute = Integer.valueOf(System.console().readLine(%0A                %22Color (0) or type (1)?: %22
+    System.out.print(%22Color (0) or type (1)?: %22);%0A            int attribute = Integer.valueOf(in.readLine(
 ));%0A%0A
+    
     
@@ -3688,32 +3688,36 @@
 ique();%0A        
+   
+ 
 critique.item(re
@@ -3743,24 +3743,28 @@
 election));%0A
+    
         crit
@@ -3847,16 +3847,20 @@
         
+    
 .attribu
@@ -3872,24 +3872,131 @@
 tribute));%0A%0A
+            return critique;%0A        %7D catch (IOException e) %7B%0A            e.printStackTrace();%0A        %7D%0A%0A
         retu

Use input method that works...