class TestAlignementStation(TestCase):
    def setUp(self):
        self.alignementStation = AlignementStation()

    def test_distance_laterale_negative_retourne_deplacement_gauche(self):
        distance_x = -2
        commande, _ = self.alignementStation.ajusterPositionLaterale_CM(distance_x)
        self.assertEqual('left', commande, "Station se trouvant a gauche, mais retourne un deplacement a droite")

    def test_distance_laterale_positive_retourne_deplacement_droite(self):
        distance_x = 3
        commande, _ = self.alignementStation.ajusterPositionLaterale_CM(distance_x)
        self.assertEqual('right', commande, "Station se trouvant a droite, mais retourne un deplacement a gauche")

    def test_distance_frontale_positive_retourne_deplacement_avant(self):
        distance_y = 3
        commande, _ = self.alignementStation.ajusterPositionY(distance_y)
        self.assertEqual('forward', commande, "Station se trouvant en avant, mais retourne un deplacement recule")

    def test_distance_elevee_retourne_deux_ajustements(self):
        distance_x = 4
        distance_y = 3
        ajustements = self.alignementStation.calculerAjustement(distance_x, distance_y)
        self.assertEqual(len(ajustements), 2, "Station mal alignee, mais ne retourne pas le bon nombre d'ajustement")

    def test_distance_laterale_en_mm_negligeable_retourne_aucun_ajustements_en_mm(self):
        distance_x = 1.2
        distance_y = 3
        self.alignementStation.ajusterPositionLaterale_MM = MagicMock()
        ajustements = self.alignementStation.calculerAjustement(distance_x, distance_y)
        self.assertFalse(self.alignementStation.ajusterPositionLaterale_MM.called)

    def test_distance_laterale_minimale_retourne_ajustements_en_mm(self):
        distance_x = 1.4
        distance_y = 5
        self.alignementStation.ajusterPositionLaterale_MM = MagicMock()
        ajustements = self.alignementStation.calculerAjustement(distance_x, distance_y)
        self.assertTrue(self.alignementStation.ajusterPositionLaterale_MM.called)

    def test_distance_laterale_grande_retourne_ajustements_en_cm_seulement(self):
        distance_x = 32.8
        distance_y = 5
        self.alignementStation.ajusterPositionLaterale_MM = MagicMock()
        ajustements = self.alignementStation.calculerAjustement(distance_x, distance_y)
        self.assertFalse(self.alignementStation.ajusterPositionLaterale_MM.called)
 def __init__(self):
     self.alignementStation = AlignementStation()
     self.positionZone = (820, 730)
     self.rayonZone = 20
     self._definirIntervallesCouleurs()
     self.ajustements = None
class DetectionStation(object):
    def __init__(self):
        self.alignementStation = AlignementStation()
        self.positionZone = (820, 730)
        self.rayonZone = 20
        self._definirIntervallesCouleurs()
        self.ajustements = None

    def trouverAjustements(self, image):
        self.imageCamera = image
        contoursCible = self.detecterFormeCouleur(self.intervalleOrange)
        if contoursCible is not None:
            distance_y = self._trouverDistanceStation(contoursCible, KNOWN_WIDTH_ORANGE)
            distance_x = self._trouverOffsetLateral(contoursCible)
            self.ajustements = self.alignementStation.calculerAjustement(distance_x, distance_y)
        else:
            self.ajustements = None

    def _trouverDistanceStation(self, contoursCible, largeurConnue):
        zoneTresor = cv2.minAreaRect(contoursCible)
        distance_y = self._calculerDistanceCamera(largeurConnue, FOCAL_LENGTH, zoneTresor[1][0]) * 2.54

        return distance_y

    def _trouverOffsetLateral(self, contoursCible):
        position_x, position_y = self._trouverCentreForme(contoursCible)
        positionZone_x, positionZone_y = self.positionZone
        distance_x = (positionZone_x - position_x) / RATIO_PIXEL_CM

        return distance_x

    def _calculerDistanceCamera(self, largeurTresor, longueurFocale, referenceLargeur):
        return (largeurTresor * longueurFocale) / referenceLargeur

    def detecterFormeCouleur(self, intervalleCouleur):
        intervalleFonce, intervalleClair, couleurForme = intervalleCouleur
        masqueCouleur = cv2.inRange(self.imageCamera, intervalleFonce, intervalleClair)

        _, contoursCouleur, _ = cv2.findContours(masqueCouleur.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        if len(contoursCouleur) > 0:
            contoursCible = self._obtenirFormeInteret(contoursCouleur)
            if contoursCible is not None:
                return contoursCible
            else:
                return None

    def _dessinerInformations(self, contoursCible, distanceStation):
        zoneTresor = cv2.minAreaRect(contoursCible)
        boiteTresor = np.int0(cv2.boxPoints(zoneTresor))
        cv2.drawContours(self.imageCamera, [boiteTresor], -1, (0, 255, 0), 2)

        cv2.putText(
            self.imageCamera,
            "%.2f cm" % (distanceStation),
            (self.imageCamera.shape[1] - 300, self.imageCamera.shape[0] - 20),
            cv2.FONT_HERSHEY_SIMPLEX,
            2.0,
            (0, 255, 0),
            3,
        )

    def _trouverCentreForme(self, contoursForme):
        MatriceCentreMasse = cv2.moments(contoursForme)
        centre_x = int(MatriceCentreMasse["m10"] / MatriceCentreMasse["m00"])
        centre_y = int(MatriceCentreMasse["m01"] / MatriceCentreMasse["m00"])

        return centre_x, centre_y

    def _obtenirFormeInteret(self, contoursCouleur):
        contoursNegligeable = []
        for contours in range(len(contoursCouleur)):
            aire = cv2.contourArea(contoursCouleur[contours])
            if aire < MAX_AIRE_SIGNE_STATON:
                contoursNegligeable.append(contours)

        if len(contoursNegligeable) > 0:
            contoursCouleur = np.delete(contoursCouleur, contoursNegligeable)

        if contoursCouleur is not None:
            return contoursCouleur[0]
        else:
            return None

    def _definirIntervallesCouleurs(self):
        self.intervalleBleuMarin = np.array([120, 80, 40]), np.array([180, 150, 100]), "Bleu"
        self.intervalleOrange = np.array([0, 50, 140]), np.array([60, 150, 255]), "Orange"

    def _dessinerZoneCible(self):
        cv2.circle(self.imageCamera, self.positionZone, self.rayonZone, (0, 255, 0), 2)

    def _dessinerZoneForme(self, position, rayon):
        cv2.line(self.imageCamera, self.positionZone, position, (255, 0, 0), 5)
        cv2.circle(self.imageCamera, position, int(rayon), (0, 0, 255), 2)
        print(position)
        cv2.circle(self.imageCamera, position, 10, (0, 0, 255), 2)
 def setUp(self):
     self.alignementStation = AlignementStation()