How would I constantly increase a value after a certain amount of time? - scala

I'm trying to figure out how to increase a variable by + 20 every 10 seconds, any simple way to do this?

This is how I might do it.
import java.time.LocalTime
import java.time.temporal.ChronoUnit.SECONDS
class Clocker(initial :Long, increment :Long, interval :Long) {
private val start = LocalTime.now()
def get :Long =
initial + SECONDS.between(start, LocalTime.now()) / interval * increment
}
usage:
// start from 7, increase by 20 every 10 seconds
val clkr = new Clocker(7, 20, 10)
clkr.get //res0: Long = 7
// 11 seconds later
clkr.get //res1: Long = 27
// 19 seconds later
clkr.get //res2: Long = 27
// 34 seconds later
clkr.get //res3: Long = 67

Related

Flutter hours and minute count issue

I need to sum the hours and minutes so I am doing this like ill convert hours in second and minutes in second then sum it
var totalServiceSeconds = minsSeconds + hoursSeconds;
var c = Duration(seconds: totalServiceSeconds);
print('c ${c.toString()}');
it's showing c 25:05:00.000000 which is correct
Know I need to show this as hours and minutes in the text widget. So I am converting to DateTime like this
var format = DateFormat("HH:mm");
DateTime totalServiceTime = format.parse(c.toString());
But it's printing it like this totalServiceTime 1970-01-02 01:05:00.000
This issue is only when the hours are 24 or more. If my hours are 24 then it's showing 0 and if greater than 24 then it's showing 1 2 so on. I know it because it's considering 24 as 0 but what can I do about this?
I want to show 24 if it's 24 hours or if greater than 24 like 26 need to show 26.
You do not want to convert it into a DateFormat because time steps of 24 hours is how they count a full day. Instead you should format var c as shown below
var totalServiceSeconds = minsSeconds + hoursSeconds;
var c = Duration(seconds: totalServiceSeconds);
print('c ${c.toString()}');
String FormatDuration = "${c.inHours}:${c.inMinutes.remainder(60)}:${(c.inSeconds.remainder(60))}";
print(FormatDuration);
String FormatDuration2 = "${c.inHours} hours ${c.inMinutes.remainder(60)} minutes ${(c.inSeconds.remainder(60))} seconds";
print(FormatDuration2);
The output will then be
c 25:05:00.000000 <-------previous
25:5:0 <-------new option 1
25 hours 5 minutes 0 seconds <-------new option 2

How to convert the time to minutes of Timer

I have this time that starts when a product is initialized and I want to format it to 00:00 instead of just 0.
Timer _timer;
_startTimer(prod) {
prod.tempo = 0;
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
prod.tempo++;
});
});
}`
[you can se the time in red I want to convert][1]
[1]: https://i.stack.imgur.com/vCv7p.jpg
If you have a total number of seconds, you can pretty print it with:
String toTimeField(int n) => n.toString().padLeft(2, '0');
var seconds = totalSeconds % 60;
var minutes = totalSeconds ~/ 60;
var prettyDuration = '${toTimeField(minutes)}:${toTimeField(seconds)}`;
That said, if you want to measure a duration, you're usually better off keeping track of the starting time and then computing the difference with the current time. That prevents accumulating error if there are any timing discrepancies from when your callback fires. You can use DateTime.now() to get the current time, store it, and then when your callback fires, call DateTime.now() again and subtract the original value. Or use the Stopwatch class, which does that for you. Using Stopwatch and Duration, you'd do:
_startTimer(prod) {
prod.stopwatch = Stopwatch();
...
}
...
final elapsed = prod.stopwatch.elapsed;
var seconds = elapsed.inSeconds % 60;
var minutes = elapsed.inMinutes;
Finally, I also recommend avoiding using : when printing durations since it could easily be misinterpreted. Does 12:34 represent a time? Does it represent 12 hours and 34 minutes or 12 minutes and 34 seconds? Printing durations as 12m34s is much clearer.
You can format the String as follows:
var seconds = prod.tempo % 60;
var minutes = (prod.tempo - seconds) / 60;
//if you have less than 10 seconds/minutes, prepend a '0':
String secondsAsString = seconds < 10 ? '0$seconds' : seconds;
String minutesAsString = minutes < 10 ? '0$minutes' : minutes;
String displayTime = 'Tempo: ' + secondsAsString + ':' + minutesAsString;

