AS2 optimized code - optimization

I am trying to implement a logging mechanism in my code. I have read in some forums that in AS2, string concatenation does not happen at compile time, instead it happens at runtime.
I wanted to know which of the following codes is more optimal:
for (var i:Number = 0; i < n; i++ )
{
var strToReplace:String = "{" + i + "}";
}
or,
for (var i:Number = 0; i < n; i++ )
{
var strToReplace:String = "{%s}".split("%s").join(String(i));
}
Your help would be greatly appreciated as I am a newbie as far as AS2 is concerned. Thank you.

Here is an easy way to test :
var n:Number = 100000;
var beforeTime:Number = getTimer();
for (var i:Number = 0; i < n; i++ ) {
var strToReplace:String = "{" + i + "}";
}
var betweenTime:Number = getTimer();
trace("between : " + (betweenTime - beforeTime));
for (var i:Number = 0; i < n; i++ ) {
var strToReplace:String = "{%s}".split("%s").join(String(i));
}
var afterTime:Number = getTimer();
trace("after : " + (afterTime - betweenTime));
What I get in the traces :
between : 269
after : 866
The first way is 3 times faster : split and join methods have to search inside your string to execute.
If your string is bigger, the difference is even bigger : the first methode duration doesn't change... The second one takes even more time.
You should try.

Related

apps script: increase variable with each execution

Hi i have a list of values each value representing the output of a shift of packaging. I want to calculate the average output of 8 weeks. So each time a shift passes the average output changes. My idea is to trigger a function after each shift, which calculates the output. Now theres my problem, how do i get a varible (the one representing the row of the first value) to increase after each trigger of the function? What i tried is to declare the variable before the function and increase the variable of 1 inside the function. Buf ofc the starting value doesnt change this way.. Probably there is an easy way for this i just dont know yet (programming newbie here :)).
let i = 7;
let j = 126;
function schnitt() {
var summe = 0;
var counter = 0;
i++;
j++;
while(i <= j){
var aktuell = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(i,6,1,1).getValue();
if(aktuell != ""){
summe = summe + aktuell;
counter++;
i++;
}
else{
i++
}
}
var durchschnitt = summe / counter;
var ausgabe = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(8,7,1,1).setValue(durchschnitt);
}
I have found a work around. I just put var i and j into cells and do it like this:
function schnitt() {
var i = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(3,14,1,1).getValue();
var j = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(4,14,1,1).getValue();
var summe = 0;
var counter = 0;
while(i <= j){
var aktuell = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(i,6,1,1).getValue();
if(aktuell != ""){
summe = summe + aktuell;
counter++;
i++;
}
else{
i++
}
}
var durchschnitt = summe / counter;
var ausgabe = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(8,7,1,1).setValue(durchschnitt);
i = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(3,14,1,1).getValue();
i++;
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(3,14,1,1).setValue(i);
j = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(4,14,1,1).getValue();
j++;
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Auswertung").getRange(4,14,1,1).setValue(j);
}

Running solve multiple timese

I need to run a solve three times. Every time solve needs to have different input from different columns of a tuple. That is why I need to access the loop variable with in the OPL as a parameter and need to change that parameter with every loop. Please suggest how to do that in ODM OPL.
(I am able to do it when running a standalone model with a physical .dat file by introducing a int in dat file and changing its values with each loop, but same is not possible when running through an ODM application).
You can do this using a scripting main() function:
.dat file:
param = 0; // This value is actually never used
.mod file:
tuple T {
int round1;
int round2;
}
T t = <1, 2>;
int param = ...;
dvar float x;
minimize x;
subject to { x >= param; }
main {
thisOplModel.generate();
var def = thisOplModel.modelDefinition;
var data = thisOplModel.dataElements;
for (var i = 0; i < 2; ++i) {
if (i == 0)
data.param = thisOplModel.t.round1;
else
data.param = thisOplModel.t.round2;
var opl = new IloOplModel(def, cplex);
opl.addDataSource(data);
opl.generate();
cplex.solve();
writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
opl.end();
}
}
The scripting code modifies the data before creating a new model in each iteration. You have a more elaborate version of code like this in the cutstock_main.mod example that ships with CPLEX.
What Daniel wrote works fine. If you do not want to have the non necessary .dat file you could write
sub.mod
tuple T {
int round1;
int round2;
}
T t = <1, 2>;
int param = ...;
dvar float x;
minimize x;
subject to { x >= param; }
and then in another model that will be the main one:
tuple T {
int round1;
int round2;
}
T t = <1, 2>;
main {
thisOplModel.generate();
var src = new IloOplModelSource("sub.mod");
var def=new IloOplModelDefinition(src);
var data = new IloOplDataElements();;
for (var i = 0; i < 2; ++i) {
if (i == 0)
data.param = thisOplModel.t.round1;
else
data.param = thisOplModel.t.round2;
var opl = new IloOplModel(def, cplex);
opl.addDataSource(data);
opl.generate();
cplex.solve();
writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
opl.end();
}
}
which will give
Round 0: 1, 1
Round 1: 2, 2
and
tuple T {
int round1;
int round2;
}
T t = <1, 2>;
int solutions[0..1];
main {
thisOplModel.generate();
var src = new IloOplModelSource("sub.mod");
var def=new IloOplModelDefinition(src);
var data = new IloOplDataElements();;
for (var i = 0; i < 2; ++i) {
if (i == 0)
data.param = thisOplModel.t.round1;
else
data.param = thisOplModel.t.round2;
var opl = new IloOplModel(def, cplex);
opl.addDataSource(data);
opl.generate();
cplex.solve();
writeln("Round " + i + ": " + cplex.getObjValue() + ", " + data.param);
thisOplModel.solutions[i]=opl.x.solutionValue;
opl.end();
}
writeln(thisOplModel.solutions);
}
to address your next question about populating tables
which gives
Round 0: 1, 1
Round 1: 2, 2
[1 2]

