1 /** 2 * Copyright (C) 2010-2014 IBM Corporation and Others. All Rights Reserved. 3 */ 4 package org.unicode.cldr.web; 5 6 import java.util.Comparator; 7 import java.util.Deque; 8 import java.util.LinkedList; 9 import java.util.Set; 10 import java.util.TreeSet; 11 12 import org.unicode.cldr.util.StackTracker; 13 14 import com.ibm.icu.dev.util.ElapsedTimer; 15 import com.ibm.icu.text.NumberFormat; 16 17 /** 18 * @author srl 19 * 20 */ 21 public class SurveyProgressManager implements CLDRProgressIndicator { 22 private static final boolean DEBUG_PROGRESS = true; 23 private Deque<SurveyProgressTask> tasks = new LinkedList<>(); 24 25 private class SurveyProgressTask implements CLDRProgressIndicator.CLDRProgressTask { 26 boolean dead = false; 27 int progressMax = 0; // "an operation is in progress" 28 int progressCount = 0; 29 String progressSub = null; 30 long taskTime = System.currentTimeMillis(); 31 long subTaskTime = taskTime; 32 String progressWhat = null; 33 SurveyProgressTask(String what, int max)34 public SurveyProgressTask(String what, int max) { 35 this.progressMax = max; 36 this.progressWhat = what; 37 this.progressCount = 0; 38 } 39 40 @Override close()41 public void close() { 42 if (tasks.isEmpty() || !tasks.contains(this)) { 43 SurveyLog.warnOnce("State Error: Closing an already-closed CLDRProgressIndicator at stack " + StackTracker.currentStack()); 44 } else { 45 tasks.remove(this); // remove from deque 46 } 47 if (DEBUG_PROGRESS && SurveyMain.isUnofficial()) 48 System.err.println("Progress (" + progressWhat + ") DONE - " 49 + ElapsedTimer.elapsedTime(taskTime, System.currentTimeMillis()) + " @" + SurveyMain.uptime); 50 dead = true; 51 } 52 53 @Override update(int count)54 public void update(int count) { 55 progressCount = count; 56 subTaskTime = System.currentTimeMillis(); 57 if (SurveyMain.isUnofficial()) System.err.println("Progress (" + progressWhat + ") on #" + progressCount + " @" + SurveyMain.uptime); 58 } 59 60 @Override update(int count, String what)61 public void update(int count, String what) { 62 progressCount = count; 63 progressSub = what; 64 subTaskTime = System.currentTimeMillis(); 65 // if(SurveyMain.isUnofficial()) System.err.println("Progress (" + progressWhat + ") on " + progressSub + " #"+progressCount + " @" + SurveyMain.uptime); 66 } 67 68 /** 69 * Update the sub-progress without moving the count 70 * 71 * @param what 72 */ 73 @Override update(String what)74 public void update(String what) { 75 progressSub = what; 76 if (progressMax < 0) { 77 progressCount++; 78 } 79 subTaskTime = System.currentTimeMillis(); 80 if (SurveyMain.isUnofficial()) System.err.println("Progress (" + progressWhat + ") on " + what + " @" + SurveyMain.uptime); 81 } 82 83 @Override startTime()84 public long startTime() { 85 return taskTime; 86 } 87 88 /** 89 * What's the most recent time that anything happened? 90 * 91 * @return 92 */ recentTime()93 public long recentTime() { 94 if (subTaskTime > taskTime) { 95 return subTaskTime; 96 } else { 97 return taskTime; 98 } 99 } 100 101 NumberFormat pctFmt = NumberFormat.getPercentInstance(); 102 103 @Override toString()104 public String toString() { 105 if (dead) 106 return ""; 107 StringBuffer buf = new StringBuffer(); 108 long now = System.currentTimeMillis(); 109 110 double max = progressMax; 111 112 buf.append("<b>" + progressWhat + "</b>"); 113 if ((now - taskTime) > 5000) { 114 buf.append(" <span class='elapsedtime'>" + ElapsedTimer.elapsedTime(taskTime, now) + "</span>"); 115 } 116 117 double cur = progressCount; 118 119 appendProgressBar(buf, cur, max); 120 121 if (progressMax >= 0) { // only show the actual number if >0 122 buf.append(progressCount + " of " + progressMax + " — "); 123 } 124 if (max > 0) { 125 double pct = (cur / max); 126 buf.append(pctFmt.format(pct)); 127 } else if (progressCount > 0) { 128 buf.append("(#" + progressCount + ")"); 129 } 130 if (progressSub != null) { 131 buf.append("<br/>" + progressSub); 132 } 133 if ((subTaskTime > taskTime) && ((now - subTaskTime) > 5000)) { 134 buf.append(" <span class='elapsedtime'>" + ElapsedTimer.elapsedTime(subTaskTime, now) + "</span>"); 135 } 136 return buf.toString(); 137 } 138 } 139 140 /* 141 * (non-Javadoc) 142 * 143 * @see 144 * org.unicode.cldr.web.CLDRProgressIndicator#openProgress(java.lang.String) 145 */ 146 @Override openProgress(String what)147 public CLDRProgressTask openProgress(String what) { 148 return openProgress(what, -100); 149 } 150 openConsoleProgress(final String what0)151 public static CLDRProgressTask openConsoleProgress(final String what0) { 152 return new CLDRProgressTask() { 153 ElapsedTimer et = new ElapsedTimer("Progress " + what0); 154 long startTime = System.currentTimeMillis(); 155 156 @Override 157 public void close() { 158 System.out.println(et + ": close"); 159 } 160 161 @Override 162 public void update(int count) { 163 System.out.println(et + ": Update #" + count); 164 } 165 166 @Override 167 public void update(int count, String what) { 168 System.out.println(et + ": Update " + what + " #" + count); 169 } 170 171 @Override 172 public void update(String what) { 173 System.out.println(et + ": Update " + what); 174 } 175 176 @Override 177 public long startTime() { 178 return startTime; 179 } 180 181 }; 182 } 183 184 /* 185 * (non-Javadoc) 186 * 187 * @see 188 * org.unicode.cldr.web.CLDRProgressIndicator#openProgress(java.lang.String, 189 * int) 190 */ 191 @Override openProgress(String what, int max)192 public CLDRProgressTask openProgress(String what, int max) { 193 SurveyProgressTask t = new SurveyProgressTask(what, max); 194 tasks.addLast(t); 195 if (SurveyMain.isUnofficial() && DEBUG_PROGRESS) 196 System.err.println("Progress (" + what + ") BEGIN"); 197 return t; 198 } 199 getProgress()200 public String getProgress() { 201 // make a list of non-dead tasks, sorted by age 202 Set<SurveyProgressTask> orderedTasks = new TreeSet<>(new Comparator<SurveyProgressTask>() { 203 204 @Override 205 public int compare(SurveyProgressTask arg0, SurveyProgressTask arg1) { 206 return (int) (arg1.recentTime() - arg0.recentTime()); 207 } 208 }); 209 for (SurveyProgressTask t : tasks) { 210 if (t != null && !t.dead) 211 orderedTasks.add(t); 212 } 213 214 StringBuffer buf = new StringBuffer(); 215 buf.append("<table id='progress-list' border=0 class='progress-list" 216 + (orderedTasks.isEmpty() ? " progress-idle" : " progress-busy") + "'><tr>"); 217 buf.append("<th>"); 218 if (orderedTasks.isEmpty()) { 219 buf.append("<span id='busy0' onclick='document.getElementById(\"progress\").className=\"popout\";'><!-- idle -->\u00BB</span>"); 220 } else { 221 buf.append("<span id='busy0' onclick='document.getElementById(\"progress\").className=\"popout\";'><!-- busy -->\u00BB</span>"); 222 } 223 buf.append("<span id='busy1' onclick='document.getElementById(\"progress\").className=\"\";'><!-- hide -->\u00AB</span>" 224 + "</th>"); 225 for (SurveyProgressTask t : orderedTasks) { 226 buf.append("<td>"); 227 buf.append(t.toString()); 228 buf.append("</td>"); 229 } 230 if (buf.length() > 0) { 231 buf.append("</tr></table>"); 232 } 233 return buf.toString(); 234 } 235 appendProgressBar(StringBuffer buf, double cur, double max)236 public static StringBuffer appendProgressBar(StringBuffer buf, double cur, double max) { 237 if (max > 0) { 238 if (cur > max) { 239 cur = max; 240 } 241 if (cur < 0) { 242 cur = 0; 243 } 244 245 double barWid = (cur / max) * SurveyMain.PROGRESS_WID; 246 247 int barX = (int) barWid; 248 int remainX = SurveyMain.PROGRESS_WID - barX; 249 250 buf.append("<table class='stprogress' border=0 ><tr height='12'>"); 251 if (barX > 0) { 252 buf.append("<td class='bar' width='" + barX + "' >"); 253 buf.append("</td>"); 254 } 255 if (remainX > 0) { 256 buf.append("<td class='remain' width='" + remainX + "'>"); 257 buf.append("</td>"); 258 } 259 buf.append("</table>"); 260 } 261 return buf; 262 } 263 264 } 265