def handle_what(query):
    '''

    :param query:
    :return:
    '''
    # query is either list with one element ('[what] cup'), so we return a object
    # or with two elements ('[what] shape cup'), so we return the attribute of the object as string
    # TODO: filter wrong querries
    name = query[-1]
    obj = retrieve_object_by_identifier(name)
    if type(obj) is not Rcobject:
        if obj is None:
            return 'Failed, did not find an object with name ' + name, 11
        else:
            return 'Failed, did not find an object with name ' + name + ' but an ' + str(
                type(obj)), 12
    if len(query) > 1:
        attr = query[0]
        attribs = {x: obj.__getattribute__(x) for x in obj._fields}
        ans = attribs[attr]
        if type(ans) == float:
            return float_to_xml(ans)
        elif type(ans) == int:
            return int_to_xml(ans)
        elif type(ans) == unicode:
            return str_to_xml(ans.encode('ascii', 'replace'))
        elif type(ans) == Location:
            return str_to_xml(ans.name)
        return 'Failed, type of attribute ' + attr + ' is ' + str(
            type(ans)) + ', and there is no xml-ifier for that!', 13

    return ET.tostring(obj.to_xml()), 0
def handle_where(query):
    '''

    :param query:
    :return:
    '''
    # query is a list with one element, which is the unique identifier of either a location, person, room or
    # object. It may have a second element, which would be a unique identifier for one of many
    # viewpoints a location or room may have
    # TODO: filter wrong querries
    name = query[0]
    viewpoint_name = None
    if len(query) > 1:
        viewpoint_name = query[1]
    entry = retrieve_object_by_identifier(name)

    if not entry:
        return 'Failed! Found no person, location, room or RCObject with name ' + name, 21

    # retrieve annotation of the fetched thingy
    annot = None
    if type(entry) == Room or type(entry) == Location:
        annot = entry.annotation
    elif type(entry) == Person:
        return ET.tostring(
            entry.position.to_xml()), 0  # persons have a position themselves
        #  so we do not need to go over annot
    elif type(entry) == Rcobject:
        annot = entry.location.annotation

    # retrieve viewpoint
    viewpoints = None
    if viewpoint_name:
        viewpoints = [
            vp for vp in annot.viewpoints if vp.label == viewpoint_name
        ]
    else:
        viewpoints = [vp for vp in annot.viewpoints if vp.label == 'main']
    if not viewpoints:
        return 'Failed! Found no viewpoint with name ' + str(
            viewpoint_name), 21

    viewpoint = viewpoints[0]

    return ET.tostring(viewpoint.to_xml()), 0
def handle_who(query):
    '''
    Hander for the question word who. Will return a xml-ified Person.
    :param query:
    :return:
    '''
    # query is list with one element, which is a identifier for a person
    # TODO: filter wrong querries
    name = query[0]
    pers = retrieve_object_by_identifier(name)
    if type(pers) is not Person:
        bdo_types = [type(Rcobject), type(Door), type(Location), type(Room)]
        if pers is None:
            return 'Failed, did not find a Person with name ' + name, 61
        if type(pers) in bdo_types:
            return 'Failed, did not find a Person with name ' + name + ' but an ' + str(
                type(pers)), 62
    return ET.tostring(pers.to_xml()), 0
Beispiel #4
0
def handle_remember(data):
    '''
    Hander for the data word remember. Will save a bdo to the knowledge base.
    :param data:
    :return:
    '''
    # data is list with one element. It is a xml format of a BDO class.
    # TODO: filter wrong querries
    xml_string = data[0]
    xml_tree = ET.fromstring(xml_string.encode('utf-8'))
    try:
        pass
    except Exception:
        print('XML parsing not successful.')
        return False, 91
    available_classes = {
        'persondata': Person,
        'location': Location,
        'room': Room,
        'door': Door,
        'rcobject': Rcobject
    }
    if xml_tree.tag not in available_classes:
        print('Class \"' + xml_tree.tag + '\" is not a valid BDO class')
        return False, 92
    try:
        new_obj = available_classes[xml_tree.tag].from_xml(xml_tree)

        # check for old object with name and delete if possible
        old_obj = retrieve_object_by_identifier(new_obj.name)
        if old_obj is not None:
            print('There already was a ' + xml_tree.tag + ' with name "' +
                  str(new_obj.name) + '", but it was overwritten.')
            if type(new_obj) == type(old_obj):
                # just update the object
                attribs_new = {
                    x: new_obj.__getattribute__(x)
                    for x in new_obj._fields
                }
                attribs_old = {
                    x: old_obj.__getattribute__(x)
                    for x in old_obj._fields
                }
                attribs_new.pop('id')
                modify_query = {}
                debug_print('New attribs: ' + str(attribs_new))
                debug_print('Old attribs: ' + str(attribs_old))
                bla = attribs_new['annotation'].viewpoints
                for attrib in attribs_new:
                    modify_query['set__' + attrib] = attribs_new[attrib]
                debug_print('query: ' + str(modify_query))
                old_obj.update(**modify_query)

                old_obj.reload()
                attribs_old = {
                    x: old_obj.__getattribute__(x)
                    for x in old_obj._fields
                }
                bla = attribs_old['annotation'].viewpoints

                return True, 0
            else:
                handle_forget([new_obj.name])

        new_obj.save()
        if type(new_obj) == Person:
            nbdo = Crowd.objects()[0]
            nbdo.update(add_to_set__persons=[new_obj])
        elif type(new_obj) == Location:
            nbdo = Arena.objects()[0]
            nbdo.update(add_to_set__locations=[new_obj])
        elif type(new_obj) == Room:
            nbdo = Arena.objects()[0]
            nbdo.update(add_to_set__rooms=[new_obj])
        elif type(new_obj) == Door:
            nbdo = Arena.objects()[0]
            nbdo.update(add_to_set__doors=[new_obj])
        elif type(new_obj) == Rcobject:
            nbdo = Rcobjects.objects()[0]
            nbdo.update(add_to_set__rcobjects=[new_obj])
        return True, 0
    except NoSuchLocationException:
        print('Could not find the location specified in BDO')
        return False, 94
    except NoSuchRoomException:
        print('Could not find the room specified in BDO')
        return False, 95
    except Exception:
        print('Error in converting the given xml to a BDO')
        print('Exact Exception: ' + str(traceback.format_exc()))
        return False, 93
