diff --git a/docs/org/camunda/latera/bss/internal/Version.html b/docs/org/camunda/latera/bss/internal/Version.html new file mode 100644 index 00000000..7131b1c9 --- /dev/null +++ b/docs/org/camunda/latera/bss/internal/Version.html @@ -0,0 +1,451 @@ + + + + + + + + + + Version (org.camunda.latera:bss:1.3) + + + + + + + + + +
+ + + + + +
+ + + + + +
+ +
Package: org.camunda.latera.bss.internal
+ +

[Groovy] Class Version

+
+
+ +
+ +
+ +
+ +
+ +
+ +
+ + + +
+ + + + + +
+ + +
+ + + diff --git a/docs/test-reports/index.html b/docs/test-reports/index.html index 9b50cc67..2a78d588 100644 --- a/docs/test-reports/index.html +++ b/docs/test-reports/index.html @@ -95,8 +95,8 @@

Specifications summary:

-6 -6 +7 +7 0 0 0 @@ -118,6 +118,16 @@

Specifications:

+org.camunda.latera.bss.internal.VersionSpec + +6 +0 +0 +0 +100,0% + + + org.camunda.latera.bss.utils.CSVSpec 98 @@ -160,7 +170,7 @@

Specifications:

org.camunda.latera.bss.utils.NumericSpec -10 +12 0 0 0 diff --git a/docs/test-reports/org.camunda.latera.bss.internal.VersionSpec.html b/docs/test-reports/org.camunda.latera.bss.internal.VersionSpec.html new file mode 100644 index 00000000..95034da7 --- /dev/null +++ b/docs/test-reports/org.camunda.latera.bss.internal.VersionSpec.html @@ -0,0 +1,1704 @@ + + + + + + +

Report for org.camunda.latera.bss.internal.VersionSpec

+
+ +
+

Summary:

+ + + + + + + + + + + + + + + + + +
Executed featuresFailuresErrorsSkippedSuccess rate
6000100,0%
+
+

