#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" Schnittstelle zwischen Lichtpult und OLA
#!/usr/bin/env python3
- Empfangen der aktuellen Werte
- Senden der im Lichtpult errechneten Werte an die jeweiligen Universen

"""

# OLARECEIVESTRING = "/ola/universe/"
OLASENDSTRING    = "/dmx/universe/"

# import math
import socket
import threading
import array
import time
# import urllib.request # um ola plugins neu zu laden mit "localhost:9090/reload"

# from pythonosc import dispatcher
# from pythonosc import osc_server
from pythonosc import osc_message_builder
from pythonosc import udp_client

from mix import Mix

# ------------------------------------------------------------------------------
# http://stackoverflow.com/questions/166506/
# finding-local-ip-addresses-using-pythons-stdlib
def get_ip_address():
    return ([(s.connect(('8.8.8.8', 80)),s.getsockname()[0], s.close())
           for s in [socket.socket (socket.AF_INET, socket.SOCK_DGRAM)]][0][1])
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class OscOla (Mix):
    """ Verbindung zu Ola:
In self.__dmx sind die aktuellen Werte aller Universen eingelesen
In self.__mix sind die im Lichtpult berechneten Werte, die zu senden sind
Vor Verwendung festzulegende Variablen:
ola_ip, out_port, universes,
"""
    olacount = 0

    def __init__(self):
        OscOla.olacount += 1
        # print ("Ola Count", OscOla.olacount)

        Mix.__init__(self)
        self.ola_ip = "127.0.0.1"
        self.out_port = 7770

        self.timeout = 0.05 # 0.05
        self.mix_thread = threading.Thread(target=self.run)
        self.mix_thread.setDaemon (True)
        # self.__mixing = False
        self.paused = False
        # self.pause_cond = threading.Condition (threading.Lock ())

        self.client = udp_client.UDPClient(self.ola_ip, self.out_port)
        self.set_universes (1)

        # self.mix_thread.start ()

    def set_ola_ip (self, newip):
        self.ola_ip = newip
        self.client.__init__ (self.ola_ip, self.out_port)

    def set_out_port (self, newport):
        self.out_port = newport
        self.client.__init__ (self.ola_ip, self.out_port)

    def update_uni(self, uni):  # mix-Werte nach Ola senden
        msgaddress = OLASENDSTRING + "{0}".format (uni)
        self.msg = osc_message_builder.OscMessageBuilder(address = msgaddress)
#        arg = array.array('B', self.__mix[uni-1]).tostring()
# Python 3.9 error:
#        arg = array.array('B', self.show_mix(uni)).tostring()
        arg = array.array('B', self.show_mix(uni)).tobytes()
        self.msg.add_arg (arg)
        self.msg = self.msg.build()
        self.client.send (self.msg)

    def run (self): #
        """ Mix an Ola senden """
        while True:
            for i in range (self.universes()):
                self.update_uni (1+i)
            time.sleep(self.timeout)

    def start_mixing (self):
        """ Mix starten """
        self.mix_thread.start ()

# ------------------------------------------------------------------------------
# Unit Test:
if __name__ == "__main__":

    ola   = OscOla ()
    ola.set_ola_ip ("192.168.0.19")
    #ola.set_universes (2)
    print("Verbinde zu OLA-device: {0}".format (ola.ola_ip))

    # dieser Rechner:
    local_ip = get_ip_address()
    print("Meine IP: {}".format(local_ip))

    ola.start_mixing()

    print("---- Lichtpult + OLA -----\n")
    print("Kommandos: x = Exit")
    print("           u = Anzahl der Universen")
    print("           r = Reset  der Universen")
    print("           1 = diverse Werte setzen")
    print("           2 = diverse Werte setzen")
    print("           3 = OLA Channel 1-2 lesen")
    print("           4 = Universes = 2")
    print("           5 = diverse Werte auf Uni 2 setzen")
    print("           6 = OLA Channel 2-1 lesen")
    print("           7 =  Uni 1 lesen")
    print("           8 =  Uni 2 lesen")

    try:
        i = 1
        while i:
            i = input ("CMD: ")
            if i == 'x': break
            elif i == 'u':
                print (ola.universes())
            elif i == 'r':
                ola.reset_mix()
            elif i == '1':
                ola.set_mixval (1,43, 255)
                ola.set_mixval (1,2, 127)
                ola.set_mixval (1,3, 12)
            elif i == '2':
                ola.set_mixval (1,43, 0)
                ola.set_mixval (1,2, 255)
                ola.set_mixval (1,3, 0)
            elif i == '3':
                print (ola.mixval(1,2))
            elif i == '4':
                ola.set_universes (2)
                #print (ola.show_mix (2))
            elif i == '5':
                ola.set_mixval (2,1, 255)
                ola.set_mixval (2,2, 127)
                ola.set_mixval (2,3, 12)
            elif i == '6':
                print (ola.mixval(2,2))
            elif i == '7':
                print (ola.show_mix(1))
            elif i == '8':
                print (ola.show_mix (2))

            elif i == '':
                i=1
            else:
                pass
    finally:
        print ("bye...")


from sklearn.metrics import f1_score
from sklearn.metrics import r2_score

def score(predict, target, type='f1'):
    """Evaluate accuracy.

    predict: predict lables
    target: target labels
    """
    if type is 'f1':
        score = f1_score(target.values.astype(int), predict.values.astype(float), average='micro')
    elif type is 'r2':
        score = r2_score(target.values, predict.values)
    else:
        raise ValueError('the score type is wrong. please choice f1 or r2.')

    return score


import base64
import json
from io import BytesIO
import math

import logging
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scipy
import scipy.stats
from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt

from core.utils import upload_file
from setup.settings import TEMPORARY_FILE_DIR

plt.switch_backend("agg")

@csrf_exempt
def choose_mle(request):
    return render(request, "mle/choose_mle.html")

@csrf_exempt
def mle(request):
    if request.method == "POST":
        plt.close("all")
        output_dict = json.loads(request.body)
        mean_val, std_val = float(output_dict["mean"]), float(output_dict["std"])
        X = np.random.normal(mean_val, std_val, 1000)
        mu, std = scipy.stats.norm.fit(X)
        pdf = scipy.stats.norm.pdf
        x = np.linspace(0, 80, 80)
        plt.hist(X, bins=x, density="true")
        plt.plot(pdf(x, loc=mu, scale=std))
        plt.xlabel("Value")
        plt.ylabel("Frequency")
        plt.legend(
            [
                "Fitted Distribution",
                "Observed Data",
            ]
        )
        buffer = BytesIO()
        plt.savefig(buffer, format="png")
        buffer.seek(0)
        image_png = buffer.getvalue()
        buffer.close()

        image = base64.b64encode(image_png)
        image = image.decode("utf-8")
        return JsonResponse({"image": image})

    return render(request, "mle/mle_home.html")

@csrf_exempt
def mle_custom(request):
    if request.method == "POST":
        df = upload_file(request)
        column_headers = list(df.columns)
        if len(column_headers) > 0:
            return render(
                request,
                "mle/mle_custom.html",
                {"column_headers": column_headers},
            )
    if request.method == "PUT":
        try:
            plt.close("all")
            df = pd.read_csv(f"{TEMPORARY_FILE_DIR}/user_file.csv", sep=",")
            output_dict = json.loads(request.body)
            target_column = output_dict["target_column"]
            X_column = df[target_column]
            min_num = math.floor(X_column.min())
            max_num = math.ceil(X_column.max())
            mean = scipy.mean([X_column])
            std_val = np.std([X_column])
            mu, std = scipy.stats.norm.fit(X_column)
            pdf = scipy.stats.norm.pdf
            x = np.linspace(min_num, max_num, max_num + 10)
            plt.hist(X_column, bins=x, density="true")
            plt.plot(pdf(x, loc=mu, scale=std))
            plt.xlabel("Value")
            plt.ylabel("Frequency")
            plt.legend(
                [
                    "Fitted Distribution",
                    "Observed Data",
                ]
            )
            buffer = BytesIO()
            plt.savefig(buffer, format="png")
            buffer.seek(0)
            image_png = buffer.getvalue()
            buffer.close()
            image = base64.b64encode(image_png)
            image = image.decode("utf-8")
            return JsonResponse(
                {"image": image, "mean": round(mean, 2), "std": round(std_val, 2)}
            )
        except Exception as e:
            logging.getLogger("error_logger").error("Error: " + repr(e))
            return JsonResponse(
                {
                    "error": "The column you selected as the target does not meet the requirements. Please select another column or upload a new dataset."
                }
            )
    return render(request, "mle/mle_custom.html")


from bs4 import BeautifulSoup
import urllib
import requests
import soupsieve as sv
import codecs
import csv
import io
import re
import numpy as np

#below was testing for confirm that inmate mailing addr exists as reference point, done
#===============================================================================
# f1 = open('out5.csv', 'rt')
# csv_reader = csv.reader(f1, escapechar='\\')
# #q = input("what name?")
#
# for row in csv_reader:
#     html_doc = urllib.request.urlopen(row[0]).read()
#     soup = BeautifulSoup(html_doc, 'html.parser')
#     holding = []
#     for string in soup.strings:
#         holding.append(string)
#     try:
#         index1 = holding.index('Inmate Mailing Address:')
#         print(index1)
#     except ValueError:
#         print(row[0])
#         continue
#===============================================================================

#
#html_doc = urllib.request.urlopen('https://www.prisonpro.com/content/roxbury-correctional-institution').read()
html_doc = urllib.request.urlopen('https://www.prisonpro.com/content/chittenden-regional-correctional-facility').read()
#https://www.prisonpro.com/content/correctional-alternative-placement-program-capp
#html_doc = urllib.request.urlopen('https://www.prisonpro.com/content/san-quentin-state-prison').read()
#html_doc = urllib.request.urlopen('https://www.prisonpro.com/content/easterling-correctional-institution').read()
#html_doc = urllib.request.urlopen('https://www.prisonpro.com/content/correctional-alternative-placement-program-capp').read()
#html_doc = urllib.request.urlopen('https://www.prisonpro.com/content/gulf-correctional-institution').read()
#html_doc = urllib.request.urlopen('https://www.prisonpro.com/content/donaldson-correctional-facility').read()
soup = BeautifulSoup(html_doc, 'html.parser')
holding = []
for string in soup.strings:
    holding.append(string)
    if "Inmate Mailing Address" in string:
        index1 = holding.index(string)

h2 = holding[index1:index1+9] #this is list of useful info strings

fac_id_str = ['prison', 'institution', 'facility', 'center', 'correctional']
add_info_str = ['dorm', 'housing', 'bed']

#===============================================================================
# for ele in h2:
#     z = re.search('^[^0-9]+(\,\s){1}([A-Z]{2}){1}\s(?P<zipcode>\d{5})(?:[-]\d{4})?', ele).groupdict()['zipcode']
#     if z != None:
#         print(z)
#         index2 = h2.index(ele)
#         print(index2)
#===============================================================================

#print(h2)

#print(holding[index1+5])
#address = holding[index1+5]
#encoded_zip = address.encode("ascii", "ignore")
#decoded_zip = encoded_zip.decode()

for string in h2:
    #pattern = re.compile('^[^0-9]+(\,\s){1}([A-Z]{2}){1}\s(\d{5})(?:[-]\d{4})?')
    regex = r"^[^0-9]+(\,\s){1}([A-Z]{2}|[A-Za-z]+){1}\s(\d{5})(?:[-]\d{4})?"
    #result = pattern.findall(string)
    match = re.search(regex, string)
    if match != None:
        print(string) #city state zip string, with zip being extracted in below statement
        z = re.search('[^0-9]+(\,\s){1}([A-Z]{2}|[A-Za-z]+){1}\s(?P<zipcode>[0-9]{5})(?:[-]\d{4})?$', string).groupdict()['zipcode']
        print(z)
        print("next:")
        print(h2[h2.index(string)])
        index2 = h2.index(string) #this is firm location of string with zip in it
        index3 = index2 - 1 #this should be firm location of street address
        print("now finding always the street address:")
        print(h2[index3])
        print("now making sure dorm or housing info rightly places index for ")
        for a in add_info_str:
            if a in h2[index3-1]:
                index4 = index3 - 2 #index4 should be facility name, depending on if dorm/bed field there or not
                print(h2[index4])
                break
            else:
                index4 = index3 - 1
                print(h2[index4])
                break
        src_name = h2[index4]
        encoded_name = src_name.encode("ascii", "ignore")
        decoded_name = encoded_name.decode()
        with codecs.open("customers8.csv", encoding='utf-8', mode ='a') as f:
            fieldnames = ['name', 'address', 'zip']
            writer = csv.DictWriter(f, fieldnames=fieldnames)
            writer.writeheader()
            writer.writerow({'name': decoded_name, 'address': h2[index3], 'zip': z})

    #===========================================================================
    # if result != None:
    #     index2 = h2.index(string)
    #     #print(result)
    #     print(h2[index2])
    #     #z = re.search('^[^0-9]+(\,\s){1}([A-Z]{2}){1}\s(?P<zipcode>\d{5})(?:[-]\d{4})?', result).groupdict()['zipcode']
    #     #print(z)
    #===========================================================================

print(h2[index4])
print("below here")
print(h2[0])
print(h2)
print(h2[3])
#print(h2[index2])

#method of stripping non ascii from stuff
h3 = []
for a in h2:
    encoded_h = a.encode("ascii", "ignore")
    decoded_h = encoded_h.decode()
    h3.append(a)
    print(a)

#print(result)
#print(h2[index2])
#print(h2[index2])

#z = re.search('^[^0-9]+(\,\s){1}([A-Z]{2}){1}\s(?P<zipcode>\d{5})(?:[-]\d{4})?', holding[index1+5]).groupdict()['zipcode']

#print(z)
#actual_zip = re.match('^(\d{5})(?:[-]\d{4})?$', decoded_zip).groupdict()['zipcode'] #now we have zip code extracted from address
#act_zip = re.search('^\d{5}$', address)
#print(act_zip)
#===============================================================================
# address = holding[index4]
# encoded_zip = address.encode("ascii", "ignore")
# decoded_zip = encoded_zip.decode()
#
# actual_zip = re.match('^\d{5}(?:[-]\d{4})?$', decoded_zip).groupdict()['zipcode'] #now we have zip code extracted from address
#===============================================================================

# this is regex for zip code and +4 matching > ^\d{5}(?:[-]\d{4})?$

#not quite finished here ^^^

#if "Dorm" in string or "housing" in string or "bed" in string:

#print(index1)
#print(h2)

#===============================================================================
# t2 = holding[47:55]
# print(t2)
# t3 = holding[index1:index1+9]
# print(t3[1])
#===============================================================================

#print(holding[index1+5]+" should be zip field")
#print(holding[y])
#check = holding.index('Inmate Mailing Address')

#===============================================================================
# test = holding[[i for i, item in enumerate(holding) if re.search('(inmate)\s(name)', item)]]
#print(test) ----- ^(inmate)\s(name)$
#
# #if "Dorm" in holding[index1+1]:
#     #index2 = index1 + 2
#     #print("place needs Housing info")
# #else:
# index2 = index1 + 2 #this should refer to facility name
# index3 = index2 + 1 #this should refer to street address
# index4 = index3 + 1 #this should refer to city state and zip
# address = holding[index4]
# try:
#     actual_zip = re.match('^.*(?P<zipcode>\d{5}).*$', address).groupdict()['zipcode'] #now we have zip code extracted from address
# except AttributeError:
#     actual_zip = 'FIND ME'
# actual_name = holding[index2]
# encoded_name = actual_name.encode("ascii", "ignore")
# decoded_name = encoded_name.decode()
#
# print(index1)
# #===============================================================================
# # print(holding[index1])
# # print(holding[index2]+" this should be name of facility")
# # print(holding[index3]+" this should be street?")
# # print(holding[index4]+" this should be city state zip")
# # print(actual_zip)
# # print(decoded_name)
# #===============================================================================
#
# fruit_list = ['raspberry', 'apple', 'strawberry']
# berry_idx = [i for i, item in enumerate(fruit_list) if re.search('berry$', item)]
# print(berry_idx)
# # (inmate)\s(name)
#
#
#
#
# print("ok")
# print(address)
# print(actual_zip)
# print(holding[index2])
# print(holding[index3])
#===============================================================================

#===============================================================================
# for string in soup.strings:
#     holding.append(string)
#     if "Inmate Mailing Address" in string:
#         print(holding.index(string))
#         index1 = holding.index(string)
#     if "Inmate" in string and "Name" in string:
#
#         y = holding.index(string)
#         print(y)
#===============================================================================

#===============================================================================
# fruit_list = ['raspberry', 'apple', 'strawberry']
# berry_idx = [i for i, item in enumerate(fruit_list) if re.search('berry$', item)]
# print(berry_idx)
#===============================================================================

    #===========================================================================
    #     index1 = holding.index(string)
    #     index2 = index1 + 2 #this should refer to facility name
    #     index3 = index2 + 1 #this should refer to street address
    #     index4 = index3 + 1 #this should refer to city state and zip
    #     if "bed" in string or "housing" in string or "dorm" in string:
    #         temp2_index = holding.index(string)
    #         index1 = temp2_index + 1
    #         index2 = index1 + 1 #this should refer to facility name
    #         index3 = index2 + 1 #this should refer to street address
    #         index4 = index3 + 1 #this should refer to city state and zip
    # if "Inmate" in string and "Name" in string:
    #     y = holding.index(string)
    #     print(y)
    #===========================================================================


"""
Module finder_interface of the package pyzeal.

