Index: geniuswebcore/test/geniusweb/bidspace/BidsWithUtilityTest.py
===================================================================
--- geniuswebcore/test/geniusweb/bidspace/BidsWithUtilityTest.py	(revision 81)
+++ geniuswebcore/test/geniusweb/bidspace/BidsWithUtilityTest.py	(revision 81)
@@ -0,0 +1,97 @@
+import unittest
+from pyson.ObjectMapper import ObjectMapper
+from geniusweb.bidspace.Interval import Interval
+from decimal import Decimal
+from geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace import LinearAdditiveUtilitySpace
+import json
+from geniusweb.profile.Profile import Profile
+from geniusweb.bidspace.BidsWithUtility import BidsWithUtility
+from random import randrange
+from geniusweb.bidspace.AllBidsList import AllBidsList
+import time
+from pathlib import Path
+
+class BidsWithUtilityTest(unittest.TestCase):
+	jackson = ObjectMapper()
+	utilityGoal = Interval(Decimal("0.50"), Decimal("0.51"))
+	accuracy = 5
+	
+	
+	parameters=[
+		[ "test/resources/jobs/jobs1.json", 11 ],
+		[ "test/resources/7issues/7issues1.json", 260000 ],
+		[ "test/resources/9issues/9issues1.json", 25000000 ] 
+	]
+	
+	def testAll(self):
+		''' 
+		runs all the tests. Python has no standard 'parameterized' mechanism
+		so we have to do it ourselves.
+		'''
+		for [filename, expectedsize] in self.parameters:
+			self.filename=filename
+			self.expectedSize= expectedsize
+			with self.subTest("test"+self.filename):
+				self.before()
+				self.simple()
+			with self.subTest("testMaxUtil"+self.filename):
+				self.before()
+				self.MaxUtil()
+			with self.subTest("benchmark"+self.filename):
+				self.before()
+				self.benchmark()
+
+	def before(self):
+		print("Running from file " + self.filename)
+		file = Path(self.filename).read_text("utf-8")
+		self.profile = self.jackson.parse(json.loads(file), Profile)
+
+			
+
+	def simple(self):
+		'''
+		Test if the values are within acceptable range from the goal.
+		'''
+		list = BidsWithUtility.create(self.profile, self.accuracy).getBids(self.utilityGoal);
+		#check not all but only 10000 random bids as list may be way too large
+		#to test them all. Testing 1 billion bids may take 15 minutes or so on
+		#quad core i7 @2.4GHz.....
+		#also notice that we may be checking only part of the list if
+		#the size of the list would become bigger than maxint.
+		for n in range(10000):
+			bid = list.get(randrange(list.size()))
+			self.assertTrue(self.utilityGoal.contains(
+				round(self.profile.getUtility(bid),self.accuracy-1)),
+				"bid "+str(bid)+" is not in range "+str(self.utilityGoal))
+						
+		self.assertTrue(list.size()>= self.expectedSize)
+
+	def MaxUtil(self) :
+		bidswithutil = BidsWithUtility.create(self.profile)
+		#notice, this is the *rounded* max util
+		maxutil = bidswithutil.getRange().getMax()
+		goal = Interval(maxutil - Decimal("0.00001"), maxutil)
+
+		bidsnearmax = bidswithutil.getBids(goal)
+		self.assertTrue(bidsnearmax.size() != 0)
+
+		foundmax = Decimal(0)
+		for bid in bidsnearmax :
+			util = self.profile.getUtility(bid)
+			if util>foundmax:
+				foundmax = util;
+		#found maximum may be slightly lower or higher because we rounded
+		#all weighted utilities.
+		self.assertTrue(abs(foundmax - maxutil) < 0.0001)
+
+	def benchmark(self):
+		print("\nBenchmarking " + self.profile.getName());
+		domainsize = AllBidsList(self.profile.getDomain()).size()
+
+		start = round(time.time()*1000)
+		body = BidsWithUtility.create(self.profile, self.accuracy)
+		list = body.getBids(self.utilityGoal)
+		end = round(time.time()*1000)
+		print("run time: " + str((end - start) / 1000.) + "s");
+		print("Total size of bidspace:" + str(domainsize))
+		print("Result size: " + str(list.size()))
Index: geniuswebcore/test/geniusweb/bidspace/IntervalTest.py
===================================================================
--- geniuswebcore/test/geniusweb/bidspace/IntervalTest.py	(revision 81)
+++ geniuswebcore/test/geniusweb/bidspace/IntervalTest.py	(revision 81)
@@ -0,0 +1,85 @@
+import unittest
+from unitpy.GeneralTests import GeneralTests
+from decimal import Decimal
+from geniusweb.bidspace.Interval import Interval
+from typing import List
+
+class IntervalTest (unittest.TestCase, GeneralTests[Interval]):
+
+	ZERO = Decimal(0)
+	ONE = Decimal(1)
+	TWO = Decimal(2)
+	THREE = Decimal(3)
+	TEN = Decimal(10)
+	
+	int1 = Interval(ZERO, ONE)
+	int1a = Interval(ZERO, ONE)
+	int2 = Interval(ONE, TEN)
+	int3 = Interval(TWO, TEN)
+
+	#Override
+	def getGeneralTestData(self)->List[List[Interval]] :
+		return [[self.int1, self.int1a], [self.int2],[self.int3]]
+
+	#Override
+	def getGeneralTestStrings(self) -> List[str] :
+		return ["Interval\\[0,1\\]", "Interval\\[1,10\\]",
+				"Interval\\[2,10\\]"]
+
+	def testsmokeTest(self) :
+		Interval(self.ZERO, self.ONE)
+
+	def testsmokeTestBad(self):
+		i = Interval(self.TEN, self.ONE)
+		self.assertTrue(i.isEmpty())
+
+	def testsmokeNull1Test(self):
+		self.assertRaises(ValueError, lambda: Interval(None,self.ZERO))
+
+	def testsmokeNull2test(self):
+		self.assertRaises(ValueError, lambda:Interval(self.ZERO, None))
+
+	def testMin(self):
+		self.assertEqual(Decimal(0), self.int1.getMin())
+		self.assertEqual(Decimal(1), self.int2.getMin())
+
+	def testMax(self):
+		self.assertEqual(Decimal(1), self.int1.getMax())
+		self.assertEqual(Decimal(10), self.int2.getMax())
+
+	def testcontainsTest(self):
+		self.assertTrue(self.int1.contains(Decimal(0.3)))
+		self.assertFalse(self.int1.contains(Decimal(-0.3)))
+		self.assertFalse(self.int1.contains(Decimal(1.3)))
+
+		self.assertFalse(self.int3.contains(self.ZERO))
+		self.assertFalse(self.int3.contains(self.ONE))
+		self.assertTrue(self.int3.contains(self.TWO));
+		self.assertTrue(self.int3.contains(self.THREE));
+		self.assertTrue(self.int3.contains(self.TEN));
+		self.assertFalse(self.int3.contains(Decimal(10.3)))
+
+	def testIntersect(self) :
+		self.assertEqual(self.int1, self.int1.intersect(self.int1))
+		self.assertEqual(Interval(self.ONE, self.ONE), self.int1.intersect(self.int2))
+		self.assertTrue(self.int1.intersect(self.int3).isEmpty())
+		self.assertEqual(Interval(self.ONE, self.TWO),
+				Interval(self.ZERO, self.TEN).intersect(Interval(self.ONE, self.TWO)))
+		self.assertEqual( Interval(self.ONE, self.TWO),
+				Interval(self.ONE, self.TWO).intersect(Interval(self.ZERO, self.TEN)))
+		self.assertEqual(Interval(self.ONE, self.TWO),
+				Interval(self.ZERO, self.TWO).intersect(Interval(self.ONE, self.TEN)))
+		self.assertEqual( Interval(self.ONE, self.TWO),
+				Interval(self.ONE, self.TEN).intersect( Interval(self.ZERO, self.TWO)))
+
+	def testsubtractTest(self):
+		self.assertEqual(Interval(Decimal(-1), self.ZERO),
+				self.int1.subtract(self.ONE))
+	
+	def testinvertTest(self) :
+		self.assertEqual(Interval(Decimal(-10), self.ZERO),
+				self.int1.invert(self.int2))
+		self.assertEqual(Interval(self.ZERO, self.TEN), self.int2.invert(self.int1))
+		self.assertEqual(
+				Interval(Decimal(-9), Decimal(8)),
+				self.int2.invert(self.int3))
Index: geniuswebcore/test/geniusweb/bidspace/IssueInfoTest.py
===================================================================
--- geniuswebcore/test/geniusweb/bidspace/IssueInfoTest.py	(revision 81)
+++ geniuswebcore/test/geniusweb/bidspace/IssueInfoTest.py	(revision 81)
@@ -0,0 +1,46 @@
+import unittest
+from geniusweb.issuevalue.DiscreteValue import DiscreteValue
+from decimal import Decimal
+from typing import Set, Dict
+from geniusweb.issuevalue.DiscreteValueSet import DiscreteValueSet
+from geniusweb.profile.utilityspace.DiscreteValueSetUtilities import DiscreteValueSetUtilities
+from geniusweb.bidspace.IssueInfo import IssueInfo
+from geniusweb.bidspace.Interval import Interval
+
+class IssueInfoTest(unittest.TestCase):
+
+	NAME = "name"
+	VAL1 = DiscreteValue("v1")
+	VAL2 = DiscreteValue("v2")
+	VAL3 = DiscreteValue("v3")
+	N03 = Decimal("0.3")
+	N04 = Decimal("0.4")
+	N05 = Decimal("0.5")
+	N06 = Decimal("0.6")
+	
+	def setUp(self) :
+		issuevalues:Set[DiscreteValue]  = set()
+		issuevalues.add(self.VAL1)
+		issuevalues.add(self.VAL2)
+		issuevalues.add(self.VAL3)
+		values = DiscreteValueSet(issuevalues)
+		valueUtils:Dict[DiscreteValue,Decimal] = {}
+		valueUtils[self.VAL1]= self.N03
+		valueUtils[self.VAL2]= self.N04
+		valueUtils[self.VAL3]= self.N05
+		utils = DiscreteValueSetUtilities(valueUtils)
+		self.info = IssueInfo(self.NAME, values, utils, self.N06, 6)
+
+	def testsmokeTest(self):
+		pass
+
+	def testGetExtremeMin(self):
+		self.assertEqual(self.VAL1, self.info.getExtreme(False))
+		self.assertEqual(self.VAL3, self.info.getExtreme(True))
+
+	def testgetNameTest(self):
+		self.assertEqual(self.NAME, self.info.getName())
+
+	def testgetIntervalTest(self):
+		self.assertEqual(Interval(self.N03*self.N06, self.N05*self.N06),
+				self.info.getInterval())
Index: geniuswebcore/test/geniusweb/references/ParametersTest.py
===================================================================
--- geniuswebcore/test/geniusweb/references/ParametersTest.py	(revision 80)
+++ geniuswebcore/test/geniusweb/references/ParametersTest.py	(revision 81)
@@ -45,4 +45,6 @@
 		# test fallback None
 		self.assertEqual(None, self.params2.getDouble("b", None, 4., 6.))
