Is it possible to use Millis() function to calculate total time taken? - esp8266

I have two conditional statement ,
for example ,
if(x<1&&y>6)
{
//get the total time(second) inside this conditional statement
}
if(x<20&&y>30)
{
//get the total time(second) inside this conditional statement
}
My question is,
is it possible use Millis () function to calculate the total time in each "if condition"??
or any other method to calculate time?
please give me some code examples.
Thanks

I have did it according to my understanding if there is something else you were trying to do tell me i will change it accordingly.
uint32_t sec1, sec2;
uint32_t sec = millis()/1000;
if(x<1&&y>6) {
//get the total time(second) inside this conditional statement
//Adding time for summing up the seconds
sec1 = sec1 + (millis() / 1000) - sec;
}
if(x<20&&y>30) {
//get the total time(second) inside this conditional statement
//Adding time for summing up the seconds
sec2 = sec2 + (millis() / 1000) - sec;
}

Related

Convert circular, continuous UISlider value to a counter

In my app, I have created a circular, continuous slidable CircularSlider (this one). It has a minimumValue of 1.0 and a maximumValue of 10. Now, I'd like my users to be able to just keep sliding in circles to increase an NSInteger used somewhere in the app.
I tried doing that by writing the code below.
- (void)sliderChanged:(UICircularSlider *)slider {
int val = (int)slider.value;
slider.value = val;
int delta = val - self.oldValue;
if (self.oldValue == self.circularSlider.maximumValue && val == 0) {
delta = 1;
}
self.number += delta;
self.oldValue = val;
}
This works, but really sketch. Sometimes the value will drop by 10, caused by the slider giving me value of 10 and right afterwards a value of 0. It also doesn't work if the users starts scrubbing backwards and numbers start decreasing. I was wondering if there's a better way to achieve the same thing. Any ideas?
I think a better approach is to first figure out what direction the user moved. This can be done by checking which direction has the closest distance between the new and the old position. Care must be taken to check for passing the border. Then it is a simple matter of adjusting the delta depending on direction.
My solution code assumes the the slider starts at zero, which I would recommend you to use instead of 1, since calculations are easier. If you really want to start at 1 it can be adjusted. I also have defined the maximum value as a constant SLIDER_MAX_VALUE, which you could change to a variable instead. Finally, I changed self.number to a CGFloat, so do the cast when using the number instead. This is important, otherwise you get rounding errors when sliding. If you really want an integer, use two variables, and assign the integer variable from the float.
#define SLIDER_MAX_VAL 10
- (void)sliderChanged:(UICircularSlider *)slider {
CGFloat delta = slider.value - self.oldValue;
if ((delta > 0 && delta < SLIDER_MAX_VAL / 2) ||
(delta < 0 && delta < -SLIDER_MAX_VAL / 2)) {
// Moving forward
if (delta < 0)
delta += SLIDER_MAX_VAL;
} else {
// Moving backward
if (delta > 0)
delta -= SLIDER_MAX_VAL;
}
self.number += delta; // Change to CGFloat
self.oldValue = slider.value;
}

Creating a Scale Between 0 and 1 Even when Higher numbers are passed in

