1 package org.unicode.cldr.util; 2 3 import java.util.Date; 4 import java.util.EnumSet; 5 import java.util.HashMap; 6 import java.util.HashSet; 7 import java.util.Map; 8 import java.util.Set; 9 import org.unicode.cldr.test.CheckCLDR; 10 import org.unicode.cldr.test.SubmissionLocales; 11 12 /** 13 * This interface is for objects which can expose information on which reports have been completed. 14 * 15 * @param T the type for each voter. Must be an Integer. 16 */ 17 public abstract class VoterReportStatus<T> { 18 /** 19 * Enumeration for the reports. In order shown in SurveyTool. Note: when adding an entry here, 20 * also update cldrText.js to add the display name, for example, 'special_r_personnames': 21 * 'Person Names' Also see {@link org.unicode.cldr.tool.Chart#forReport(ReportId, String)} 22 */ 23 public enum ReportId { 24 datetime, // non-Chart 25 zones, // non-Chart 26 compact, // non-Chart, aka 'numbers' 27 personnames; // Chart 28 29 /** 30 * True if this report is available in this vetting period 31 * 32 * @return 33 */ isAvailable()34 public boolean isAvailable() { 35 return (!CheckCLDR.LIMITED_SUBMISSION) 36 || (SubmissionLocales.getReportsAvailableInLimited().contains(this)); 37 } 38 getReportsAvailable()39 public static Set<ReportId> getReportsAvailable() { 40 if (!CheckCLDR.LIMITED_SUBMISSION) { 41 return EnumSet.allOf(ReportId.class); 42 } else { 43 return SubmissionLocales.getReportsAvailableInLimited(); 44 } 45 } 46 }; 47 48 public enum ReportAcceptability { 49 notAcceptable, 50 acceptable; 51 isAcceptable()52 boolean isAcceptable() { 53 return this == acceptable; 54 } 55 fromPair(boolean isComplete, boolean isAcceptable)56 static ReportAcceptability fromPair(boolean isComplete, boolean isAcceptable) { 57 if (isAcceptable) { 58 return acceptable; 59 } else if (isComplete) { 60 return notAcceptable; 61 } else { 62 return null; 63 } 64 } 65 }; 66 getReportStatus(T user, CLDRLocale locale)67 public abstract ReportStatus getReportStatus(T user, CLDRLocale locale); 68 69 public static class ReportStatus { 70 public EnumSet<ReportId> completed = EnumSet.noneOf(ReportId.class); 71 public EnumSet<ReportId> acceptable = EnumSet.noneOf(ReportId.class); 72 public Date date = null; 73 mark(ReportId r, boolean asComplete, boolean asAcceptable)74 public ReportStatus mark(ReportId r, boolean asComplete, boolean asAcceptable) { 75 return this.mark(r, asComplete, asAcceptable, null); 76 } 77 mark(ReportId r, boolean asComplete, boolean asAcceptable, Date date)78 public ReportStatus mark(ReportId r, boolean asComplete, boolean asAcceptable, Date date) { 79 if (!asComplete && asAcceptable) { 80 throw new IllegalArgumentException("Cannot be !complete&&acceptable"); 81 } 82 if (asComplete) { 83 completed.add(r); 84 } else { 85 completed.remove(r); 86 } 87 if (asAcceptable) { 88 acceptable.add(r); 89 } else { 90 acceptable.remove(r); 91 } 92 this.date = date; 93 return this; 94 } 95 getDate()96 public Date getDate() { 97 return date; 98 } 99 100 /** 101 * Return the acceptability enum for this report type 102 * 103 * @param r report type 104 * @return the acceptability enum, or null if there was no entry 105 */ getAcceptability(ReportId r)106 public ReportAcceptability getAcceptability(ReportId r) { 107 return ReportAcceptability.fromPair(completed.contains(r), acceptable.contains(r)); 108 } 109 } 110 111 /** 112 * Update a Resolver for a particular Report. The resolver will be cleared. Note that T must be 113 * an Integer for this to succeed. 114 * 115 * @param l locale 116 * @param r which report 117 * @param userList set of users 118 * @param res which 119 * @return vote statistics for each acceptability level 120 */ updateResolver( CLDRLocale l, ReportId r, Set<T> userList, VoteResolver<ReportAcceptability> res, Map<T, ReportAcceptability> votes)121 public Map<ReportAcceptability, Set<Integer>> updateResolver( 122 CLDRLocale l, 123 ReportId r, 124 Set<T> userList, 125 VoteResolver<ReportAcceptability> res, 126 Map<T, ReportAcceptability> votes) { 127 Map<ReportAcceptability, Set<Integer>> statistics = new HashMap<>(); 128 res.clear(); 129 votes.clear(); 130 res.setBaileyValue(null); 131 // Get the report status for each user 132 userList.forEach( 133 id -> { 134 // get the report status for this user 135 final ReportStatus rs = getReportStatus(id, l); 136 // convert the ReportStatus for the specific id, into an enum (or null) 137 final ReportAcceptability acc = rs.getAcceptability(r); 138 if (acc != null) { 139 // if not an abstention, add 140 res.add( 141 acc, 142 (Integer) id, 143 null, 144 rs.getDate()); // TODO: Cast because T must be an Integer. 145 // Refactor class to not be templatized 146 statistics.computeIfAbsent(acc, k -> new HashSet<>()).add((Integer) id); 147 votes.put(id, acc); 148 } 149 }); 150 return statistics; 151 } 152 } 153