class SelectionsTest(unittest.TestCase):

    def setUp(self):
        self.__selections = Selections()
        self.__selections.addSelections("default", [1, 2, 3])

    def testAddAndGetSelections_byPosition(self):
        '''Tests adding and retrieval of selection. Note that the returned order must be the
        same as the order as in which they were added!'''
        assert_that(self.__selections.getSelections("default"), contains(1, 2, 3))

    def testAddAndGetSelections_all(self):
        assert_that(self.__selections.getSelections(), is_(equal_to({
            "default": [1, 2, 3]
        })))

    def testAddSelections_alreadyAtPosition(self):
        self.__selections.addSelections("default", 1)
        assert_that(self.__selections.getSelections("default"), contains(1, 2, 3))


    def testAddSelections_positionAlreadyExists(self):
        self.__selections.addSelections("default", 4)
        assert_that(self.__selections.getSelections("default"), contains(1, 2, 3, 4))
    
    def testAddSelections_useList(self):
        self.__selections.addSelections("default", [4, 5])
        assert_that(self.__selections.getSelections("default"), contains(1, 2, 3, 4, 5))
    
    def testAddSelections_useListWithOverlap(self):
        self.__selections.addSelections("default", [3, 4, 5])
        assert_that(self.__selections.getSelections("default"), contains(1, 2, 3, 4, 5))

    def testAddSelections_otherPositions(self):
        self.__selections.addSelections("with list", [4, 5, 6])
        self.__selections.addSelections("use single", 7)

        assert_that(self.__selections.getSelections(), has_entries({
            "default": [1, 2, 3],
            "with list": [4, 5, 6],
            "use single": [7]
        }))

    def testGetSelections_byPosition_noEntriesAddedForPosition(self):
        assert_that(self.__selections.getSelections("not added"), is_(equal_to([])))

    def testGetSelections_byPosition_afterAllRemoved(self):
        self.__selections.removeSelection("default", 1)
        self.__selections.removeSelection("default", 2)
        self.__selections.removeSelection("default", 3)
        assert_that(self.__selections.getSelections("default"), is_(equal_to([])))

    def testGetSelections_all_beforeAnyAdded(self):
        assert_that(Selections().getSelections(), is_(equal_to({})))

    def testGetSelectedPositions(self):
        assert_that(self.__selections.getSelectedPositions(1), contains_inanyorder("default"))

    def testGetSelectedPositions_all(self):
        assert_that(self.__selections.getSelectedPositions(), is_(equal_to({
            1: set(["default"]),
            2: set(["default"]),
            3: set(["default"])
        })))

    def testGetSelectedPositions_multiplePositions(self):
        self.__selections.addSelections("other", [1])
        assert_that(self.__selections.getSelectedPositions(1), 
            contains_inanyorder("default", "other"))

    def testGetSelectionPositions_all_multiplePositions(self):
        self.__selections.addSelections("other", [1])
        assert_that(self.__selections.getSelectedPositions(), is_(equal_to({
            1: set(["default", "other"]),
            2: set(["default"]),
            3: set(["default"])
        })))

    def testGetSelectedPositions_afterRemove(self):
        self.__selections.removeSelection("default", 1)
        assert_that(len(self.__selections.getSelectedPositions(1)), is_(equal_to(0)))

    def testGetSelectedPositions_all_afterRemove(self):
        self.__selections.removeSelection("default", 1)
        assert_that(self.__selections.getSelectedPositions(), is_(equal_to({
            2: set(["default"]),
            3: set(["default"])
        })))

    def testGetSelectedPositions_all_afterAllRemoved(self):
        self.__selections.removeSelection("default", 1)
        self.__selections.removeSelection("default", 2)
        self.__selections.removeSelection("default", 3)
        assert_that(self.__selections.getSelectedPositions(), is_(equal_to({}))) 

    def testRemoveSelection_removeExisting(self):
        self.__selections.removeSelection("default", 1)
        assert_that(self.__selections.getSelections("default"), contains(2, 3))

    def testRemoveSelection_nonExistingPlayerId(self):
        self.__selections.removeSelection("default", 5)
        assert_that(self.__selections.getSelections("default"), contains(1, 2, 3))

    def testRemoveSelection_nonExistingPosition(self):
        self.__selections.removeSelection("other", 1)
        assert_that(self.__selections.getSelections("default"), contains(1, 2, 3))

    def testRemoveSelection_playerHasMultiplePositions(self):
        self.__selections.addSelections("other", 1)
        self.__selections.removeSelection("default", 1)
        assert_that(self.__selections.getSelections(), has_entries({
            "default": [2, 3],
            "other": [1]
        }))

    def testRemoveSelection_allRemoved(self):
        self.__selections.removeSelection("default", 1)
        self.__selections.removeSelection("default", 2)
        self.__selections.removeSelection("default", 3)
        assert_that(self.__selections.getSelections(), is_(equal_to({})))
                # quartile.
   
                replacement = dao.findReplacement(p, 
                    selections.getSelectedPositions().iterkeys(),
                    minGames = minGames,        
                    priceLimit = quartiles[p].getQuartileBounds()[0])
                
                print "  Replace with: %s (%s)" % (replacement["name"], replacement["price"])
                byIds[replacement["id"]] = replacement
                selections.addSelections(p, replacement["id"])
                
totalPrice = dao.getTotalPrice(selections.getSelectedPositions().iterkeys())
print "Total price: %s" % totalPrice

# If the total price is too high, look at adjusting the preferences of the lower candidates first.
for (position, selected) in selections.getSelections().iteritems():
    last2 = selected[-2:]
    nominalQuartile = [1, 0]
    for i in [0, 1]:
        candidate = byIds[last2[i]]
        if quartiles[position].findQuartile(candidate['price']) > nominalQuartile[i]:
            # Find replacement.
            print "  Replace candidate %s" % candidate["name"]

            selections.removeSelection(position, last2[i])
            replacement = dao.findReplacement(position, 
                selections.getSelectedPositions().iterkeys(),
                minGames = minGames,        
                priceLimit = quartiles[position].getQuartileBounds()[nominalQuartile[i]])
        
            print "  Replace with: %s (%s)" % (replacement["name"], replacement["price"])