I need a way to call an Ant target if a given version (with dots) is greater than another version. I found greaterThan in ant-contrib, but I think that it only uses a straight string comparison unless the strings are completely numeric. For instance, I need something like "8.2.10" greaterThan "8.2.2" to evaluate to true. Is there anything in ant-contrib I can use, or has anyone ever written a custom script to do this?
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="test" name="test">
<target name="script-definition">
<scriptdef name="greater" language="javascript">
<attribute name="v1"/>
<attribute name="v2"/>
<![CDATA[
self.log("value1 = " + attributes.get("v1"));
self.log("value2 = " + attributes.get("v2"));
var i, l, d, s = false;
a = attributes.get("v1").split('.');
b = attributes.get("v2").split('.');
l = Math.min(a.length, b.length);
for (i=0; i<l; i++) {
d = parseInt(a[i], 10) - parseInt(b[i], 10);
if (d !== 0) {
project.setProperty("compare-result", (d > 0 ? 1 : -1));
s = true;
break;
}
}
if(!s){
d = a.length - b.length;
project.setProperty("compare-result", (d == 0 ? 0 : (d > 0 ? 1 : -1)));
}
]]>
</scriptdef>
</target>
<target name="test" depends="script-definition">
<greater v1="8.2.2.1" v2="8.2.2.1.1.101" />
<echo message="compare-result: ${compare-result}" />
</target>
</project>
p.s: javascript cheated from here from Lejared's answer.
Pretty old post but there is the solution using the scriptlet task :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="test" name="test">
<scriptdef name="versioncompare" language="javascript">
<attribute name="arg1"/>
<attribute name="arg2"/>
<attribute name="returnproperty"/>
<![CDATA[
importClass(java.lang.Double);
var num1 = Double.parseDouble(attributes.get("arg1"));
var num2 = Double.parseDouble(attributes.get("arg2"));
project.setProperty(attributes.get("returnproperty"), (num1 > num2 ? 1 : (num1 < num2 ? -1 : 0)));
]]>
</scriptdef>
<target name="test">
<versioncompare arg1="2.0" arg2="1.9" returnproperty="compareresult"/>
<echo message="compareresult: ${compareresult}"/>
</target>
</project>
Related
Let's have for example the following travel routes in Neo4j:
Tom: New York --> Moskow --> Berlin --> Paris --> Mumbay --> Kairo --> Rio --> Amsterdam --> Nashville
Mary: Madrid --> New York --> Moskow --> Berlin --> Mumbay --> Kairo --> New York --> Nashville --> Toronto
Bob: New York --> Nashville --> Amsterdam --> Rio --> Kairo --> Mumbay --> Paris --> Berlin --> Moscow
Now I need to get the travel route that is most similar to Tom's route. Similarity means, the number of common cities that are visited in the same sequence, while skipping cities in between is allowed.
Expected result:
Common route of Tom and Mary: New York -> Moskow -> Berlin -> Mumbay -> Kairo -> Nashville => Similarity = 6
Common route of Tom and Bob: New York -> Nashville (also New York -> Amsterdam and other paths) => Similarity = 2
Note: Even Tom and Bob have 9 common cities, but they are not in the same sequence, this is not counting for similarity!
Is it possible with Neo4j to get this kind of similarity?
I would be able to read all the paths and then compare them outside of Neo4j. But better would be to do this with Neo4j, because it will be more elegant and probably faster.
Added:
My current algorithm is a similarity matrix, where I have one path on the x-axis and another on the y-axis. Every match between x and y causes an increment of all values that are on right side and below the match. I other words, every value in the matrix represents the count of the common path before the cell.
Condition to increment a value is that the value is not already greater. This may happen if there are several common paths, in this case the longest path must win.
Two examples of matrix of above examples:
Full Java code:
public static int getLongestCommonWordsInSequence(List<String> yList, List<String> xList) {
// right = X, left = Y
// Need dimension +1, because matches-count is incremented not on match point, but on next indexes
int[][] matrix = new int[xList.size() + 1][yList.size() + 1];
// Iterate y
for (int y = 0; y < yList.size(); y++) {
// Iterate x
for (int x = 0; x < xList.size(); x++) {
// Check if y = x
if (yList.get(y).equals(xList.get(x))) {
// Increment the count
int newCount = matrix[x][y] + 1;
// Update all counts that are on right side AND below the current match
for (int _x = x + 1; _x <= xList.size(); _x++) {
for (int _y = y + 1; _y <= yList.size(); _y++) {
// Update only if value is < newCount
if (matrix[_x][_y] < newCount) {
matrix[_x][_y] = newCount;
}
}
}
}
}
}
return matrix[matrix.length - 1][matrix[matrix.length - 1].length - 1];
}
Added
This is my Java code I would use to create the data of a single journey. This is only experimental. I will extend it or create any other structure if it is of advantage.
Node journeyNode = graphDb.createNode(Label.label("Journey"));
for (Destination destination : journey.destinations) {
Node destinationNode = graphDb.createNode(Label.label("Destination"));
destinationNode.setProperty("name", destination.name);
journey.createRelationshipTo(destinationNode, RelationshipType.withName("Destination"));
}
In Tsung, I want publish message time in milisec, I tried below but able to get time in Sec only.
<setdynvars sourcetype="eval" code='fun({Pid,DynVars})->
{{Year,Month,Day},{Hour,Minute,Second}} = erlang:localtime(),
io_lib:format('~4..0B-~2..0B-~2..0B::~2..0B:~2..0B:~4..0B\n', [Year,Month,Day,Hour,Minute,Second]) end.'>
<var name="time" />
</setdynvars>
<request subst="true">
<mqtt type="publish" topic="xxx" qos="0" retained="true">%%_time%%</mqtt>
</request>
you can use
1> Time_milli = fun() ->
Um = erlang:system_time(milli_seconds),
{D,T} = calendar:gregorian_seconds_to_datetime(Um div 1000 + 719528*86400)
{D,T,Um rem 1000}
end.
#Fun<erl_eval.20.54118792>
2> Time_milli().
{{2015,12,9},{8,13,53},40}
The value 719528*86400 is the number of seconds between the 1 1 1 at 0 0 0 and the 1970 1 1 at 0 0 0.
Note: the system_time is not monotonic, if you need this feature you can use erlang:monotonic_time/1, but in this case you cannot convert to a date or compare between different nodes.
I have a simple web based drawing tool where I use SVG to store the drawing in a data base.
Typical sag looks like this :
<?xml version='1.0'?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg version='1.1' xmlns='http://www.w3.org/2000/svg'>
<path fill='none' stroke='#FF0000' stroke-width='4' d='M85, 140 L85, 140, 86, 140, 88, 140'/>
<path fill='none' stroke='#FF0000' stroke-width='4' d='M299, 130 L299, 130, 301, 129, 304, 128'/>
</svg>
I manipulate the XML using jQuery via:
svgDoc = jQuery.parseXML(svgData);
There is problem with IE in that it strips the commas from my attributes.
In IE the d attribute comes out as " M85 140 L85 140 86 140 88 140 "
All other browsers have "M85, 140 L85, 140, 86, 140, 88, 140"
Put simply is there a way of changing IE'd behaviour or do I have to program around it?
The SVG spec allows this:
Superfluous white space and separators such as commas can be eliminated (e.g., "M 100 100 L 200 200" contains unnecessary spaces and could be expressed more compactly as "M100 100L200 200").
References
SVG:8.3.1 General information about path data
I am posting this as an answer in case it is overlooked in the comments:
To parse the contents of the d attribute of an svg path element in a cross-browser compatible manner, use the pathSegList property.
(jsFiddle example)
SVG:
<path id="myPath" d="M 0 0 L 100 100 />
JavaScript:
var path = document.getElementById("myPath")
var pathSegs = path.pathSegList;
// it's important to use '.getItem()'; IE doesn't support accessing with item index
var start = pathSegs.getItem(0);
var typeLetter = start.pathSegTypeAsLetter; // 'M'
var x = start.x; // 0
var y = start.y; // 0
This will work if the d attribute has commas and also when it doesn't.
I found that sometimes I must give types explicitly for pattern variables, otherwise Rascal would not work as expected. The following session in the Console says it all:
rascal>data foo = bar(int);
ok
rascal>int x = 1;
int: 1
rascal>[x | bar(x) <- [bar(2), bar(3)]];
list[void]: []
rascal>[x | bar(int x) <- [bar(2), bar(3)]];
list[int]: [2,3]
Why did this happen?
In the current version of Rascal it is such that variables in patterns that exist in the surrounding scope are not matched and shadowed, but rather checked for equality.
So:
<int x, x> := <2,2> => true // x is first introduced and then checked for equality
<int x, x> := <2,3> => false // x is first introduced and then checked for equality
{ int x = 1; if (x := 2) println("true"); else println("false"); // false!
And this holds for all places where we use pattern matching.
We have had several complaints about this particular design of "non-linear matching", and we intend to add an operator soon ($) to identify the intention of taking something from the surround scope. If the operator is not used, then shadowing will occur:
<int x, $x> := <2,2> => true // x is first introduced and then checked for equality
<int x, $x> := <2,3> => false // x is first introduced and then checked for equality
<int x, x> := <2,3> // static error due to illegal shadowing
<int x, y> := <2,3> => true // x and y are both introduced
{ int x = 1; if ($x := 2) println("true"); else println("false"); // false!
{ int x = 1; if (x := 2) println("true <x>"); else println("false"); // true, prints 2! or perhaps a static error.
Might also add some additional power to get expressions into patterns as in:
<1, ${1 + 2 + 3}> := <1,6> // true
I have a dir with files. I need delete only some of them with condition.
For example... my folder contains:
super-lib-1.0.jar
super-lib-2.0.jar
super-lib-2.1.jar
cool-lib-3.3.1.jar
cool-lib-3.3.2.jar
I need delete only old versions of same lib. In this example I need delete files: super-lib-1.0.jar, super-lib-2.0.jar, cool-lib-3.3.1.jar
you can do it with javascript in ant like this way:
<?xml version="1.0" encoding="UTF-8"?>
<project default="init" name="My Project">
<scriptdef name="removeAllButLatest" language="javascript">
<attribute name="dir"/>
<![CDATA[
dir = new java.io.File(attributes.get("dir"));
files = dir.listFiles();
java.util.Arrays.sort(files, new java.util.Comparator({
compare: function(f1,f2) {
n1 = f1.getName();
n2 = f2.getName();
v1 = Number(n1.substring(n1.lastIndexOf('-')+1,n1.lastIndexOf('.')).replace(/\./g, ""));
v2 = Number(n2.substring(n2.lastIndexOf('-')+1,n2.lastIndexOf('.')).replace(/\./g, ""));
n1 = n1.substring(0, n1.lastIndexOf('-'));
n2 = n2.substring(0, n2.lastIndexOf('-'));
if (n1 < n2) {return -1;}
if (n1 > n2) {return 1;}
if (v1 < v2) {return 1;}
if (v1 > v2) {return -1;}
return 0;
}
}));
echo = project.createTask( "echo" );
name = "";
for(i = 0; i < files.length; i++) {
n = files[i].getName();
n = n.substring(0, n.lastIndexOf('-'));
if(n == name){
echo.setMessage( "deleting file: " + files[i] );
echo.perform();
files[i].delete();
}
else {
name = n;
}
}
]]>
</scriptdef>
<target name="init">
<removeAllButLatest dir="/home/guest/Desktop" />
</target>
</project>