package com.pr0gramm.statistics.helper; import com.pr0gramm.statistics.Main; import com.pr0gramm.statistics.api.Item; import com.pr0gramm.statistics.api.User; import com.pr0gramm.statistics.api.UserInfo; import com.pr0gramm.statistics.generator.StatisticsGenerator; import com.pr0gramm.statistics.predicate.ConditionalPredicateCombination; import com.pr0gramm.statistics.predicate.GeneralPredicate; import com.pr0gramm.statistics.predicate.OperatorPredicate; import com.pr0gramm.statistics.toolbox.ConditionalOperatorType; import com.pr0gramm.statistics.toolbox.SortOption; import com.pr0gramm.statistics.toolbox.SortType; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.logging.Level; /** * Helper methods for statistics requests. * <p> * Created by koray on 30/01/2017. */ public class StatisticsHelper { public static void parseItemsStatsRequest(ArrayList<Item> items, String[] predicate) { if (items.size() < 1) { Main.getLogger().log(Level.WARNING, "There are no cached items to generate stats!"); Main.getLogger().log(Level.WARNING, "Please use 'readitems <path>' to read items from the disk " + "or 'downloaditems <outputPath>' to download all items!"); return; } SortOption sortOption = filterPredicates(predicate); ArrayList<GeneralPredicate<Item>> itemPredicates = generatePredicates(sortOption.getPredicate(), Item.class); if (itemPredicates == null) { Main.getLogger().log(Level.WARNING, "Statistics could not be generated!"); return; } StatisticsGenerator<Item> itemGenerator = new StatisticsGenerator<Item>(items, itemPredicates); itemGenerator.generate(); Main.getLogger().info("There are " + itemGenerator.getStatisticsList().size() + " out of " + items.size() + " items which satisfy all given predicates!"); Main.getLogger().info("------- Showing the top " + sortOption.getTop() + " items -------"); Main.getLogger().info("--- Sorted by field " + sortOption.getField() + "\n\n"); ArrayList<Item> sorted = itemGenerator.sort(sortOption); printTop(sortOption, sorted); } public static void parseUsersStatsRequest(ArrayList<User> users, String[] predicate) { if (users.size() < 1) { Main.getLogger().log(Level.WARNING, "There are no cached users to generate stats."); Main.getLogger().log(Level.WARNING, "Please use 'readusers <path>' to read users from the disk " + "or 'downloadusers <outputPath>' to download all users!"); return; } SortOption sortOption = filterPredicates(predicate); // Default field is user.id for users if (sortOption.getField().equals("id")) { sortOption.setField("user.id"); } ArrayList<GeneralPredicate<User>> userPredicates = generatePredicates(sortOption.getPredicate(), User.class); if (userPredicates == null) { Main.getLogger().log(Level.WARNING, "Statistics could not be generated!"); return; } StatisticsGenerator<User> userGenerator = new StatisticsGenerator<User>(users, userPredicates); userGenerator.generate(); Main.getLogger().info("There are " + userGenerator.getStatisticsList().size() + " out of " + users.size() + " users which satisfy all given predicates!"); Main.getLogger().info("------- Showing the top " + sortOption.getTop() + " users -------"); Main.getLogger().info("--- Sorted by field " + sortOption.getField() + "\n\n"); ArrayList<User> sorted = userGenerator.sort(sortOption); printTop(sortOption, sorted); } public static void parseUserInfoStatsRequest(ArrayList<User> users, String[] predicate) { if (users.size() < 1) { Main.getLogger().log(Level.WARNING, "There are no cached users to generate stats."); Main.getLogger().log(Level.WARNING, "Please use 'readusers <path>' to read users from the disk " + "or 'downloadusers <outputPath>' to download all users!"); return; } SortOption sortOption = filterPredicates(predicate); // Get user info elements ArrayList<UserInfo> userInfos = new ArrayList<UserInfo>(); for (User u : users) { if (u.getUser() != null) { userInfos.add(u.getUser()); } } ArrayList<GeneralPredicate<UserInfo>> userInfoPredicates = generatePredicates(sortOption.getPredicate(), UserInfo.class); if (userInfoPredicates == null) { Main.getLogger().log(Level.WARNING, "Statistics could not be generated!"); return; } StatisticsGenerator<UserInfo> userInfoGenerator = new StatisticsGenerator<UserInfo>(userInfos, userInfoPredicates); userInfoGenerator.generate(); Main.getLogger().info( "There are " + userInfoGenerator.getStatisticsList().size() + " out of " + userInfos.size() + " user info elements which satisfy all given predicates!"); Main.getLogger().info("------- Showing the top " + sortOption.getTop() + " userinfo -------"); Main.getLogger().info("--- Sorted by field " + sortOption.getField() + "\n\n"); ArrayList<UserInfo> sorted = userInfoGenerator.sort(sortOption); printTop(sortOption, sorted); } private static <T> ArrayList<GeneralPredicate<T>> generatePredicates(String[] predicate, Class<T> predicateType) { ArrayList<GeneralPredicate<T>> predicates = new ArrayList<GeneralPredicate<T>>(); LinkedList<String> list = new LinkedList<String>(Arrays.asList(predicate)); boolean running = true; ConditionalOperatorType lastType = null; while (running) { String field = list.poll(); String operator = list.poll(); String value = list.poll(); if (field == null && operator == null && value == null) { running = false; continue; } else if (field == null || operator == null || value == null) { warnPredicate(); return null; } OperatorPredicate<T> operatorPredicate = new OperatorPredicate<T>(predicateType); try { operatorPredicate.parsePredicate(new String[] { field, operator, value }); } catch (NoSuchFieldException e) { Main.getLogger().log(Level.WARNING, "The field with the name '" + field + "' could not be found!"); return null; } if (lastType == null) { predicates.add(operatorPredicate); } else { if (predicates.size() < 1) { Main.getLogger().log(Level.WARNING, "Something went totally wrong and I bet the programmer doesn't know what the problem is..."); return null; } GeneralPredicate<T> oldPred = predicates.get(predicates.size() - 1); predicates.remove(predicates.size() - 1); ConditionalPredicateCombination<T, GeneralPredicate<T>> combinedPred = new ConditionalPredicateCombination<>( oldPred, operatorPredicate, lastType); lastType = null; predicates.add(combinedPred); } // Getting next combinator or finishing the loop String combinator = list.poll(); if (combinator == null) { running = false; } else { ConditionalOperatorType type = ConditionalOperatorType.fromString(combinator); if (type == null) { Main.getLogger().log(Level.WARNING, "The conditional operator " + combinator + " is not supported. Please use either && or ||"); return null; } lastType = type; } } return predicates; } private static SortOption filterPredicates(String[] predicate) { int top = 5; String sortField = "id"; SortType sortType = SortType.ASCENDING; ArrayList<String> predicateList = new ArrayList<String>(Arrays.asList(predicate)); Iterator<String> predicateIterator = predicateList.iterator(); while (predicateIterator.hasNext()) { String s = predicateIterator.next(); if (s == null) { continue; } if (s.startsWith("--top=")) { String number = s.replace("--top=", ""); if (DecimalHelper.isInt(number)) { top = Integer.parseInt(number); } predicateIterator.remove(); } else if (s.startsWith("--sort_type=")) { SortType sort = SortType.fromString(s.replace("--sort_type=", "")); if (sort != null) { sortType = sort; } predicateIterator.remove(); } else if (s.startsWith("--sort_field=")) { sortField = s.replace("--sort_field=", ""); predicateIterator.remove(); } } String[] filteredPredicates = new String[predicateList.size()]; filteredPredicates = predicateList.toArray(filteredPredicates); SortOption sortOption = new SortOption(sortType, sortField, top, filteredPredicates); return sortOption; } private static void warnPredicate() { Main.getLogger().log(Level.WARNING, "Predicates must follow the following rule: " + "<memberName> (== | != | > | < | >= | <=) <value>" + "\nand can be combined with && or ||"); } private static <T> void printTop(SortOption sortOption, ArrayList<T> sorted) { if (sortOption.getSortType() == SortType.DESCENDING) { int minIndex = sorted.size() - 1 - sortOption.getTop(); minIndex = minIndex < -1 ? -1 : minIndex; for (int i = sorted.size() - 1; i > minIndex; i--) { logPlacing(i + 1, sorted.get(i)); } } else { for (int i = 0; i < sortOption.getTop(); i++) { if (sorted.size() > i) { logPlacing(i + 1, sorted.get(i)); } } } } private static void logPlacing(int number, Object object) { String info = ""; info = info + "Number " + number + ":\n"; info = info + object.toString(); info = info.replace("\n", "\n "); Main.getLogger().info(info); } }