How to make a counter for Ignition Designer using Python - counter

I'm trying to do a counter that would count the amout of times when a tag (measuring conditions) is either 0 or 32767. The counter should count +1 in either case.
I'm trying something like this (but I know it's a mess):
def count(self):
while x == 0 or X == 32676
print count += 1
or somethin like this:
def isEqual(num):
x == 0 or x == 32676
print counter += 1
elif: print counter

You could make a memory tag to store your counter. Then make a gateway tag change script to check for your two values each time the tag changes. Increment your counter each time the tag is equal to either of those two values. Like this:
if (newValue.value in [0, 32676]) and (not initialChange):
system.tag.write('counter', system.tag.read('counter').getValue() + 1)

set label bound to the tag you are tracking,
create memory tag for counter
add value change script that will run every time the value of the tag you are tracking changes
Script should look like:
counter = system.tag.readBlocking(["[default]My/Tag/counter"])
counter = counter + 1
system.tag.writeBlocking(["[default]My/Tag/counter"],["counter"])

Related

Libreoffice calc - how to write a same value into a range

I know how to 'select' a range in LO (7.2.4.1) Calc BASIC ....
ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("D1:H6")
But how to write a value, e.g. "1", into that range using BASIC?
myRange = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("D1:H6")
myRange.Value = 1
Gives an "property or method not found" error. But I can't find any properties or values to go after Range to allow me to do what I want. Flailing around and trying
myRange.setValue = 1
myRange.writeValue = 1
myRange.setString = "1"
and numerous other variants don't work either.
Would really appreciate the solution. Thanks.
You can edit the value of an individual cell, but not the entire range. You will have to iterate over all the cells in the range one at a time, changing the value of each of them.
Sub Set1ToD1H6
myRange = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("D1:H6")
For i = 0 To myRange.getRows().getCount()-1
For j = 0 To myRange.getColumns().getCount()-1
myRange.getCellByPosition(j, i).setValue(1)
Next j
Next i
End Sub
But since the read-write operation to a cell is comparable in time to the read-write operation to a whole range, it is preferable to use another method - to prepare data in an array and write from it to a range in one operation:
Sub Set1ToRange
myRange = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName("D1:H6")
dataOfRange = myRange.getData()
For i = LBound(dataOfRange) To UBound(dataOfRange)
For j = LBound(dataOfRange(i)) To UBound(dataOfRange(i))
dataOfRange(i)(j) = 1
Next j
Next i
myRange.setData(dataOfRange)
End Sub
(For your example, this will be approximately 30 times faster, for a larger range the time winnings will be even more significant)
The .getData() and .setData() methods work on numeric range values. To work with text strings (and numbers), use .getDataArray() and .setDataArray(), for working with cell formulas use .getFormulaArray() and .setFormulaArray()

Allow only a fixed number of agents to pass through a queue block periodically in Anylogic

I am using a Queue and hold block together, where the hold remains blocked until all the agents arrive at the Queue block.
How to change it and want to allow only a fixed number of agents (say 5 agents) at fixed intervals of time(say every 3 minutes)? Current properties of my Queue and hold block:
queue_block_properties
hold_block_properties
Create a cyclic event with recurrence time 3 minutes.
Also create a variable which you can name count of type int.
In the event action field write:
count = 0;
hold.unblock();
Then, in the On enter field of the hold block write the following:
count++;
if( count == 5 ) {
self.block();
}
The only question that I have is whether you want every 3 minutes to have exactly 5 agents leave or whether it's okay if they arrive a bit later. In other words if after 3 minutes, there are only 3 agents in the queue, do they leave and the hold remains unblocked in case another 2 arrive before the next cycle? Or does the hold block blocks again immediately?
In the solution I provided, if there are less than 5 at the cycle time occurrence, and then new agents arrive before the next cycle, they can pass.
Otherwise, create a new variable called target for example and write the following in the event action:
count= 0;
if( queue.size() >= 5 ) {
target = 5;
hold.unblock();
}
else if ( queue.size() > 0 ) {
target = queue.size();
hold.unblock();
}
And in the on enter of the hold, write:
count++;
if( count == target ) {
self.block();
target = 0;
}
I would advise to not use a hold block for such delicate control of releasing agents. Instead, I would propose a simpler solution.
Simply let the agents build up in the queue and then you remove them using an event. The only action for this event is to remove the minimum between your set number of agents and the queue size, from the queue and send them to an enter block. The enter block is where your process flow then continues. See the screenshot below.
Code in the event is
for (int i = 0; i < min(5, queue.size()); i ++){
enter.take(queue.remove(0));
}
On that note, you can also use the Wait block (Which is hidden in the Auxillary section in the PML library
Then you can ditch the enter block and simply call the following code
for (int i = 0; i < min(5, wait.size()); i ++){
wait.free(wait.get(0));
}

How to contunally add to a number in SparkAR ( += equivalent)

New to reactive programming and pretty lost.
I have a number (which can be positive or negative) coming into a script from a patch in SparkAR and I'd like to add the number to itself once every frame.
ie if the incoming number is 1 and it comes in 9 times the variable would be 9.
let intoScript = Patches.getScalarValue('intoScript').pinLastValue;
let myValue = Reactive.add(myValue, intoScript);
The above doesnt work.
One way-
Increment counter in Patch editor and send variable value to SparkAR.
(https://sparkar.facebook.com/ar-studio/learn/documentation/docs/visual-programming/javascript-to-patch-bridging/)
let originalValue = Reactive.val(0)
function increment(newValue){
Diagnostics.watch('originalValue', originalValue)
originalValue = newValue.add(originalValue)
}
Don't forget to import Reactive module. more info about logical operations here

Using counter to count one index in a string for Python

Now, I imported Counter and I saw that it counts all the letters in the string but I would want it to only count one letter and ignore the others.. Is that possible?
run = 'Mississippi'
count = 0
for letter_s in run:
if letter_s == 's':
count = count + 1
print count
What you're doing should be totally possible. You can iterate over most things in python and the way you're doing it should work. I reformatted yours a bit and it works just fine.
run = 'Mississippi'
count = 0
for letter_s in run:
if letter_s == 's':
count += 1
print count
output is 4

In KRL can I have a persistent variable count down instead of up?

I want to have an app variable count down instead of up. I put the following in the postlude of one rule:
fired {
app:pies -= 1 from 10;
}
The variable app:pies would count from 10 down to 1 but it never reached zero. I need to stop giving out pies when I run out. Why doesn't the variable ever reach zero? Is there a better way to do this?
It seems that decrementing an app variable won't ever cause it to go below 1. I have no idea why that is. You can make an app variables be less than 1. This code, for example, starts the variable at -2 and increments it from there, which works fine:
app:test += 1 from -2;
Decrementing just doesn't seem to work like that...
I would suggest just adjusting the count by 1, such that you pretend that 1 means 0. Your app might look like this in that case:
rule morePies {
select when web pageview ".*"
if (app:pies > 1) then {
notify("You get a pie", "Yay!");
}
fired {
app:pies -= 1 from 11;
}
}
rules piesAreGone {
select when web pageview ".*"
if (app:pies <= 1) then {
notify("No pies left", "Sorry.");
}
}