Accessing Photoshop preferences

I'm trying to loop over the Photoshop preferences. This should be as straightforwards as
for (i = 0; i < app.preferences.length; i++)
{
alert(app.preferences[i]);
}
only the object app.preferences doesn't have a length and accessing each item such as
alert(app.preferences.beepWhenDone); //bool
works, but is tedious and is also possibly version dependent. I know most of them are read-only, but I'm quite keen to list them all.
This should do what you want:
alert(app.preferences.reflect.properties.sort().join("\r"));
Or actually, to also let you inspect the actual values, you could do something like this:
var prefsObject = app.preferences;
var prefs = app.preferences.reflect.properties.sort();
var prefString = "Photoshop Preferences\r";
for(var i = 0; i < prefs.length; i++) {
try {
prefString += prefs[i] + ": " + prefsObject[prefs[i]] + "\r";
} catch (e) {
prefString += prefs[i] + ": " + e.message + "\r";
}
}
alert(prefString);

QMSClient.SaveCALConfiguration doesn't seem to be working

Can anyone help me understand why this below would not remove named cals. It seems to work fine until the very last line where it does the save. I don't get any exceptions or error messages.
When i look in QV Management console under System>Licenses i still see the ones that were supposed to be removed (Named user CALs)
Client Build Number: 11.20.13314.0
QMSClient Client;
string QMS = "http://localhost:4799/QMS/Service";
Client = new QMSClient("BasicHttpBinding_IQMS", QMS);
string key = Client.GetTimeLimitedServiceKey();
ServiceKeyClientMessageInspector.ServiceKey = key;
List<ServiceInfo> MyQVS = Client.GetServices(ServiceTypes.QlikViewServer);
Client.ClearQVSCache(QVSCacheObjects.All);
CALConfiguration myCALs = Client.GetCALConfiguration(MyQVS[0].ID, CALConfigurationScope.NamedCALs);
List<AssignedNamedCAL> currentNamedCALs = myCALs.NamedCALs.AssignedCALs.ToList();
List<int> indexToRemove = new List<int>();
int cnt = 1;
for (int i = 0; i < currentNamedCALs.Count; i++)
{
if ((currentNamedCALs[i].QuarantinedUntil < System.DateTime.Now)
&& (currentNamedCALs[i].LastUsed < DateTime.Now.AddDays(daysFromToday)))
{
Console.WriteLine("[" + cnt + "] " + currentNamedCALs[i].UserName +
"; Last used: " + currentNamedCALs[i].LastUsed);
indexToRemove.Add(i);
cnt++;
}
}
Console.WriteLine();
for (int i = indexToRemove.Count; i > 0; i--)
{
if (currentNamedCALs[indexToRemove[i - 1]] != null)
{
currentNamedCALs.RemoveAt(indexToRemove[i - 1]);
}
}
Console.WriteLine("\nDone");
myCALs.NamedCALs.AssignedCALs = currentNamedCALs;
Client.SaveCALConfiguration(myCALs);

Quick help turning sum into mean

I was helped earlier in creating this code that would create a histogram of a randomint. Everything looks good except I accidently had the output as a sum instead of a mean of all the numbers that were randomly chosen.I dont want to mess anything up so I was just going to ask, How can I convert this sum into a mean output instead?
import java.util.Random;
class Assignment4
{
public static void main(String[] args)
{
Random r = new Random();
int sum = 0;
int[] bins = new int[10];
for(int i = 0; i < 100; i++)
{
int randomint = 1 + r.nextInt(10);
sum += randomint;
bins[randomint-1]++;
//System.out.print(randomint + ", ");
}
System.out.println("Sum = " + sum);
System.out.println("Data shown below: ");
for (int i = 0; i < bins.length; i++)
{
int binvalue = bins[i];
System.out.print((i+1) + ": ");
for(int j = 0; j < binvalue; j++)
{
System.out.print('*');
}
System.out.println(" (" + binvalue + ")");
}
}
}
Never mind figured it out.... just turned System.out.println("Sum = " + sum); into System.out.println("Mean = " + sum/100);