Beispiel #5
0
def handle_forget(data):
    '''
    Hander for the data word forget. Will delete a bdo from the knowledge base.
    :param data:
    :param delete_references
    :return:
    '''
    # data is list with one or two elements. if it is of length one, it will contain the unique identifier of the bdo
    # to delete. otherwise the first element shall be "all" and the second either "person(s)", "object(s)", "door(s)",
    # "location(s)" or "room(s)"
    # TODO: filter wrong querries
    if len(data) > 1:  # "all" path
        types = {
            'person': Person,
            'object': Rcobject,
            'rcobject': Rcobject,
            'room': Room,
            'location': Location,
            'door': Door
        }
        if not data[0] == 'all':
            print(
                'More than one element for forget and first element not \"all\"'
            )
            return False, 81
        if data[1] not in types:
            if data[1].endswith('s') and data[
                    1][:-1] in types:  # got plural of type, e.g. persons
                data[1] = data[1][:-1]
            else:
                print('Identification word not in classes allowed to delete!')
                return False, 82
        types[data[1]].objects().delete()
        return True, 0
    else:
        obj = retrieve_object_by_identifier(data[0])
        if obj is None:
            print('No object with identifier \"' + data[0] + '\" found!')
            return False, 83
        obj.delete()
        if type(obj) == Person:
            nbdo = Crowd.objects()[0]
            nbdo.update(pull__persons=obj)
        elif type(obj) == Location:
            nbdo = Arena.objects()[0]
            nbdo.update(pull__locations=obj)
            rcobjects = Rcobject.objects(location=obj)
            for each in rcobjects:
                each.location = None
                each.save()
        elif type(obj) == Room:
            nbdo = Arena.objects()[0]
            nbdo.update(pull__rooms=obj)
            # TODO remove reference from doors and locations
        elif type(obj) == Door:
            nbdo = Arena.objects()[0]
            nbdo.update(pull__doors=obj)
        elif type(obj) == Rcobject:
            nbdo = Rcobjects.objects()[0]
            nbdo.update(pull__rcobjects=obj)
        return True, 0
def handle_in_which(query):
    '''
    query is a list with 3-4 elements for which the second element is always either 'location' or 'room' and the
    third is either the keyword 'point' or a unique identifier of either a location, person, room or object. In the case
    the third element is 'point', a Point2D in xml format should follow as the third element.
    :param query:
    :return:
    '''
    # TODO: filter wrong querries

    # if there is a point in the query, parse it into point2D
    point = None
    if len(query) > 2 and query[1] == 'point':
        point = Point2d.from_xml(ET.fromstring(query[2]))

    # retrieve thingy by identifier if we dont already have a point
    if not point:
        entry = retrieve_object_by_identifier(query[1])
        if not entry:
            return 'Failed! Found no person, location, room or RCObject with name ' + query[
                1], 31

        # now there are 4 possibilities: we have retrieved a person (->point), location, room or object
        if type(entry) == Person:
            point = entry.position.point2d

        elif type(entry) == Location:
            if query[0] == 'room':
                return ET.tostring(entry.room.to_xml()), 0
            elif query[0] == 'location':
                return ET.tostring(entry.to_xml()), 0

        elif type(entry) == Room:
            if query[0] == 'room':
                return ET.tostring(entry.to_xml()), 0
            elif query[0] == 'location':
                print('Failed, query ' + ' '.join(query) +
                      ' makes no sense! A room cannot be in a location.')
                return 'Failed, a room cannot be in a location!', 32

        elif type(entry) == Rcobject:
            if query[0] == 'room':
                return ET.tostring(entry.location.room.to_xml()), 0
            elif query[0] == 'location':
                return ET.tostring(entry.location.to_xml()), 0

    # for persons and given points we need to keep going
    ## retrieve room/ location in which this point lies

    if query[0] == 'room':
        for room in Room.objects(
                annotation__polygon__geo_intersects=[point.x, point.y]):
            return ET.tostring(room.to_xml()), 0
    elif query[0] == 'location':
        for loc in Location.objects(
                ishidden=False,
                annotation__polygon__geo_intersects=[point.x, point.y]):
            return ET.tostring(loc.to_xml()), 0

    print('Failed, query ' + ' '.join(query) +
          ' could not find a corresponding item!')
    return 'Failed, something unforseen happened, maybe the there is no room/location this point/object/location/room/person lies in', 33