+		# a is integer!
+		self.assertEqual(1, self.params2.getDouble("a", 0., -0., 2.))		
 
 	def testGetDoubleWithErrors(self):
Index: geniuswebcore/test/resources/7issues/7issues1.json
===================================================================
--- geniuswebcore/test/resources/7issues/7issues1.json	(revision 81)
+++ geniuswebcore/test/resources/7issues/7issues1.json	(revision 81)
@@ -0,0 +1,105 @@
+{
+	"LinearAdditiveUtilitySpace": {
+		"name": "7issues1",
+		"issueUtilities": {
+			"i1": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.11,
+					"highValue": 9,
+					"highUtility": 0.99
+
+				}
+			},
+			"i2": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.12,
+					"highValue": 9,
+					"highUtility": 0.97
+
+				}
+			},
+			"i3": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.13,
+					"highValue": 9,
+					"highUtility": 0.96
+
+				}
+			},
+			"i4": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.14,
+					"highValue": 9,
+					"highUtility": 0.94
+
+				}
+			},
+			"i5": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.15,
+					"highValue": 9,
+					"highUtility": 0.93
+
+				}
+			},
+			"i6": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.16,
+					"highValue": 9,
+					"highUtility": 0.92
+
+				}
+			},
+			"i7": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.16,
+					"highValue": 9,
+					"highUtility": 0.91
+
+				}
+			}
+		},
+		"issueWeights": {
+			"i1": 0.07531677352656704,
+			"i2": 0.18148468268008364,
+			"i3": 0.13035193969082373,
+			"i4": 0.24649985443378972,
+			"i5": 0.16931694966873587,
+			"i6": 0.131353,
+			"i7": 0.0656768
+		},
+		"domain": {
+			"name": "7issues",
+			"issuesValues": {
+				"i1": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i2": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i3": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i4": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i5": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i6": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i7": {
+					"range": {"low":0,"high":9,"step":1}
+				}
+			}
+		}
+	}
+}
Index: geniuswebcore/test/resources/7issues/7issues2.json
===================================================================
--- geniuswebcore/test/resources/7issues/7issues2.json	(revision 81)
+++ geniuswebcore/test/resources/7issues/7issues2.json	(revision 81)
@@ -0,0 +1,105 @@
+{
+	"LinearAdditiveUtilitySpace": {
+		"name": "7issues2",
+		"issueUtilities": {
+			"i1": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.51,
+					"highValue": 9,
+					"highUtility": 0.11
+
+				}
+			},
+			"i2": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.92,
+					"highValue": 9,
+					"highUtility": 0.21
+
+				}
+			},
+			"i3": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.93,
+					"highValue": 9,
+					"highUtility": 0.13
+
+				}
+			},
+			"i4": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.94,
+					"highValue": 9,
+					"highUtility": 0.14
+
+				}
+			},
+			"i5": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.95,
+					"highValue": 9,
+					"highUtility": 0.15
+
+				}
+			},
+			"i6": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.96,
+					"highValue": 9,
+					"highUtility": 0.16
+
+				}
+			},
+			"i7": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.97,
+					"highValue": 9,
+					"highUtility": 0.17
+
+				}
+			}
+		},
+		"issueWeights": {
+			"i1": 0.24745759773026107,
+			"i2": 0.11824193959921694,
+			"i3": 0.1860471425098606,
+			"i4": 0.20629555826677742,
+			"i5": 0.16112666189388397,
+			"i6": 0.0538874,
+			"i7": 0.0269437
+		},
+		"domain": {
+			"name": "7issues",
+			"issuesValues": {
+				"i1": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i2": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i3": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i4": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i5": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i6": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i7": {
+					"range": {"low":0,"high":9,"step":1}
+				}
+			}
+		}
+	}
+}
Index: geniuswebcore/test/resources/9issues/9issues1.json
===================================================================
--- geniuswebcore/test/resources/9issues/9issues1.json	(revision 81)
+++ geniuswebcore/test/resources/9issues/9issues1.json	(revision 81)
@@ -0,0 +1,134 @@
+{
+	"LinearAdditiveUtilitySpace": {
+		"name": "9issues1",
+		"issueUtilities": {
+			"i1": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.11,
+					"highValue": 9,
+					"highUtility": 0.99
+
+				}
+			},
+			"i2": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.12,
+					"highValue": 9,
+					"highUtility": 0.97
+
+				}
+			},
+			"i3": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.13,
+					"highValue": 9,
+					"highUtility": 0.96
+
+				}
+			},
+			"i4": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.14,
+					"highValue": 9,
+					"highUtility": 0.94
+
+				}
+			},
+			"i5": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.15,
+					"highValue": 9,
+					"highUtility": 0.93
+
+				}
+			},
+			"i6": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.16,
+					"highValue": 9,
+					"highUtility": 0.92
+
+				}
+			},
+			"i7": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.16,
+					"highValue": 9,
+					"highUtility": 0.91
+
+				}
+			},
+			"i8": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.7664,
+					"highValue": 9,
+					"highUtility": 0.183
+
+				}
+			},
+
+			"i9": {
+				"NumberValueSetUtilities": {
+					"lowValue": 0,
+					"lowUtility": 0.191,
+					"highValue": 9,
+					"highUtility": 0.891
+
+				}
+			}
+
+		},
+		"issueWeights": {
+			"i1": 0.07531677352656,
+			"i2": 0.18148468268008,
+			"i3": 0.12035193969082,
+			"i4": 0.21649985443378,
+			"i5": 0.15621694966876,
+			"i6": 0.111253,
+			"i7": 0.0656768,
+			"i8": 0.0201,
+			"i9": 0.0531
+		},
+		"domain": {
+			"name": "9issues",
+			"issuesValues": {
+				"i1": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i2": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i3": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i4": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i5": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i6": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i7": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i8": {
+					"range": {"low":0,"high":9,"step":1}
+				},
+				"i9": {
+					"range": {"low":0,"high":9,"step":1}
+				}
+
+			}
+		}
+	}
+}
