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);
Related
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]
I try to add a non-breaking space when using CreateJS (or EaselJS). But it does not work.
For example: I don't want a linebreak between a "text" and a "!"
Example:
this.copy_01 = new cjs.Text("This is a text\u00A0!", "bold 60px 'Times New Roman'", "#FFFFFF");
\u00A0 usually works in JavaScript. But now it only adds a space, but not a non-breaking space.
Does someone know if it is possible to add a non-breaking space in CreateJS?
The line-wrapping in EaselJS is manually implemented in the Canvas, so it doesn't follow the JavaScript ruleset. You would have to manually add support for it. Sorry!
I am currently trying a workaround.
Seems to work for me, but I am not really happy with this.
function nonBreak(textObj) {
var origString = textObj.text;
var compStr = origString.replace(/(.|[\r\n])*?<nbr>.*?($|\s)/, "");
compStr = origString.replace(compStr, "");
compStr1 = compStr.replace(/<nbr>/, " ");
compStr2 = compStr.replace(/<nbr>/, "\n");
textObj.text = compStr1;
var sizeStr1 = textObj.getMetrics().height;
textObj.text = compStr2;
sizeStr2 = textObj.getMetrics().height;
textObj.text = origString;
if (sizeStr1 == sizeStr2) {
newString1 = origString.replace(/\s?[^ ]*<nbr>.*/, "");
newString2 = origString.replace(newString1 + " ", "");
newString1 = newString1 + "\n";
newString2 = newString2.replace(/<nbr>/, " ");
newString = newString1 + newString2;
textObj.text = newString;
} else {
newString = origString.replace(/<nbr>/, " ");
textObj.text = newString;
}
}
var origString = this.copy_01.text;
var textCopy = this.copy_01;
var countBR = origString.match(/<nbr>/g);
if (countBR !== null) {
for (i = 0; i < countBR.length; i++) {
if (countBR[i] == "<nbr>") {
nonBreak(textCopy);
}
}
}
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);
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);
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.