<reponame>FishwithCat/ERMAO
# coding=UTF-8
from testlib.infrustructure.match.DataTransformer import DataTransformer
from testlib.infrustructure.match.Hungarian import Hungarian

class Match(object):
    def __init__(self, config, request):
        self._config = config
        self._request = request
        self._deviceTypeMap = {}
        self._formatedConfig = self._reformat_config(config)
        self._formatedRequest = self._reformat_request(request)

    def _reformat_config(self, config):
        devices = config['devices']
        if 'links' not in config:
            return devices
        return self._merge_config_link(devices, config['links'])
    
    def _reformat_request(self, request):
        devices = request['devices']
        if 'links' not in request:
            return devices
        return self._merge_release_link(devices, request['links'])
    
    def _merge_config_link(self, devices, links):
        for linkPair in links:
            linkPair.sort(key=lambda id: self._get_device_type(devices, id))
            devices.append({
                'id': tuple(linkPair),
                'type': tuple([self._get_device_type(devices, linkPair[0]), 
                            self._get_device_type(devices, linkPair[1])])
            })
        return devices
    
    def _merge_release_link(self, devices, links):
        deviceTypeMap = {}
        for linkPair in links:
            linkPair.sort(key=lambda id: self._get_device_type(devices, id))
            devices = self._remove_request_device_used_in_link(devices, linkPair)
            devices.append({
                'id': tuple(linkPair),
                'type': tuple([self._get_device_type(devices, linkPair[0]), 
                            self._get_device_type(devices, linkPair[1])])
            })
        return devices

    def _get_device_type(self, devices, deviceId):
        if deviceId not in self._deviceTypeMap:
            device = self._get_device_info(devices, deviceId)
            self._deviceTypeMap[deviceId] = device['type']
        return self._deviceTypeMap[deviceId]

    def _get_device_info(self, devices, deviceId):
        deviceList = list(filter(lambda device : device['id'] == deviceId, devices))
        if len(deviceList) == 0:
             return None
        return deviceList[0]
    
    def _remove_request_device_used_in_link(self, devices, linkPair):
        deviceA, deviceB = linkPair
        return list(filter(lambda device: device['id'] != deviceA and device['id'] != deviceB, devices))
    
    def match(self):
        adjacencyList = DataTransformer.generate_adjacency_list(self._formatedConfig, self._formatedRequest)
        matchResult = Hungarian(adjacencyList, len(self._formatedConfig)).doMatch()
        if -1 in matchResult:
            return None
        return self._extract_match_result(matchResult)
    
    def _extract_match_result(self, matchResult):
        result = {}
        for requestIndex in range(len(matchResult)):
            result.update(self._generate_match(self._formatedRequest[requestIndex], 
                                            self._formatedConfig[matchResult[requestIndex]]))
        return result

    def _generate_match(self, requestDevice, configDevice):
        match = {}
        if type(requestDevice['id']) is tuple:
            for index in range(len(requestDevice['id'])):
                match[requestDevice['id'][index]] = configDevice['id'][index]
        match[requestDevice['id']] = configDevice['id']
        return match
# coding=UTF-8
from testlib.infrustructure.match.DataTransformer import DataTransformer
from testlib.infrustructure.match.Hungarian import Hungarian

class Match(object):
    def __init__(self, config, request):
        self._config = config
        self._request = request
        self._deviceTypeMap = {}
        self._formatedConfig = self._reformat_config(config)
        self._formatedRequest = self._reformat_request(request)

    def _reformat_config(self, config):
        devices = config['devices']
        if 'links' not in config:
            return devices
        return self._merge_config_link(devices, config['links'])
    
    def _reformat_request(self, request):
        devices = request['devices']
        if 'links' not in request:
            return devices
        return self._merge_release_link(devices, request['links'])
    
    def _merge_config_link(self, devices, links):
        for linkPair in links:
            linkPair.sort(key=lambda id: self._get_device_type(devices, id))
            devices.append({
                'id': tuple(linkPair),
                'type': tuple([self._get_device_type(devices, linkPair[0]), 
                            self._get_device_type(devices, linkPair[1])])
            })
        return devices
    
    def _merge_release_link(self, devices, links):
        deviceTypeMap = {}
        for linkPair in links:
            linkPair.sort(key=lambda id: self._get_device_type(devices, id))
            devices = self._remove_request_device_used_in_link(devices, linkPair)
            devices.append({
                'id': tuple(linkPair),
                'type': tuple([self._get_device_type(devices, linkPair[0]), 
                            self._get_device_type(devices, linkPair[1])])
            })
        return devices

    def _get_device_type(self, devices, deviceId):
        if deviceId not in self._deviceTypeMap:
            device = self._get_device_info(devices, deviceId)
            self._deviceTypeMap[deviceId] = device['type']
        return self._deviceTypeMap[deviceId]

    def _get_device_info(self, devices, deviceId):
        deviceList = list(filter(lambda device : device['id'] == deviceId, devices))
        if len(deviceList) == 0:
             return None
        return deviceList[0]
    
    def _remove_request_device_used_in_link(self, devices, linkPair):
        deviceA, deviceB = linkPair
        return list(filter(lambda device: device['id'] != deviceA and device['id'] != deviceB, devices))
    
    def match(self):
        adjacencyList = DataTransformer.generate_adjacency_list(self._formatedConfig, self._formatedRequest)
        matchResult = Hungarian(adjacencyList, len(self._formatedConfig)).doMatch()
        if -1 in matchResult:
            return None
        return self._extract_match_result(matchResult)
    
    def _extract_match_result(self, matchResult):
        result = {}
        for requestIndex in range(len(matchResult)):
            result.update(self._generate_match(self._formatedRequest[requestIndex], 
                                            self._formatedConfig[matchResult[requestIndex]]))
        return result

    def _generate_match(self, requestDevice, configDevice):
        match = {}
        if type(requestDevice['id']) is tuple:
            for index in range(len(requestDevice['id'])):
                match[requestDevice['id'][index]] = configDevice['id'][index]
        match[requestDevice['id']] = configDevice['id']
        return match
# coding=UTF-8