DateTime: Difference between Hour and Integer

I have some mistakes, in my code in the 2 lines where a comment above them:
import java.time.temporal.ChronoUnit
import java.time.LocalTime
import scala.concurrent.duration._
val t = LocalTime.now()
def toStart(t: LocalTime) = {
val start = LocalTime.of(9, 0)
val midEnd = LocalTime.of(13, 0)
val midStart = LocalTime.of(14, 0)
val end = LocalTime.of(18, 0)
if (t.isBefore(start)) 0.hours
// if (9 > myHour < 13 ==> myHour + 9 Hours, I wrote: - 9.hours instead of + 4.hours
else if (t.isBefore(midEnd)) t.until(midEnd, ChronoUnit.MILLIS).millis - 9.hours
else if (t.isBefore(midStart)) 4.hours
// if (14 > myHour < 18 Then (myhour - 14) + 4
else if (t.isBefore(end)) t.until(end, ChronoUnit.MILLIS).millis
else 8.hours
}
implicit class formatter(d: FiniteDuration) {
def withMinutes = {
val l = d.toMinutes
s"${l / 60}:${l % 60}"
}
def withSeconds = s"${d.toHours}:${d.toMinutes % 60}:${d.toSeconds % 60}"
}
The test of the function ToStart, is false in these tow cases:
scala> toStart(LocalTime.of(9, 30, 24)).withSeconds
res89: String = -5:-30:-24
scala> toStart(LocalTime.of(12, 30, 32)).withSeconds
res90: String = -8:-30:-32
scala> toStart(LocalTime.of(14, 30, 45)).withSeconds
res92: String = 3:29:15
scala> toStart(LocalTime.of(16, 22, 44)).withSeconds
res93: String = 1:37:16
How can I change my code to find the best result ?
Code should be similar to my answer to you here, but you need to understand what I did. You definitely need to check api calls I used, but I added some additional comments:
import java.time.temporal.ChronoUnit
import java.time.LocalTime
import scala.concurrent.duration._
val t = LocalTime.now()
// start of the day
val start = LocalTime.of(9, 0)
// end of first half
val midEnd = LocalTime.of(13, 0)
// start of second half
val midStart = LocalTime.of(14, 0)
// end of the day
val end = LocalTime.of(18, 0)
// here we define duration of first half a day: diff between start of a day and midEnd (end of first half)
val firstHalf = start.until(midEnd, ChronoUnit.MILLIS).millis
// here we define duration of second half a day: diff between start of second half a day and end of a day
val secondHalf = midStart.until(end, ChronoUnit.MILLIS).millis
def toStart(t: LocalTime) = {
// when checked time is before start of a day
if (t.isBefore(start)) 0.hours
// otherwise when checked time is before end of first half (will be diff between start time and checked time)
else if (t.isBefore(midEnd)) start.until(t, ChronoUnit.MILLIS).millis
// otherwise when checked time is before start of second half (will be duration of first half)
else if (t.isBefore(midStart)) firstHalf
// otherwise when checked time is before end of a day (will be duration of first half + duration of diff between checked time and start of second half)
else if (t.isBefore(end)) firstHalf + midStart.until(t, ChronoUnit.MILLIS).millis
// otherwise sum of durations
else firstHalf + secondHalf
}
// here you can add any specific format for evaluated duration
implicit class formatter(d: FiniteDuration) {
def withMinutes = {
// convert to minutes
val l = d.toMinutes
// format
s"${l / 60}:${l % 60}"
}
}
toStart(t).withMinutes
toStart(LocalTime.of(9, 30)).withMinutes
toStart(LocalTime.of(12, 30)).withMinutes
toStart(LocalTime.of(13, 30)).withMinutes
toStart(LocalTime.of(14, 30)).withMinutes
Spend some time and check java.time api (specifically LocalTime.until). Check FiniteDuration api to understand .millis suffix I used

Date intervals keeping state