Features:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+Default constructor + +Return + +
+
+
Expect:
+
+
(new Version(      main,        major,        minor,      mod) as String) == result
+(new Version(main: main, major: major, minor: minor, mod: mod) as String) == result
+
+
Examples:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
mainmajorminormodresult
51255.1.2.5OK
51255.1.2.5OK
51<null>55.1.0.5OK
51<null>55.1.0.5OK
5<null><null>55.0.0.5OK
5<null><null>55.0.0.5OK
512<null>5.1.2OK
512<null>5.1.2OK
5<null>2<null>5.0.2OK
5<null>2<null>5.0.2OK
51<null><null>5.1OK
51<null><null>5.1OK
5<null><null><null>5OK
5<null><null><null>5OK
5.1<null>255.1.2.5OK
5.1<null>255.1.2.5OK
5.1<null><null>55.1.0.5OK
5.1<null><null>55.1.0.5OK
5.1<null>2<null>5.1.2OK
5.1<null>2<null>5.1.2OK
5.1<null><null><null>5.1OK
5.1<null><null><null>5.1OK
<null>5.1255.1.2.5OK
<null>5.1255.1.2.5OK
<null>5.1<null>55.1.0.5OK
<null>5.1<null>55.1.0.5OK
<null>5.12<null>5.1.2OK
<null>5.12<null>5.1.2OK
<null>5.1<null><null>5.1OK
<null>5.1<null><null>5.1OK
+
+
+
30/30 passed
+
+
+Constructor for String input + +Return + +
+
+
Expect:
+
+
(new Version(input) as String) == result
+
+
Examples:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
inputresult
5.1.2.55.1.2.5OK
5.1.0.55.1.0.5OK
5.0.2.55.0.2.5OK
5.0.0.55.0.0.5OK
5.1.25.1.2OK
5.0.25.0.2OK
5.1.05.1.0OK
5.15.1OK
5.05.0OK
55OK
+
+
+
10/10 passed
+
+
+Constructor for Number input + +Return + +
+
+
Expect:
+
+
(new Version(input) as String) == result
+
+
Examples:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
inputresult
55OK
5.15.1OK
5.125.1OK
5.1255.1OK
+
+
+
4/4 passed
+
+
+#toNumber + +Return + +
+
+
Expect:
+
+
(new Version(input).toNumber()) == result
+
+
Examples:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
inputresult
5.1.2.55.1OK
5.1.0.55.1OK
5.0.2.55.0OK
5.0.0.55.0OK
5.1.25.1OK
5.0.25.0OK
5.1.05.1OK
5.15.1OK
5.05.0OK
55OK
+
+
+
10/10 passed
+
+
+#compareTo with Version or String input + +Return + +
+
+
Expect:
+
+
(new Version(first)).compareTo(new Version(second)) == result
+(new Version(first)).compareTo(second) == result
+
+
Examples:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
firstsecondresult
5.1.2.55.1.2.50OK
5.1.2.54.1.2.51OK
5.1.2.55.1.20OK
5.1.2.54.1.21OK
5.1.2.55.10OK
5.1.2.54.11OK
5.1.2.55.01OK
5.1.2.54.01OK
5.1.2.550OK
5.1.2.541OK
4.1.2.55.1.2.5-1OK
4.1.2.55.1.2-1OK
4.1.2.55.1-1OK
4.1.2.55.0-1OK
4.1.2.55-1OK
4.1.2.540OK
5.1.0.55.1.2.5-1OK
5.1.0.54.1.2.51OK
5.1.0.55.1.2-1OK
5.1.0.54.1.21OK
5.1.0.55.10OK
5.1.0.54.11OK
5.1.0.55.01OK
5.1.0.54.01OK
5.1.0.550OK
5.1.0.541OK
5.0.2.55.1.2.5-1OK
5.0.2.54.1.2.51OK
5.0.2.55.1.2-1OK
5.0.2.54.1.21OK
5.0.2.55.1-1OK
5.0.2.54.11OK
5.0.2.55.00OK
5.0.2.54.01OK
5.0.2.550OK
5.0.2.541OK
5.1.25.1.2.5-1OK
5.1.24.1.2.51OK
5.1.25.1.20OK
5.1.24.1.21OK
5.1.25.10OK
5.1.24.11OK
5.1.25.01OK
5.1.24.01OK
5.1.250OK
5.1.241OK
5.0.25.1.2.5-1OK
5.0.24.1.2.51OK
5.0.25.1.2-1OK
5.0.24.1.21OK
5.0.25.1-1OK
5.0.24.11OK
5.0.25.00OK
5.0.24.01OK
5.0.250OK
5.0.241OK
5.15.1.2.5-1OK
5.14.1.2.51OK
5.15.1.2-1OK
5.14.1.21OK
5.15.10OK
5.14.11OK
5.15.01OK
5.14.01OK
5.150OK
5.141OK
5.05.1.2.5-1OK
5.04.1.2.51OK
5.05.1.2-1OK
5.04.1.21OK
5.05.1-1OK
5.04.11OK
5.05.00OK
5.04.01OK
5.050OK
5.041OK
55.1.2.5-1OK
54.1.2.51OK
55.1.2-1OK
54.1.21OK
55.1-1OK
54.11OK
55.0-1OK
54.01OK
550OK
541OK
+
+
+
86/86 passed
+
+
+#compareTo with Number input + +Return + +
+
+
Expect:
+
+
(new Version(first)).compareTo(second) == result
+
+
Examples:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
firstsecondresult
5.1.2.55.10OK
5.1.2.54.11OK
5.1.2.55.01OK
5.1.2.54.01OK
5.1.2.550OK
5.1.2.541OK
5.1.0.55.10OK
5.1.0.54.11OK
5.1.0.55.01OK
5.1.0.54.01OK
5.1.0.550OK
5.1.0.541OK
5.0.2.55.1-1OK
5.0.2.54.11OK
5.0.2.55.00OK
5.0.2.54.01OK
5.0.2.550OK
5.0.2.541OK
5.1.25.10OK
5.1.24.11OK
5.1.25.01OK
5.1.24.01OK
5.1.250OK
5.1.241OK
5.0.25.1-1OK
5.0.24.11OK
5.0.25.00OK
5.0.24.01OK
5.0.250OK
5.0.241OK
5.15.10OK
5.14.11OK
5.15.01OK
5.14.01OK
5.150OK
5.141OK
5.05.1-1OK
5.04.11OK
5.05.00OK
5.04.01OK
5.050OK
5.041OK
55.1-1OK
54.11OK
55.0-1OK
54.01OK
550OK
541OK
+
+
+
48/48 passed
+
+
+ + + \ No newline at end of file diff --git a/src/org/camunda/latera/bss/internal/Version.groovy b/src/org/camunda/latera/bss/internal/Version.groovy new file mode 100644 index 00000000..23b3db0b --- /dev/null +++ b/src/org/camunda/latera/bss/internal/Version.groovy @@ -0,0 +1,206 @@ +package org.camunda.latera.bss.internal + +import groovy.transform.EqualsAndHashCode +import static org.camunda.latera.bss.utils.StringUtil.trim +import static org.camunda.latera.bss.utils.StringUtil.isString +import static org.camunda.latera.bss.utils.Numeric.isInteger +import static org.camunda.latera.bss.utils.Numeric.isIntegerStrict +import static org.camunda.latera.bss.utils.Numeric.isFloat +import static org.camunda.latera.bss.utils.Numeric.isNumber +import static org.camunda.latera.bss.utils.Numeric.round +import static org.camunda.latera.bss.utils.Numeric.toIntSafe +import static org.camunda.latera.bss.utils.Numeric.toFloatSafe + +@EqualsAndHashCode +class Version implements Comparable { + /** + First item of Hydra version (e.g. 5 for 5.1.2.4) + */ + Integer main + + /** + Second item of Hydra version (e.g. 1 for 5.1.2.4) + */ + Integer major + + /** + Third item of Hydra version (e.g. 2 for 5.1.2.4) + */ + Integer minor + + /** + Forth item of Hydra version (e.g. 4 for 5.1.2.4) + */ + Integer mod + private Integer scale + + + /** + Constructor with separated version items. +

+ Examples: + + @param main @see #main + @param major @see #major + @param minor @see #minor + @param mod @see #mod + */ + Version(def main, def major, def minor = null, def mod = null) { + if (main != null) { + this.main = toIntSafe(main) + if (isIntegerStrict(main)) { // 5 + this.major = toIntSafe(major) + } else if (isFloat(main)) { // 5.0, 5.1 + this.major = toIntSafe((round(toFloatSafe(main), 1) - this.main)*10) // 0, 1 + //DON'T USE MORE THAN 1 DIGIT AFTER DECIMAL POINT + } + } else if (major != null) { + this.main = toIntSafe(major) + if (isIntegerStrict(major)) { // 5 + this.major = 0 + } else if (isFloat(major)) { // 5.0, 5.1 + this.major = toIntSafe((round(toFloatSafe(major), 1) - this.main)*10) // 0, 1 + //DON'T USE MORE THAN 1 DIGIT AFTER DECIMAL POINT + } + } + this.minor = toIntSafe(minor) + this.mod = toIntSafe(mod) + setScale() + } + + /** + Constructor overload with named arguments. +

+ Examples: + + @param input Map with named arguments. + @see Version(def) + */ + Version(Map input) { + this(input.main, input.major, input.minor, input.mod) + } + + /** + Constructor overload for Number input. +

+ Examples: + + @param input Number with version data. + @see Version(def) + */ + Version(Number input) { + this(main: input) + } + + /** + Constructor overload for String input. +

+ Examples: + + @param input String or GStringImpl with version data. + @see Version(def) + */ + Version(CharSequence input) { + List parts = trim(input).tokenize('.') + if (parts.size() > 0) { + this.main = toIntSafe(parts[0]) + if (parts.size() > 1) { + this.major = toIntSafe(parts[1]) + if (parts.size() > 2) { + this.minor = toIntSafe(parts[2]) + if (parts.size() > 3) { + this.mod = toIntSafe(parts[3]) + } + } + } + } + setScale() + } + + private setScale() { + scale = 0 + if (mod != null) { + scale = 4 + } else { + if (minor != null) { + scale = 3 + } else { + if (major != null) { + scale = 2 + } else { + if (main != null) { + scale = 1 + } + } + } + } + if (scale == 0) { + throw new Exception('Version should have at least one number') + } + } + + private Integer toInteger() { + return toIntSafe(main*1000000000 + (major ?: 0)*1000000 + (minor ?: 0)*1000 + (mod ?: 0)) + } + + private Integer toIntegerRound(Version v) { + return toIntSafe(this.main*1000000000 + (this.major != null && v.major != null ? this.major : 0)*1000000 + (this.major != null && v.major != null && this.minor != null && v.minor != null ? this.minor : 0)*1000 + (this.major != null && v.major != null && this.minor != null && v.minor != null && this.mod != null && v.mod != null ? this.mod : 0)) + } + + /** + Get version as string. +

+ Examples: + + @returns String with version. + */ + String toString() { + String result = "${main}" + if (scale > 1) { + result += ".${major ?: 0}" + if (scale > 2) { + result += ".${minor ?: 0}" + if (scale > 3) { + result += ".${mod}" + } + } + } + return result + } + + /** + Get version as integer of decimal number (only main.major, without other parts). +

+ Examples: + + @returns BigInteger or BigDecimal with version. + */ + Number toNumber() { + if (major == null) { + return main + } + return toFloatSafe("${this.main}.${this.major}") + } + + /** + Compare two versions. +

+ Examples: + + @param input Version, Number or String with version to compare. + @returns 0 if source satisfies target (5.1.2 == 5.1), -1 if source less than target (5.0.0 < 5.1) or 1 if source more than target (5.1.2 > 5.0) + */ + int compareTo(def v) { + if (isString(v) || isNumber(v)) { + v = new Version(v) + } + Integer v1 = toIntegerRound(v) + Integer v2 = v.toInteger() + int result = v1.compareTo(v2) + + if (result == 0 && scale < v.scale) { // 5.0 == 5 but 5 < 5.0 because 5.0 is more precise + return -1 + } + return result + } +} \ No newline at end of file diff --git a/test/org/camunda/latera/bss/internal/VersionSpec.groovy b/test/org/camunda/latera/bss/internal/VersionSpec.groovy new file mode 100644 index 00000000..82656ee7 --- /dev/null +++ b/test/org/camunda/latera/bss/internal/VersionSpec.groovy @@ -0,0 +1,243 @@ +package org.camunda.latera.bss.internal + +import spock.lang.* +import org.camunda.latera.bss.internal.Version + +class VersionSpec extends Specification { + def "Default constructor"() { + expect: + (new Version( main, major, minor, mod) as String) == result + (new Version(main: main, major: major, minor: minor, mod: mod) as String) == result + + where: + main |major |minor|mod |result + 5 |1 |2 |5 |'5.1.2.5' + '5' |'1' |'2' |'5' |'5.1.2.5' + 5 |1 |null |5 |'5.1.0.5' + '5' |'1' |null |'5' |'5.1.0.5' + 5 |null |null |5 |'5.0.0.5' + '5' |null |null |'5' |'5.0.0.5' + 5 |1 |2 |null |'5.1.2' + '5' |'1' |'2' |null |'5.1.2' + 5 |null |2 |null |'5.0.2' + '5' |null |'2' |null |'5.0.2' + 5 |1 |null |null |'5.1' + '5' |'1' |null |null |'5.1' + 5 |null |null |null |'5' + '5' |null |null |null |'5' + 5.1 |null |2 |5 |'5.1.2.5' + '5.1'|null |'2' |'5' |'5.1.2.5' + 5.1 |null |null |5 |'5.1.0.5' + '5.1'|null |null |'5' |'5.1.0.5' + 5.1 |null |2 |null |'5.1.2' + '5.1'|null |'2' |null |'5.1.2' + 5.1 |null |null |null |'5.1' + '5.1'|null |null |null |'5.1' + null |5.1 |2 |5 |'5.1.2.5' + null |'5.1' |'2' |'5' |'5.1.2.5' + null |5.1 |null |5 |'5.1.0.5' + null |'5.1' |null |'5' |'5.1.0.5' + null |5.1 |2 |null |'5.1.2' + null |'5.1' |'2' |null |'5.1.2' + null |5.1 |null |null |'5.1' + null |'5.1' |null |null |'5.1' + } + + def "Constructor for String input"() { + expect: + (new Version(input) as String) == result + + where: + input|result + '5.1.2.5'|'5.1.2.5' + '5.1.0.5'|'5.1.0.5' + '5.0.2.5'|'5.0.2.5' + '5.0.0.5'|'5.0.0.5' + '5.1.2' |'5.1.2' + '5.0.2' |'5.0.2' + '5.1.0' |'5.1.0' + '5.1' |'5.1' + '5.0' |'5.0' + '5' |'5' + } + + def "Constructor for Number input"() { + expect: + (new Version(input) as String) == result + + where: + input|result + 5 |'5' + 5.1 |'5.1' + 5.12 |'5.1' //more than 1 digits after decimal point are being dropped + 5.125|'5.1' //more than 1 digits after decimal point are being dropped + } + + def "#toNumber"() { + expect: + (new Version(input).toNumber()) == result + + where: + input|result + '5.1.2.5'|5.1 + '5.1.0.5'|5.1 + '5.0.2.5'|5.0 + '5.0.0.5'|5.0 + '5.1.2' |5.1 + '5.0.2' |5.0 + '5.1.0' |5.1 + '5.1' |5.1 + '5.0' |5.0 + '5' |5 + } + + def "#compareTo with Version or String input"() { + expect: + (new Version(first)).compareTo(new Version(second)) == result + (new Version(first)).compareTo(second) == result + + where: + first |second |result + '5.1.2.5'|'5.1.2.5'| 0 + '5.1.2.5'|'4.1.2.5'| 1 + '5.1.2.5'|'5.1.2' | 0 + '5.1.2.5'|'4.1.2' | 1 + '5.1.2.5'|'5.1' | 0 + '5.1.2.5'|'4.1' | 1 + '5.1.2.5'|'5.0' | 1 + '5.1.2.5'|'4.0' | 1 + '5.1.2.5'|'5' | 0 + '5.1.2.5'|'4' | 1 + '4.1.2.5'|'5.1.2.5'|-1 + '4.1.2.5'|'5.1.2' |-1 + '4.1.2.5'|'5.1' |-1 + '4.1.2.5'|'5.0' |-1 + '4.1.2.5'|'5' |-1 + '4.1.2.5'|'4' | 0 + '5.1.0.5'|'5.1.2.5'|-1 + '5.1.0.5'|'4.1.2.5'| 1 + '5.1.0.5'|'5.1.2' |-1 + '5.1.0.5'|'4.1.2' | 1 + '5.1.0.5'|'5.1' | 0 + '5.1.0.5'|'4.1' | 1 + '5.1.0.5'|'5.0' | 1 + '5.1.0.5'|'4.0' | 1 + '5.1.0.5'|'5' | 0 + '5.1.0.5'|'4' | 1 + '5.0.2.5'|'5.1.2.5'|-1 + '5.0.2.5'|'4.1.2.5'| 1 + '5.0.2.5'|'5.1.2' |-1 + '5.0.2.5'|'4.1.2' | 1 + '5.0.2.5'|'5.1' |-1 + '5.0.2.5'|'4.1' | 1 + '5.0.2.5'|'5.0' | 0 + '5.0.2.5'|'4.0' | 1 + '5.0.2.5'|'5' | 0 + '5.0.2.5'|'4' | 1 + '5.1.2' |'5.1.2.5'|-1 + '5.1.2' |'4.1.2.5'| 1 + '5.1.2' |'5.1.2' | 0 + '5.1.2' |'4.1.2' | 1 + '5.1.2' |'5.1' | 0 + '5.1.2' |'4.1' | 1 + '5.1.2' |'5.0' | 1 + '5.1.2' |'4.0' | 1 + '5.1.2' |'5' | 0 + '5.1.2' |'4' | 1 + '5.0.2' |'5.1.2.5'|-1 + '5.0.2' |'4.1.2.5'| 1 + '5.0.2' |'5.1.2' |-1 + '5.0.2' |'4.1.2' | 1 + '5.0.2' |'5.1' |-1 + '5.0.2' |'4.1' | 1 + '5.0.2' |'5.0' | 0 + '5.0.2' |'4.0' | 1 + '5.0.2' |'5' | 0 + '5.0.2' |'4' | 1 + '5.1' |'5.1.2.5'|-1 + '5.1' |'4.1.2.5'| 1 + '5.1' |'5.1.2' |-1 + '5.1' |'4.1.2' | 1 + '5.1' |'5.1' | 0 + '5.1' |'4.1' | 1 + '5.1' |'5.0' | 1 + '5.1' |'4.0' | 1 + '5.1' |'5' | 0 + '5.1' |'4' | 1 + '5.0' |'5.1.2.5'|-1 + '5.0' |'4.1.2.5'| 1 + '5.0' |'5.1.2' |-1 + '5.0' |'4.1.2' | 1 + '5.0' |'5.1' |-1 + '5.0' |'4.1' | 1 + '5.0' |'5.0' | 0 + '5.0' |'4.0' | 1 + '5.0' |'5' | 0 + '5.0' |'4' | 1 + '5' |'5.1.2.5'|-1 + '5' |'4.1.2.5'| 1 + '5' |'5.1.2' |-1 + '5' |'4.1.2' | 1 + '5' |'5.1' |-1 + '5' |'4.1' | 1 + '5' |'5.0' |-1 + '5' |'4.0' | 1 + '5' |'5' | 0 + '5' |'4' | 1 + } + def "#compareTo with Number input"() { + expect: + (new Version(first)).compareTo(second) == result + + where: + first |second |result + '5.1.2.5'|5.1 | 0 + '5.1.2.5'|4.1 | 1 + '5.1.2.5'|5.0 | 1 + '5.1.2.5'|4.0 | 1 + '5.1.2.5'|5 | 0 + '5.1.2.5'|4 | 1 + '5.1.0.5'|5.1 | 0 + '5.1.0.5'|4.1 | 1 + '5.1.0.5'|5.0 | 1 + '5.1.0.5'|4.0 | 1 + '5.1.0.5'|5 | 0 + '5.1.0.5'|4 | 1 + '5.0.2.5'|5.1 |-1 + '5.0.2.5'|4.1 | 1 + '5.0.2.5'|5.0 | 0 + '5.0.2.5'|4.0 | 1 + '5.0.2.5'|5 | 0 + '5.0.2.5'|4 | 1 + '5.1.2' |5.1 | 0 + '5.1.2' |4.1 | 1 + '5.1.2' |5.0 | 1 + '5.1.2' |4.0 | 1 + '5.1.2' |5 | 0 + '5.1.2' |4 | 1 + '5.0.2' |5.1 |-1 + '5.0.2' |4.1 | 1 + '5.0.2' |5.0 | 0 + '5.0.2' |4.0 | 1 + '5.0.2' |5 | 0 + '5.0.2' |4 | 1 + '5.1' |5.1 | 0 + '5.1' |4.1 | 1 + '5.1' |5.0 | 1 + '5.1' |4.0 | 1 + '5.1' |5 | 0 + '5.1' |4 | 1 + '5.0' |5.1 |-1 + '5.0' |4.1 | 1 + '5.0' |5.0 | 0 + '5.0' |4.0 | 1 + '5.0' |5 | 0 + '5.0' |4 | 1 + '5' |5.1 |-1 + '5' |4.1 | 1 + '5' |5.0 |-1 + '5' |4.0 | 1 + '5' |5 | 0 + '5' |4 | 1 + } +} \ No newline at end of file