I want to write an algorithm which allows me to rescale numbers to between 0 and 1. This means if I pass 25, 100, 500 then it should generate a new scale and represent those numbers on a scale of 0 to 1.
Here is what I have which is incorrect and does not make sense.
height: item.height/item.height * 20
Pass in the numbers in an array.
Loop through the numbers and find the max.
Map the array of integers to an array of Doubles, each one being the value from the source array, divided by the max.
Try to write that code. If you have trouble, update your question with your attempt and tell us what's going wrong.
EDIT:
Your answer shows how to print your resulting scaled values, but you implied that you actually want to create a new array containing the scaled values. For that you could use a function like this:
func scaleArray(_ sourceArray: [Int]) -> [Double] {
guard let max = sourceArray.max() else {
return [Double]()
}
return sourceArray.map {
return Double($0)/Double(max)
}
}
Edit #2:
Here is code that would let you test the above:
func scaleAndPrintArray(_ sourceArray: [Int]) {
let scaledArray = scaleArray(sourceArray)
for index in 0..<sourceArray.count {
print(String(format: "%3d", sourceArray[index]), String(format: "%0.5f",scaledArray[index]))
}
}
for arrayCount in 1...5 {
let arraySize = Int(arc4random_uniform(15)) + 5
var array = [Int]()
for _ in 1..<arraySize {
array.append(Int(arc4random_uniform(500)))
}
scaleAndPrintArray(array)
if arrayCount < 5 {
print("-----------")
}
}
(Sorry but I don't know swift)
If you're wanting to create a linear scale, a linear equation is y(x) = m*x + c. You wish the output to range from 0 to 1 when the input ranges from the minimum value to the maximum (your question is ambiguous, maybe you may wish to lock y(0) to 0).
y(0) = min
y(1) = max
therefore
c = min
m = max - min
and to find the value of any intervening value
y = m*x + c

Understanding random numbers in iOS Swift 2

How do I make a random number continue to change over time in the program (I.E. become a new one within the range everytime I want to use it)?
I'm stumped. I've read more than 20 different posts and articles on how to generate random numbers in this language (which I'm pretty new to) and I just can't seem to get it to work.
I'm basically trying to get a random double from 1.0-3.0. I can do this pretty easily, but once it has selected that number it doesn't change. This is my code that I use:
var randomNumber:Double = (Double(arc4random() % 3) + 1);
Then I use this as a value for the line:
SKAction.waitForDuration(randomNumber)
Every time I run this I want to change the number again, but once the program starts it continues that same number (It's different every time i reset the program)
I understand how to generate the number, but I can't seem to find anything on updating it!
I've tried adding
randomNumber = (Double(arc4random() % 3) + 1);
into the code in a spot where it will be ran many times, but it still gives me the same thing.
I'm very familiar with c++ so if you're trying to explain something you can reference its style and I will most likely understand.
What you need it is a read only computed property that will return a new random every time you try to access it:
var randomNumber: Double {
return Double(arc4random_uniform(3).successor())
}
print(randomNumber) // 2.0
print(randomNumber) // 2.0
print(randomNumber) // 1.0
print(randomNumber) // 3.0
print(randomNumber) // 3.0
Use:
SKAction.waitForDuration(sec: NSTimeInterval, withRange: NSTimeInterval)
where sec is the middle of the range in time you want to use, since range goes in a +- direction.
So in your case you want:
SKAction.waitForDuration(2, withRange: 2), this will get you a range of 1 to 3 (-1 to 1 range)
If for some reason you need a method that will constantly create a new random wait, you can always do:
extension SKAction
{
func waitForRandomDuration() -> SKAction
{
var randomNumber:Double = (Double(arc4random() % 3) + 1);
return SKAction.waitForDuration(randomNumber);
}
}
And then make sure that you add this as a new action onto your sprite every time you need to get it done, if you store it into a variable, your randomness won't change.
Try this code:
func randomNumberBetween1_0And3_0() -> Double {
return 1 + Double(arc4random_uniform(2000)) / 1000.0
}
for index in 1...10 {
print(randomNumberBetween1_0And3_0())
}
Sample output is:
2.087
1.367
1.867
1.32
2.402
1.803
1.325
1.703
2.069
2.335

Trouble with Grand Central Dispatch using Swift

I have the following function that doesn't behave as I would have expected.
func dispatchTrouble(startValue:Float, endValue:Float, duration:Float)
{
//100 increment steps per second
let incrementSteps = duration * 100
for(var step = 0.0 as Float; step < incrementSteps; step++)
{
var delayInSeconds = step * (duration / incrementSteps)
let answer = Float(NSEC_PER_SEC) * delayInSeconds
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(answer))
println(step)
//Using GCD to perform this on the main thread.
dispatch_after(popTime, dispatch_get_main_queue()){
println(step)
let fraction = step / incrementSteps
let incrementedValue = startValue + (endValue - startValue) * fraction
println(incrementedValue)
}
}
}
I expected the println(incrementedValue) statement to display a value that incremented from startValue to endValue and to finish in the number of seconds passed in duration.
However the behavior I get is that the code in the dispatch_after closure only prints the final value, it never prints the increments.
The delay occurs as expected, but the values are all calculated as if the for-loop had already completed. The first println(step) does show step incrementing, but the second one only shows the final value.
I clearly have a misunderstanding of how this should work. I expected that the code in the closure would hold the values that existed at the time the dispatch_after method was called, but it acts like it uses whatever the value is at the time it actually executes instead.
How can I capture the values at each iteration of the for-loop and execute the code in the closure using that?
All the closures you send to GDC are pointing to the same step variable. That means that every time one of them executes, it has the value it had when the loop ended.
Try changing your code to this:
func dispatchTrouble(startValue:Float, endValue:Float, duration:Float)
{
//100 increment steps per second
let incrementSteps = duration * 100
for(var step = 0.0 as Float; step < incrementSteps; step++)
{
var delayInSeconds = step * (duration / incrementSteps)
let answer = Float(NSEC_PER_SEC) * delayInSeconds
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(answer))
println(step)
let stepCopy = step
//Using GCD to perform this on the main thread.
dispatch_after(popTime, dispatch_get_main_queue()){
println(stepCopy)
let fraction = stepCopy / incrementSteps
let incrementedValue = startValue + (endValue - startValue) * fraction
println(incrementedValue)
}
}
}
It'll work like that. The closure is doing a retain on step, as explained on the swift reference.
Unlike Objective-C blocks which capture values, Swift closures capture variables. That means where an Objective-C block would have captured 100 different values of the "step" variable, the Swift closure captures the variable itself and prints its value at the time the closure is called.
The best way to fix this is to add a capture list.
dispatch_after(popTime, dispatch_get_main_queue()){
[let stepcopy = step] () -> Void in
println(stepcopy)
let fraction = stepcopy / incrementSteps
let incrementedValue = startValue + (endValue - startValue) * fraction
println(incrementedValue)
}
So a closure starts with {, followed optionally by the capture list in [ brackets], followed optionally by (arguments) -> result in, followed by the code.
BTW by using Float instead of Double you reduce the precision to about 7 digits instead of 15, for no good reason whatsoever.

Setting Maximum Data Points for Range Selector and Interval

I've got a chart that has a large number of data points. I'm setting the extremes right now so it only shows a smaller number - about 100 or so at a time. The issue I have is I don't want to disable the range selector or the manual input for dates, but currently the user can expand the range selector to include the entire data set. Is there any way to limit this so they can only grab, at most, X number of points?
I don't want to use data grouping either, I have different data for different data groups, so it's important the grouping does not change. Thanks in advance for any pointers on this one!
Unfortunately you can't disable range selector for such purpose, but you can overwrite extremes after user change them, see:
api.highcharts.com/highstock#xAxis.events.afterSetExtremes So for example, if user takes range for 4 days and you want max for 2 days - grab one of min or max, and add/remove two days in extremes (call chart.xAxis.setExtremes() with new extremes). Of course, it will call another afterSetExtremes, so it would be infinite loop, however now extremes will be proper (two days), so it wouldn't call another setExtremes().
Here's a working example of using afterSetExtremes (like Dexter describes) to create a maximum range from the range selector :
http://jsfiddle.net/B7vCR/3/
xAxis: {
minRange:6 * 30 * 24 * 3600 * 1000,
events: {
afterSetExtremes: function(e) {
var maxDistance = 10 * 30 * 24 * 3600 * 1000; //8 months time
var xaxis = this;
if ((e.max - e.min) > maxDistance) {
var min = e.max - maxDistance;
var max = e.max;
window.setTimeout(function() {
xaxis.setExtremes(min, max);
}, 1);
}
}
}
}
From this post
http://forum.highcharts.com/viewtopic.php?f=12&t=21741

Resources