My task is to write function, that takes 2 LocalDateTime instances and generate list of intervals, splitted by 15 minutes
case class Interval(start:LocalDateTime, end:LocalDateTime)
so, for example if startDate = 2 Aug 2017 14:30:15 and endDate is 2 Aug 2017 15:00:00, intervals should be
List(Interval(2 Aug 2017 14:30:15, 2 Aug 2017 14:45:15), Interval(2 Aug 2017 14:45:15, 2 Aug 2017 15:00:00))
Here, is 2 main complications(at least for me)
1) If end date is less then prevDate + 15 min, then we need take min from(prevdate + 15 min, endDate)
2) We need somehow keep the state, because start of each interval is end of previous interval.
I am able to create imperative version, but I want to do it in functional style, please, help!)
x => {
var start = x.startTime
var end = min(findRightBorder(start), x.endTime)
var result = ListBuffer(Interval(start, end))
while (end.isBefore(x.endTime)) {
start = end
end = min(start.plusMinutes(QUARTER_MINUTES), x.endTime)
result += Interval(start, end)
}
result.toList
}
private def findRightBorder(dt: LocalDateTime): LocalDateTime = {
val minute = dt.getMinute
if (minute >= 0 && minute < 15) dt.withMinute(15)
else if (minute >= 15 && minute < 30) dt.withMinute(30)
else if (minute >= 30 && minute < 45) dt.withMinute(45)
else if (minute >= 45 && minute < 60) dt.withMinute(0).plusHours(1)
else dt
}
private def min(dt1: LocalDateTime, dt2: LocalDateTime): LocalDateTime = {
if (dt1.compareTo(dt2) < 0) dt1 else dt2
}
Another solution with streams:
x => {
Stream
.from(0)
.map(i => x.startTime.plusMinutes(i * QUARTER_MINUTES))
.takeWhile(_.isBefore(x.endTime))
.map(s => Interval(s, min(s.plusMinutes(QUARTER_MINUTES), x.endTime)))
.toList
}
Here's one way to go about this.
import java.time.LocalDateTime
case class Interval(start:LocalDateTime, end:LocalDateTime)
val dt1: LocalDateTime = ??? //some start DateTime
val dt2: LocalDateTime = ??? //some end DateTime
// a (potentially) infinite Stream of dates at 15 minute intervals
// starting at dt1 but ending before dt2
val dates = Stream.iterate(dt1)(_.plusMinutes(15L))
.takeWhile(_.isBefore(dt2))
val result = dates.sliding(2) //pair the dates together
.toSeq //a Seq is easier to append to
.map{case Seq(from,to) => Interval(from,to)} //make Intervals
.:+(Interval(dates.last,dt2)) //append the final Interval
.toList //if you need a List result

Scala, iterating a collection, working out 10% points

While iterating an arbitrarily-sized List, I'd like to print some output at ~10% intervals to show that the iteration is progressing. For any list of 10 or more elements, I want 10 outputs printed.
I've played around with % and Math functions, but am not always getting 10 outputs printed unless the list sizes are multiples of 10. Would appreciate your help.
One possibility is to calculate 10% of the size based on your input, and then use IterableLike.grouped to group based on that percent:
object Test {
def main(args: Array[String]): Unit = {
val range = 0 to Math.abs(Random.nextInt(100))
val length = range.length
val percent = Math.ceil((10.0 * length) / 100.0).toInt
println(s"Printing by $percent percent")
range.grouped(percent).foreach {
listByPercent =>
println(s"Printing $percent elements: ")
listByPercent.foreach(println)
}
}
}
Unless the length of your list is divisible by 10, then you are not going to get 10 print statements. Here I am rounding by interval up (ceil) so you will have less print statements. You could used Math.floor which would round down, and give you more print statements.
// Some list
val list = List.range(0, 27)
// Find the interval that is roughly 10 percent
val interval = Math.ceil(list.length / 10.0)
// Zip the list with the index, so that we can look at the indexes
list.zipWithIndex.foreach {
case (value, index) =>
// If an index is divisible by out interval, do your logging
if (index % interval == 0) {
println(s"$index / ${list.length}")
}
// Do something with the value here
}
Output:
0 / 27
3 / 27
6 / 27
9 / 27
12 / 27
15 / 27
18 / 27
21 / 27
24 / 27