3 * Reporting progress for long-running jobs
5 * (c) 2018 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the Trivial IP Encryption (TrIPE) Android app.
12 * TrIPE is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 3 of the License, or (at your
15 * option) any later version.
17 * TrIPE is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License
23 * along with TrIPE. If not, see <https://www.gnu.org/licenses/>.
26 package uk.org.distorted.tripe; package object progress {
28 /*----- Imports -----------------------------------------------------------*/
30 import scala.collection.mutable.{Publisher, Subscriber};
32 import java.lang.System.currentTimeMillis;
34 /*----- Progress displays -------------------------------------------------*/
37 protected val t0 = currentTimeMillis;
42 def eta(cur: Long): Double = {
43 /* Report the estimated time remaining in seconds, or -1 if no idea.
45 * The model here is very stupid. Weird jobs should override this and
46 * do something more sensible.
50 val delta = currentTimeMillis - t0
51 if (max < 0 || cur <= 0) -1 else delta*(max - cur)/cur.toDouble
54 protected def fmt1(n: Long): String = n.toString;
56 def format(cur: Long): String = {
59 if (max >= 0) { val fm = fmt1(max); s"%${fm.length}s/%s".format(fc, fm) }
65 class SimpleModel(val what: String, val max: Long) extends Model;
67 private val UDATA = Seq("kB", "MB", "GB", "TB", "PB", "EB");
69 trait DataModel extends Model {
70 override def fmt1(n: Long): String = {
71 val (x, u) = ((n.toDouble, "B ") /: UDATA) { (xu, n) => (xu, n) match {
72 case ((x, u), name) if x >= 1024.0 => (x/1024.0, name)
81 def failed(e: Exception);
84 trait JobReporter extends BaseReporter {
86 def change(model: Model, cur: Long);
89 trait OperationReporter extends BaseReporter {
90 def step(detail: String);
93 def withReporter[T, R <: BaseReporter]
94 (rep: R, body: R => T): T = {
95 val ret = try { body(rep) }
96 catch { case e: Exception => rep.failed(e); throw e; }
102 def note(msg: String);
105 def record(msg: String) { note(msg); commit(); }
107 def cancelled() { failed("cancelled"); }
108 def failed(msg: String);
110 def beginJob(model: Model): JobReporter
111 // = new JobReporter(model);
113 def beginOperation(what: String): OperationReporter
114 // = new OperationReporter(what);
116 def job[T](model: Model)(body: JobReporter => T): T =
117 withReporter(beginJob(model), body);
119 def operation[T](what: String)(body: OperationReporter => T): T =
120 withReporter(beginOperation(what), body);
123 /*----- That's all, folks -------------------------------------------------*/