This module contains the base interface for all rootfinder implementations. Its
methods provide the main root finding API for end users. Internally its
implementations should build up an appropriate root finding context and then
employ a `FinderAlgorithm` to calculate the actual roots. Internal book keeping
is facilitated by the implementations of `RootContainer`.

Authors:\n
- Philipp Schuette\n
"""

from abc import ABC, abstractmethod
from typing import Optional, Tuple

from numpy import int32
from numpy.typing import NDArray

from pyzeal.pyzeal_types.filter_types import FilterTypes
from pyzeal.pyzeal_types.root_types import tVec
from pyzeal.utils.containers.root_container import RootContainer
from pyzeal.utils.factories.container_factory import ContainerFactory
from pyzeal.utils.initialization_handler import PyZEALInitializationHandler

class RootFinderInterface(ABC):
    """
    Interface for the main root finding API. After initializing a root finder
    for a given concrete problem methods for calculating roots as well as
    properties for retrieving roots and their orders are available.
    """

    PyZEALInitializationHandler.initPyZEALServices()

    @abstractmethod
    def calculateRoots(
        self,
        reRan: Tuple[float, float],
        imRan: Tuple[float, float],
        precision: Optional[Tuple[int, int]] = None,
    ) -> None:
        """
        Abstract entry point for starting a root finding calculation in the
        rectangle `reRan x imRan` up to a number of `precision` significant
        digits in real and imaginary part.

        :param reRan: horizontal extend of the complex region to search in
        :param imRan: vertical extend of the complex region to search in
        :param precision: accuracy of the search in real and imaginary parts
        """

    @property
    @abstractmethod
    def roots(self) -> tVec:
        """
        Return the roots calculated with this root finder through previous
        calls to `calculateRoots()`.

        :return: the set of roots calculated by this finder
        """

    @property
    @abstractmethod
    def orders(self) -> NDArray[int32]:
        """
        Return the orders of the roots calculated with this finder. The output
        is parallel to the return value of the `roots` property.

        :return: the orders of the roots calculated by this finder
        """

    @property
    @abstractmethod
    def container(self) -> RootContainer:
        """
        Return the container instance managing the roots of this finder.

        :return: the container of this finder
        """

    def setRootFilter(
        self, filterType: FilterTypes, *, threshold: int = 3
    ) -> None:
        """
        Add a filter of type `filterType` to the set of filters which
        found roots are checked against.

        :param filterType: the type of root filter to add
        :param threshold: the threshold for function on root evaluation filters
        """
        ContainerFactory.registerPreDefinedFilter(
            self.container, filterType, threshold=threshold
        )


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# This script is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# It is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with it. If not, see <http://www.gnu.org/licenses/>.

"""
Import the result segmented building prediction done by the script
pbf_segmented_building_predict.py
into the cadastre database.
"""

import sys
import json
import numpy
import os.path
import psycopg2
from shapely.geometry.polygon import Polygon
import numpy as np;

dbstring = file(os.path.join(os.path.dirname(sys.argv[0]), ".database-connection-string")).read()

db = psycopg2.connect(dbstring)
db.autocommit = True
cur = db.cursor()

def execute(query):
    print(query)
    return cur.execute(query)

def polygon_wkt(latlngs):
    # Restrict to 7 digits precision as in OSM database.
    return "POLYGON((" + ",".join(["%.7f %.7f" % tuple(ll) for ll in latlngs]) + "))"

def wkt_polygon_latlngs(wkt):
    assert(wkt.startswith("POLYGON((") and wkt.endswith("))"));
    coords = wkt[len("POLYGON(("): -len("))")];
    return [list(map(float,p.split(" "))) for p in  coords.split(",")]

def common_center_wkt(latlngs1, latlngs2):
    commons_points = set(map(tuple, latlngs1)).intersection(set(map(tuple, latlngs2)))
    center = list(map(numpy.mean, list(zip(*commons_points))))
    return "POINT(%.7f %.7f)" % tuple(center)

def latlngs_equals(latlngs1, latlngs2):
    if len(latlngs1) == len(latlngs2):
        diff = np.array(latlngs1) - np.array(latlngs2)
        return np.max(np.abs(diff)) < 0.0000001
    else:
        return False

def insert(data):
    id1 = data[0]['id']
    id2 = data[1]['id']
    assert(id1 < id2);
    latlngs1 = data[0]['latlngs']
    latlngs2 = data[1]['latlngs']
    already_exists = False
    execute("""
        SELECT id, ST_AsText(way1_geom), ST_AsText(way2_geom), resolution
        FROM segmented_cases
        WHERE way1_osm_id = %s AND way2_osm_id = %s;
        """ % (id1, id2));
    for id, geom1, geom2, resolution in cur.fetchall():
        geom1 = wkt_polygon_latlngs(geom1)
        geom2 = wkt_polygon_latlngs(geom2)
        if latlngs_equals(latlngs1, geom1) and latlngs_equals(latlngs2, geom2):
            already_exists = True
        elif resolution == 'none':
            # The geometry of the building has changed,
            # mark the previous case as 'outofdate':
            execute("""
                UPDATE segmented_cases
                SET resolution='outofdate', resolution_time=now()
                WHERE id=%s""" % id);
    if not already_exists:
        execute("""
            INSERT INTO segmented_cases
                (way1_osm_id, way1_geom, way2_osm_id, way2_geom, center, creation_time)
                VALUES (%d, ST_GeomFromText('%s', 4326), %d, ST_GeomFromText('%s', 4326), ST_GeomFromText('%s', 4326), now());
            """ % (id1, polygon_wkt(latlngs1), id2, polygon_wkt(latlngs2), common_center_wkt(latlngs1, latlngs2)))

def main(args):
    for line in sys.stdin.readlines():
        data = json.loads(line)
        insert(data)

if __name__ == '__main__':
    main(sys.argv[1:])


from typing import List

class Solution:
    def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
        m, n = len(board), len(board[0])
        next_state = [row[::] for row in board]
        dxy = [[0, 1], [1, 0], [0, -1], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]]

        def reveal(r, c):

            adj_revealed_mine = adj_unrevealed_mine = 0
            for dx, dy in dxy:
                nr, nc = r + dx, c + dy
                if 0 <= nr < m and 0 <= nc < n:
                    if next_state[nr][nc] == 'X':
                        adj_revealed_mine += 1
                    if next_state[nr][nc] == 'M':
                        adj_unrevealed_mine += 1
            total_mines = adj_revealed_mine + adj_unrevealed_mine
            if total_mines == 0:
                next_state[r][c] = 'B'
                for dx, dy in dxy:
                    nr, nc = r + dx, c + dy
                    if 0 <= nr < m and 0 <= nc < n and next_state[nr][nc] == 'E':
                        reveal(nr, nc)
            else:
                next_state[r][c] = str(total_mines)

        cr, cc = click
        if board[cr][cc] == 'M':
            next_state[cr][cc] = 'X'
        else:
            reveal(cr, cc)
        return next_state


from datetime import datetime

from django.conf import settings
from django.db import transaction
from django.utils import timezone

from .utils import Harvest

def make_item_key(item):
    return "{}:{}".format(item.category.name.lower(),
                          item.description.lower())

class HarvestDefaultHookset(object):

    @transaction.atomic
    def update_project_line_item_times(self, api_credentials, project_to_update):
        if not project_to_update.categories.all().exists():
            return

        harvest = Harvest(access_token=api_credentials['access_token'],
                          account_id=api_credentials.get('account_id', None),
                          client_id=settings.HARVEST_CLIENT_ID,
                          client_secret=settings.HARVEST_CLIENT_SECRET,
                          refresh_token=api_credentials.get('refresh_token', None),
                          tokens_last_refreshed_at=api_credentials.get('tokens_last_refreshed_at', None))

        # Right now we are assuming that every project has a unique name
        # Note: Toggl requires a workspace id to get a detailed report
        # so we need to grab the one associated with the project
        harvest_project = None
        for project in harvest.projects():
            if project.name == project_to_update.name:
                harvest_project = project
                break
        if harvest_project is None:
            return

        # Get tasks that correspond to our categories
        all_tasks = harvest_project.task_assignments
        project_to_update_categories = project_to_update.categories.all()
        category_names = {category.name.lower() for category
                          in project_to_update_categories}
        ids_for_tasks_that_match_categories = []
        for task_data in all_tasks:
            task = task_data.task
            if task.name.lower() in category_names:
                ids_for_tasks_that_match_categories.append(task.id)

        # Grab all the time entires over the past year
        # for the project we want to update
        time_entries = project.entries()

        # Add up the durations for all of the line items
        # whose descriptions match the descriptions of our
        # project's line items.
        project_to_update_line_items = []
        for category in project_to_update_categories:
            line_items = category.items.all()
            if line_items.exists():
                project_to_update_line_items += list(line_items)
        if not project_to_update_line_items:
            return

        line_items = {make_item_key(item) : item for item
                      in project_to_update_line_items}
        line_item_totals = {make_item_key(item): 0
                            for item in project_to_update_line_items}

        for time_entry in time_entries:
            time_entry_task_name = time_entry.task.name.lower()
            item_key = "{}:{}".format(time_entry_task_name,
                                      time_entry.notes.lower())
            if item_key in line_item_totals:
                total = line_item_totals[item_key]
                total+= time_entry.hours
                line_item_totals[item_key] = total

        for item_key, total in line_item_totals.items():
            line_item = line_items[item_key]
            line_item.actual = total
            line_item.save()

        project_to_update.last_imported_date = timezone.make_aware(datetime.now())
        project_to_update.save()

class HookProxy(object):

    def __getattr__(self, attr):
        return getattr(HarvestDefaultHookset, attr)

hookset = HookProxy()


from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from audio_activity_detection.data_loader import parse_data
from collections import namedtuple

FS = 22050  # sampling rate in [Hz]
TEN_MS = 10 / 1000  # 10 milliseconds
IF = 55  # 55 zero crossings per 10 ms (one frame)
THRESHOLD = namedtuple('THRESHOLD', 'IE, ste_mean, ste_std, MINSTE, T_lower, T_upper, IF, stzcr_mean, stzcr_std, T_zc')
MI5 = 5  # multiple of 5 frames, intotal 50 ms
MI10 = 10

class aad(object):
    """ Audio activity detection """
    def __init__(self, file_name, fs):
        self.file_name = file_name
        self.fs = fs
        self.frame_length_10ms = self.nSamples_ms(period=TEN_MS)  # frame length in samples
        self.ste_section = np.empty(self.frame_length_10ms) * np.nan
        # period of calculation of statistics for coarse search. 50 ms period (5 frames)
        self.stat_coarse_section = np.empty(self.frame_length_10ms * MI5) * np.nan
        self.stzcr_section = np.empty(self.frame_length_10ms * MI10) * np.nan  # no more than 10 frames
        self.pointer = 0
        self.signal_channel_2 = self.show_data()
        self.threshold_found = False  # has noise level (silence period) been known
        self.threshold = THRESHOLD
        self.coarse_Tl_found = False  # lower threshold in the coarse start search is found
        self.coarse_Tu_found = False  # upper threshold in the coarse start search is found
        self.coarse_start_candidate = None
        self.coarse_start = None
        self.fine_start = None
        self.coarse_end = None
        self.fine_end = None
        self.start_found = False
        self.coarse_end_found = False
        self.fine_end_found = False
        self.check_ste = []
        self.check_zcr = []

    def threshold_init(self):
        # thresholds for STE
        self.threshold.IE = 0.25
        self.threshold.ste_mean = np.mean(self.stat_coarse_section)  # mean of the signals in STE section
        self.threshold.ste_std = np.std(self.stat_coarse_section)  # standard deviation of the signals in STE section
        self.threshold.MINSTE = min(self.threshold.IE, self.threshold.ste_mean + self.threshold.ste_std)
        self.threshold.T_lower = 8 * self.threshold.MINSTE
        self.threshold.T_upper = 32 * self.threshold.MINSTE

        # thresholds for STZCR
        zcr_list = np.array(self.obtain_zcr(self.stat_coarse_section))
        self.threshold.IF = 0.25  # (number of zc) / (number of samples in one frame)
        self.threshold.stzcr_mean = np.mean(zcr_list)
        self.threshold.stzcr_std = np.std(zcr_list)
        self.threshold.T_zc = min(self.threshold.IF, self.threshold.stzcr_mean + self.threshold.stzcr_std)

        self.threshold_found = True

    def nSamples_ms(self, period=TEN_MS):
        """ Set number of samples for 10ms and ensure that the output is even.

        Args:
            period: the time period to be calculated [ms]
            fs: sampling rate [Hz]

        Returns:
            number of number of samples for 10ms

        """
        tmp_len = int(period * self.fs)
        if tmp_len % 2 != 0:
            tmp_len = tmp_len - 1
        return tmp_len

    def show_data(self):
        sound_data = parse_data(self.file_name)
        # return sound_data[30000:76000, 1]
        return sound_data[30000:300000, 1]

    def update_ste_section(self, overlap_length):
        self.ste_section[:overlap_length] = self.ste_section[
                                            overlap_length:]  # replace the 1st half section by the 2nd half
        self.ste_section[overlap_length:] = self.signal_channel_2[
                                            self.pointer:self.pointer + overlap_length]  # load 5ms data to the 1st half

    def update_stzcr_section(self, overlap_length):
        self.stzcr_section[:(self.frame_length_10ms * MI10 - overlap_length)] = self.stzcr_section[overlap_length:]
        self.stzcr_section[(self.frame_length_10ms * MI10 - overlap_length):] = \
            self.signal_channel_2[self.pointer:self.pointer + overlap_length]

    def update_stat_coarse_section(self, overlap_length):
        self.stat_coarse_section[:(self.frame_length_10ms * MI5 - overlap_length)] = self.stat_coarse_section[overlap_length:]
        self.stat_coarse_section[(self.frame_length_10ms * MI5 - overlap_length):] = \
            self.signal_channel_2[self.pointer:self.pointer + overlap_length]

    def update_sections(self):
        """ Update Short-term Energy (STE) section. """
        overlap_length = int(self.frame_length_10ms / 2)  # overlap length in samples
        self.update_ste_section(overlap_length)
        self.update_stzcr_section(overlap_length)

        # if 50 ms initialization data are not fullfilled, then keep adding
        if np.sum(np.isnan(self.stat_coarse_section)) > 0:
            self.update_stat_coarse_section(overlap_length)
        elif not self.threshold_found:
            self.threshold_init()  # calculating all threshold values

        self.pointer = self.pointer + overlap_length  # update pointer to the next beginning for STE use

        if np.sum(np.isnan(self.ste_section)) > 0:
            return False
        else:
            return True

    @staticmethod
    def cal_zcr(d):
        """ Calculation of zero crossing rate. """
        if not isinstance(d, np.ndarray):
            d = np.array(d)
        diff = np.sign(d[1:]) - np.sign(d[:-1])
        print('what:{}, d:{}'.format(np.sum(np.abs(diff)), (len(d) * 2)))
        return np.sum(np.abs(diff)) / (len(d) * 2)

    def obtain_zcr(self, d):
        d = d - np.mean(d)
        stzcr_nan_removal = d[(~np.isnan(d)).tolist()]  # remove NaN
        zcr = []
        for i in range(int(len(stzcr_nan_removal)/self.frame_length_10ms)):
            tmp = stzcr_nan_removal[i*self.frame_length_10ms:(i+1)*self.frame_length_10ms]
            zcr.append(self.cal_zcr(tmp))
        return zcr

    def find_fine_start(self):
        lock = True
        zcr_list = np.array(self.obtain_zcr(self.stzcr_section))  # remember that zcr is flipped in [latest ...  oldest]
        tmp = np.flip(np.where(zcr_list - self.threshold.T_zc > 0)[0], axis=0)  # find index of zcr above the threshold and flip around
        if len(tmp) < 3:
            self.fine_start = self.coarse_start
        else:
            for i in range(2, len(tmp)):
                if lock:
                    if tmp[i-2] - tmp[i] == 2:
                        self.fine_start = self.coarse_start - (9-tmp[i])*self.frame_length_10ms
                        lock = False
                    # the last index and still no fine_start is found, then assign coarse_start to it
                    elif i == len(tmp) - 1:
                        self.fine_start = self.coarse_start
                        continue
                elif tmp[i-1] - tmp[i] == 1:
                    self.fine_start = self.fine_start - self.frame_length_10ms
                else:
                    self.fine_start = self.coarse_start
                    break

    def find_fine_end(self, consecutive3, consecutive3flag, i_max10, zcr_value):

        if i_max10 < 10:
            if consecutive3flag:
                if zcr_value[0] > self.threshold.T_zc:
                    self.fine_end = self.pointer
            else:
                if zcr_value[0] > self.threshold.T_zc:  # only one frame, so single value is expeced
                    consecutive3 = consecutive3 + 1
                    if consecutive3 == 3:
                        consecutive3flag = True
            i_max10 = i_max10 + 1
        else:
            self.fine_end_found = True
        return consecutive3, consecutive3flag, i_max10

    def find_coarse_start_end(self, ste_value):

        if not self.coarse_start:
            if (not self.coarse_Tl_found) and (ste_value > self.threshold.T_lower):
                self.coarse_start_candidate = self.pointer
                self.coarse_Tl_found = True
            elif self.coarse_Tl_found and (ste_value < self.threshold.T_lower):
                self.coarse_Tl_found = False
                self.coarse_start_candidate = None
            elif self.coarse_Tl_found and (ste_value > self.threshold.T_upper):
                self.coarse_start = self.coarse_start_candidate - 1 * self.frame_length_10ms  # due to initialization
                self.coarse_Tl_found = False
                self.find_fine_start()
        else:
            if (not self.coarse_Tu_found) and (ste_value < self.threshold.T_upper):
                self.coarse_Tu_found = True
            elif self.coarse_Tu_found and (ste_value < self.threshold.T_lower):
                self.coarse_Tu_found = False
                self.coarse_end = self.pointer

    def audio_activity_detection(self):
        # Loop over the signal
        consecutive3 = 0
        consecutive3flag = False
        i_max10 = 0
        while True:
            if not self.update_sections():
                continue

            ste_value = np.sum(np.abs(self.ste_section)) / 220  # STE value of 10ms data
            zcr_value = self.obtain_zcr(self.ste_section)
            self.check_ste.append(ste_value)
            self.check_zcr.append(zcr_value)

            if (not self.coarse_start or not self.coarse_end) and self.threshold_found:
                self.find_coarse_start_end(ste_value)

            if self.coarse_end:
                consecutive3, consecutive3flag, i_max10 = self.find_fine_end(consecutive3, consecutive3flag, i_max10, zcr_value)

            if self.pointer + (self.frame_length_10ms/2) > len(self.signal_channel_2):
                break

if __name__ == '__main__':

    file_name = 'IN_D1_FWC_S5_20170810_111645.snd'
    fs = 22050  # sampling rate

    kwd = aad(file_name=file_name, fs=fs)  # keyword detection
    kwd.audio_activity_detection()  # find utterance, beginning and ending point

    plt.figure()
    plt.subplot(211)
    plt.plot(kwd.signal_channel_2, 'b')
    plt.plot([kwd.coarse_start, kwd.coarse_start], [-0.1, 0.1], 'r')
    plt.plot([kwd.fine_start, kwd.fine_start], [-0.1, 0.1], 'm')
    plt.plot([kwd.coarse_end, kwd.coarse_end], [-0.1, 0.1], 'r')
    plt.plot([kwd.fine_end, kwd.fine_end], [-0.1, 0.1], 'm')
    plt.xlim([0, 40000])
    plt.grid()
    plt.subplot(212)
    plt.plot(np.array(range(len(kwd.check_ste))) * kwd.frame_length_10ms * 0.5, kwd.check_ste, 'bo')
    plt.plot(np.array(range(len(kwd.check_zcr))) * kwd.frame_length_10ms * 0.5, kwd.check_zcr, 'go-')
    plt.plot([kwd.coarse_start, kwd.coarse_start], [-0.1, 0.1], 'r')
    plt.plot([kwd.fine_start, kwd.fine_start], [-0.1, 0.1], 'm')
    plt.plot([kwd.coarse_end, kwd.coarse_end], [-0.1, 0.1], 'r')
    plt.plot([kwd.fine_end, kwd.fine_end], [-0.1, 0.1], 'm')
    plt.xlim([0, 40000])
    plt.grid()
    plt.show()


import os
import random
import socket
import time
import traceback
from threading import Thread

from dependencies import LiveTransmitter
from dependencies import fileService as fService
from dependencies import messageService as msgService
from dependencies import socketConnect as sockConnService

client_and_nickname_by_address_dict = dict()
client_by_id_dict = dict()
file_process_queue = dict()
client_dest_file = []
W_transmission = None
broadcaster_dic = dict()

server_feed = None

def Check_video_feed(Class_video, client_by_id_dict):
    while True:
        if Class_video.server_is_running == False:
            clients = []
            for cl in client_by_id_dict:
                clients.append(client_by_id_dict[cl])
            request = str({'service': 'video_feed', 'type': 'stoped'}).encode()
            msgService.Broadcast(request, clients)
            break

def ReceptionRoom():
    while True:
        global server_socket, client_and_nickname_by_address_dict, client_by_id_dict, broadcaster_dic
        try:
            client_socket, address_tupple = server_socket.accept()

            # save client informations
            id_c = len(client_by_id_dict)
            client_by_id_dict[id_c] = client_socket
            client_and_nickname_by_address_dict[address_tupple] = ("Unknown", client_socket)
            broadcaster_dic[address_tupple] = (False, (None, None))

            # start exchange with the client
            print("\033[92m[ReceptionRoom] New client : {}:{} ! \033[0m".format(address_tupple[0], address_tupple[1]))
            Thread(target=ClientHandler, args=(id_c, address_tupple, client_socket)).start()

        except Exception as e:
            print("\033[32m[ReceptionRoom] Error {}\033[0m".format(e))
            break

def ClientHandler(id_c, address, client_socket):
    while True:
        global client_and_nickname_by_address_dict, client_by_id_dict, client_dest_file

        try:

            # get the request and transform it to a dict
            raw_q = client_socket.recv(1024)
            try:
                req_d = eval(raw_q)
                print(req_d)
            except Exception as e:
                print("\033[31m [ClientHandler.raw_q] Error : {}\033[0m".format(e))
                req_d = {'service': 'None caused by an error'}

            # Message Service
            if req_d['service'] == 'message':

                if req_d['type'] == 'global':  # private message
                    clients = []
                    for cl in client_by_id_dict:
                        clients.append(client_by_id_dict[cl])
                    request = str({'service': 'message', 'type': 'global', 'content': req_d['content'],
                                   'from_client': client_and_nickname_by_address_dict[address][0]}).encode()
                    msgService.Broadcast(request, clients)

                if req_d['type'] == 'private':  # global message
                    client_dest = client_and_nickname_by_address_dict[eval(req_d['client_dest_address'])][1]
                    request = str({'service': 'message', 'type': 'private', 'content': req_d['content'],
                                   'from_client': client_and_nickname_by_address_dict[address][0]}).encode()
                    client_dest.send(request)

            # File Service
            # ajouter un token unique par téléchargement (un aléatoire par destination de client)
            if req_d['service'] == 'file':

                if req_d['type'] == 'receive':  # receive and distribute the message

                    fService.FileReceiver(client_socket, req_d['file_name'], req_d['BUFFER'], save_pre_ext="server/download/")

                    d = eval(req_d['client_dest_address'])
                    if type(d) == tuple:
                        d = [d]

                    print(d)

                    client_dest_file = []
                    for i in range(len(d)):
                        client_dest_file.append(client_and_nickname_by_address_dict[d[i]][1])

                    request = []
                    global file_process_queue
                    for i in range(len(d)):
                        file_id = random.randint(0, 10000)
                        request.append(str({'service': 'file', 'type': 'getAgree', 'file_name': req_d['file_name'],
                                            'from_client_address': address, 'file_id': file_id,
                                            'BUFFER': req_d['BUFFER']}).encode())
                        file_process_queue[file_id] = (req_d['file_name'], address)
                        print(file_process_queue)

                    # send the agree
                    msgService.Broadcast(request, client_dest_file, unique=True)

                if req_d['type'] == 'agreement':

                    if req_d['command'] == 'Yes':
                        global file_process_queue_dict
                        try:
                            print(file_process_queue[int(req_d['file_id'])][0])
                            print(req_d['file_name'])
                            print(file_process_queue[int(req_d['file_id'])][0] == req_d['file_name'])
                            if file_process_queue[int(req_d['file_id'])][0] == req_d['file_name']:
                                request = str({'service': 'file', 'type': 'receive', 'file_name': req_d['file_name'],
                                               'from_client_address': file_process_queue[int(req_d['file_id'])][1],
                                               'BUFFER': int(req_d['BUFFER']),
                                               'file_size': os.path.getsize("server/download/" + req_d['file_name'])}).encode()
                                print(request)
                                client_socket.send(request)
                                fService.FileSender(client_socket, "server/download/" + req_d['file_name'], req_d['file_name'],
                                                    req_d['BUFFER'])
                                del file_process_queue[int(req_d['file_id'])]
                                print(file_process_queue)

                            else:
                                print("[ClientHandler.fileService] file_process_queue_dict error")
                                print("Original queue : {}".fomat(file_process_queue))
                                print("File id and file_name received {} | {}".format(req_d['file_id'],
                                                                                req_d['file_name']))
                        except Exception as e:
                            print(e)
                    else:
                        try:
                            del file_process_queue[int(req_d['file_id'])]
                        except:
                            print("file process queue del error")

            # Nicknames Service
            if req_d['service'] == 'nicknames':

                if req_d['type'] == 'update':
                    client_and_nickname_by_address_dict[address] = (req_d['content'], client_socket)

                if req_d['type'] == 'get_IPs_and_nicknames':

                    nickname_by_address_dict = dict()
                    for client_address in client_and_nickname_by_address_dict:
                        nickname_by_address_dict[client_address] = client_and_nickname_by_address_dict[client_address][
                            0]

                    request = str({'service': 'nicknames', 'type': 'receive_nicknames',
                                   'content': nickname_by_address_dict}).encode()
                    client_socket.send(request)

                if req_d['type'] == 'get_my_own':
                    request = str({'service': 'nicknames', 'type': 'get_my_own', 'content': str(address)}).encode()
                    client_socket.send(request)

            # Video_feed Service
            if req_d['service'] == 'video_feed':

                if req_d['type'] == 'start_streaming':
                    global server_feed, ip, W_transmission, broadcaster_dic

                    # send a request for refresh nicknames
                    clients = []
                    for cl in client_by_id_dict:
                        clients.append(client_by_id_dict[cl])
                    request = str({'service': 'nicknames', 'type': 'order_to_refresh', }).encode()
                    msgService.Broadcast(request, clients)

                    image_bytes_socket_port = sockConnService.found_free_port()  # search a free port for stream the video
                    image_bytes_socket_address = (ip, image_bytes_socket_port)
                    print(image_bytes_socket_address)

                    web_handler_socket_port = sockConnService.found_free_port(
                        different_of=image_bytes_socket_port)  # search a free port for stream the video
                    web_handler_socket_address = (ip, web_handler_socket_port)
                    print(web_handler_socket_address)

                    # server
                    W_transmission = LiveTransmitter.Web_Server(LiveTransmitter.ImageSource.Screen, scale=1)
                    W_transmission.connect([image_bytes_socket_address, web_handler_socket_address],
                                           type_of_conn=LiveTransmitter.Web_Server.Master,
                                           mode=LiveTransmitter.Web_Server.distributor)

                    request = str({'service': 'video_feed', 'type': 'streaming_port',
                                   'image_bytes_socket_address': image_bytes_socket_address,
                                   'web_handler_socket_address': web_handler_socket_address}).encode()
                    client_socket.send(request)
                    print("W.start()")
                    W_transmission.start()

                    # check if the Video feed is running and order to the GUIs to close it when it's off
                    Thread(target=Check_video_feed, args=(W_transmission, client_by_id_dict)).start()

                    # put the user in the broadcaster dict
                    global broadcaster_dic
                    broadcaster_dic[address] = (True, web_handler_socket_address)

                    time.sleep(1)

                    # send the video feed link
                    clients = []
                    for cl in client_by_id_dict:
                        clients.append(client_by_id_dict[cl])
                    request = str({'service': 'video_feed', 'type': 'live_link',
                                   'content': [web_handler_socket_address[0], web_handler_socket_address[1]],
                                   'from_client': client_and_nickname_by_address_dict[address][0],
                                   'from_address': address}).encode()
                    msgService.Broadcast(request, clients)

                if req_d['type'] == 'end_streaming':
                    if broadcaster_dic[address][0] == True:
                        W_transmission.shutDown()
                        broadcaster_dic[address] = (False, (None, None))
                    else:
                        print("broadcast_dict doesn't match with the address")

                if req_d['type'] == 'check_is_broadcasting':
                    request = str({'service': 'video_feed', 'type': 'check_is_broadcasting', 'content':broadcaster_dic[address][0], 'web_address':broadcaster_dic[address][1]}).encode()
                    client_socket.send(request)

                    # send the port

        # del the client
        except Exception as e:
            traceback.print_exc()
            print("\033[31m [ClientHandler] Error : {}".format(e))
            client_socket.close()
            del client_and_nickname_by_address_dict[address]
            del client_by_id_dict[id_c]
            broadcaster_dic[address] = (False, (None, None))
            print("[ClientHandler] Client {} succesfully disconnected ! \033[0m")
            break

# clean the download server path:
for f in os.listdir("server\\download\\"):
    os.remove(os.path.join("server\\download\\", f))

# connect the server
print("launch start")
while True:
    port = random.randint(1000, 9999)
    port = 8081
    ip = socket.gethostbyname(socket.gethostname())
    server_socket = sockConnService.ServerConnect(ip, port)

    if server_socket != "error":
        Thread(target=sockConnService.winMessage, args=("infoConn", ip, port)).start()
        break

# launch the server
Thread(target=ReceptionRoom).start()


from pybricks import ev3brick as brick
from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor)
from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align)
from pybricks.tools import print, wait, StopWatch
from pybricks.robotics import DriveBase
from portHelper import PortHelper
from simple_pid.PID import PID
from debug import debug
from speed import SpeedThread
from sensorMotorThread import SensorMotorThread
from pidThread import PidThread
from reden import Reden
from oszilationDetector import OszilationDetector

class Roboter():

    def __init__(self,
                radDurchmesser: int=56,
                achsenAbstand: int=130,
                motorRechts:Motor = None,
                motorLinks:Motor = None,
                sensorMotor:Motor = None,
                speed:int=80,
                speedThread=None): # SpeedThread cannot be imported due to cyclic imports

        self.speed = speed
        self.steuer = 0
        self.gyro=PortHelper.getSensor(GyroSensor)
        if self.gyro:
            self.gyro.reset_angle(0)
        self._us = None
        self._cs = None
        self.motorRechts = motorRechts
        self.motorLinks = motorLinks
        self.sensorMotor = sensorMotor
        self.speedThread=speedThread
        if speedThread:
            speedThread.roboter = self
        motors = PortHelper.getMotors()
        if not (self.motorRechts and self.motorLinks) and self.gyro:
            # gyrosensor um die richitgen motoren zu finden
            checkDegs=30
            checkSpeed=300
            for m in motors:
                self.gyro.reset_angle(0)
                m.run_angle(checkSpeed,checkDegs)
                angle = self.gyro.angle()
                debug("Motorfind: angle {}".format(angle))
                if angle > 0:
                    print("Rechter Motor","{}".format(m).split("\n")[2].replace("\t",""))
                    debug(m,level=5)
                    self.motorRechts = m
                elif angle < 0:
                    print("Linker Motor","{}".format(m).split("\n")[2].replace("\t",""))
                    debug(m,level=5)
                    self.motorLinks = m
                else:
                    print("Sensor Motor","{}".format(m).split("\n")[2].replace("\t",""))
                    debug(m,level=5)
                    self.sensorMotor = m
                m.run_angle(-1*checkSpeed,checkDegs)
                #m.run_until_stalled()

        if not (self.motorRechts and self.motorLinks):
            debug("Motoren raten")
            self.motorRechts = motors[0]
            self.motorLinks  = motors[1]

        self.driveBase = DriveBase(self.motorLinks, self.motorRechts, radDurchmesser, achsenAbstand)

        debug("Robot initialised")
        #self.kraft = 30

    @property
    def cs(self):
        if not self._cs:
            self._cs = PortHelper.getSensor(ColorSensor)
            if self._cs:
                print("New ColorSensor: ambient {} color {} reflection {} rgb {}".format(self._cs.ambient(),self._cs.color(),self._cs.reflection(),self._cs.rgb()))
        if not self._cs:
            print("No ColorSensor found")
        return self._cs

    @property
    def us(self):
        if not self._us:
            self._us = PortHelper.getSensor(UltrasonicSensor)
            if self._us:
                print("New UltrasonicSensor: distance {} presence {}".format(self._us.distance(),self._us.presence()))
        if not self._us:
            print("No UltrasonicSensor found")
        return self._us

    def zeigGyro(self):
        if self.gyro:
            print("Gyro: Speed {} Angle {}".format(self.gyro.speed(),self.gyro.angle()))
        else:
            print("No Gyrosensor")

    @property
    def kraft(self):
        return self._kraft

    @kraft.setter
    def kraft(self, kraft:int):
        self._kraft = kraft
        self.motorLinks.dc(kraft)
        self.motorRechts.dc(kraft)

    @property
    def speed(self):
        return self._speed

    @speed.setter
    def speed(self, speed:int):
        self._speed = speed
        print("Set speed ",self._speed)

    @property
    def steuer(self):
        return self._stearing

    @steuer.setter
    def steuer(self,stearing:float):
        self._stearing = stearing
        print("Set stearing ",self._stearing)

    def drive(self, speed:float=None, stearing:float=None, time:int=None):
        if speed == None:
            speed = self.speed
        if stearing == None:
            stearing = self.steuer
        if time:
            self.driveBase.drive_time(speed,stearing,time)
        else:
            self.driveBase.drive(speed,stearing)

    def drehen(self,winkel:int,fehler:int=0):
        self.gyro.reset_angle(0)
        self.drehenAufWinkel(winkel)

    def drehenAufWinkel(self, winkel:int, fehler:int=0):
        winkel=-1*winkel
        winkelPid=PID(-5,0,0,winkel, output_limits=(-50,50))
        angle = self.gyro.angle()
        while  abs(winkel - angle) > fehler:
            stear = winkelPid(angle)
            if stear < 5:
                stear*=3
            self.drive(0,stear)
            debug("drehenAufWinkel: ziel {} angle {} stear {}".format(winkel, angle,stear),level=2)
            angle = self.gyro.angle()
            #wait(10)
        debug("drehenAufWinkel: ziel {} ist {}".format(winkel, angle ))
        self.stop(Stop.BRAKE)

    def ausweichen(self):
        # if self.us and self.us.distance() < 2550:
        #     self.__ausweichen_pid()
        # else:
            self.__ausweichenSimpel()

    def __ausweichenPid(self):
        pid=PID(1,0,0,2551,None)
        sw = StopWatch()
        while 1 or sw.time() < 13000:
            a = pid(self.us.distance())
            debug("PID ausweichen: Steuer {} dist {}".format(a,self.us.distance()))
            self.drive(0,a)
            wait(100)

    def __ausweichenSimpel(self):
        if not self.speed == 0:
            speed=self.speed*-1
            time=abs(100/speed)
            time*=1000
            print("Ausweichen: speed {} time {}".format(speed,time))
            self.drive(speed,0,time)
            self.drive(0,30,3000)

    def stop(self,action:Stop=Stop.BRAKE):
        self.driveBase.stop(action)

    def linieFolgenThread(self, tuningsStear=None,tuningsSpeed=None,oszilationDetector:OszilationDetector=None):
        debug("linieFolgen")
        pidThread=PidThread(input=self.cs.reflection,robot=self, oszilationDetector=oszilationDetector)
        if tuningsStear:
            debug("Custon stear tunings: {}".format(tuningsStear))
            pidThread.pidStear.tunings = tuningsStear
        if tuningsSpeed:
            debug("Custon speed tunings: {}".format(tuningsSpeed))
            pidThread.pidSpeed.tunings = tuningsSpeed

        pidThread.start()
        while 1:
            self.drive(stearing=pidThread.stear, speed=pidThread.speed)
            #wait(5)

    def linieFolgen(self):
        debug("linieFolgen")
        baseSpeed=60
        targetColor=self.cs.reflection()
        debug("Target color ",targetColor)
        self.drive(0,40,1000)
        linksColor=self.cs.reflection()
        linksTresh = abs(targetColor - linksColor) / 3
        debug("linksColor {} tresh {} ".format(linksColor,linksTresh))
        self.drive(0,-40,2000)
        rechtsColor=self.cs.reflection()
        rechtsTresh =  abs(targetColor - rechtsColor) / 3
        debug("rechtsColor {} tresh {} ".format(rechtsColor,rechtsTresh))
        self.drive(0,40,1000)
        pidStear = PID(Kp=-2.5,Ki=-0.,Kd=0.1, setpoint=targetColor, output_limits=(-160,160))
       # pidStear.tunings = (-8.340000000000002, -28.70912220309812, -0.6056925)

        spd=baseSpeed
        lastStear = 0
        while 1:
            color=self.cs.reflection()
            stear = round(pidStear(color))
            if (abs(color - linksColor) < linksTresh or abs(color - rechtsColor) < rechtsTresh) and abs(stear) > 10:
                if spd > baseSpeed/2:
                    self.stop(Stop.BRAKE)
                    brick.sound.beep()
                    print("**** Drive back: {} {} {}".format(-1*spd,lastStear,pidStear.dt*1000))
                    self.driveBase.drive_time(-1*spd,-lastStear,pidStear.dt*1000)
                spd=0
            else:
                spd+=3
                if spd > baseSpeed:
                    spd = baseSpeed
            debug(level=2,showOnBrick=False, msg="stear {} speed {} color {} target {} error {} {}".format(stear, spd, color, targetColor,abs(color - linksColor),abs(color - rechtsColor)))
            self.drive(stearing=stear, speed=spd)
            lastStear = stear

    def rumFahren(self):
        baseSpeed=self.speed
        self.steuer=0
        debug("rumFahren started: speed {}".format(baseSpeed))
        if not self.speedThread:
            self.speedThread = SpeedThread(roboter=self)
        self.speedThread.start()
        if self.sensorMotor:
            sensorMotorThread=SensorMotorThread(self.sensorMotor)
            sensorMotorThread.start()
        while 1:
            self.drive()
            if self.speedThread and self.speedThread():
                brick.sound.beep()
                self.ausweichen()

            if self.us and self.us.distance() < self.speed:
                self.stop()
                brick.sound.file(SoundFile.DETECTED)
                self.ausweichen()

            if self.cs and self.cs.color() is None:
                self.stop()
                brick.sound.file(SoundFile.OUCH)
                self.ausweichen()

            btns = brick.buttons()
            while any(btns):
                self.stop()
                if Button.CENTER in btns:
                    self.steuer = 0
                    self.speed = baseSpeed
                if Button.UP in btns:
                    self.speed = self.speed + 5
                if Button.DOWN in btns:
                    self.speed = self.speed - 5
                if Button.RIGHT in btns:
                    self.steuer = self.steuer + 1
                if Button.LEFT in btns:
                    self.steuer = self.steuer - 1

                brick.display.clear()
                brick.display.text("Speed {}".format(self.speed), (20,60))
                brick.display.text("Steuer {}".format(self.steuer))
                wait(10)
                btns = brick.buttons()
            wait(10)

        self.speedThread.stop()
        # if self.sensorMotor:
        #     sensorMotorThread.stop()

    def menu(self):
        r=self
        auswahl=[ (r.linieFolgenThread, "thread line follower"),(r.linieFolgen, "line follower"), (lambda : r.linieFolgenThread(oszilationDetector=OszilationDetector()), "healing line follower"), (r.rumFahren, "seaker")]
        i=0
        while 1:
            if i < 0:
                i = len(auswahl) -1
            if not i < len(auswahl):
                i=0
            debug(i)
            code, name = auswahl[i]
            Reden.reden(name,False)
            btn = []
            while not any(btn):
                btn = brick.buttons()
                if Button.CENTER in btn:
                    Reden.reden(name,False)
                    code()
                if Button.LEFT in btn:
                    i+=1
                    break
                if Button.RIGHT in btn:
                    i-=1
                    break
                wait(50)