Esempio n. 1
0
    def __init__(self, 
        name=None, 
        size=15,
        xpos=0,
        ypos=0,
        haircolor='blue',
        happiness=0.5,
        ):

        if agentsim.debug.get(2):
            print("Person init", self.__class__, self, 
                name, size, xpos, ypos, haircolor, happiness)

        self._id = Person._nextID
        Person._nextID += 1

        # set the name of the person from constructor parameters
        if name == None:
            self._name = "ID-" + str(self._id)
        else:
            self._name = name

        # size, haircolor, xpos, ypos, happiness are delegated to the
        # shape associated with the person
        # haircolor is mapped to color in the shape

        # create the shape associated with this instance
        # Arggh, the xpos = xpos form is confusing, but there is no way
        # around it without creating even more keyword names.  The xpos on 
        # the right is the value of the xpos argument to this function, 
        # which is begin provided to the xpos keyword of the HappyFace
        # constructor

        self._shape = HappyFace(
            xpos = xpos, ypos = ypos,
            size = size, color = haircolor,
            happiness = happiness,
            )

        # insert into collection of instances
        Person._instances[self._id] = self
Esempio n. 2
0
class Person():
    # Class variables:
    # id of the next object instance to be created
    _nextID = 1

    # dict of of all instances of Person, keyed by object id
    _instances = { }

    # Class methods
    # the @classmethod decorator causes the class that was used to invoke
    # the method to be passed as the first argument, just like a object
    # instance invocation.

    @classmethod
    def get_all_instances(cls):
        """
        return all instances of the class it was invoked with.  
        E.g.  Person.get_all_instances() returns all the Person objects
            or subclass of Person objects
        while
            Normal.get_all_instances() returns only the objects
            that are Normal or a subclass

        Also works if invoked on an object, getting all the instances
        of the class of the object

            p = Person()
            p.get_all_instances()
        """

        return [v for v in Person._instances.values() if isinstance(v, cls)]

    @classmethod
    def get_all_present_instances(cls):
        """
        return all instances of the class it was invoked with that 
        also satisfy the is_present test

        Also works if invoked on an object, getting all the instances
        of the class of the object

            p = Person()
            p.get_all_present_instances()
        """

        return [v for v in Person._instances.values() if 
            isinstance(v, cls) and v.is_present() ]

    @classmethod
    def get_instances_with_name(cls, name):
        """
        return all instances of the class it was invoked with and whose
        name exactly matches name.

        E.g.  Person.get_instances_name('fred') returns all the Person 
            objects or subclass of Person objects with name 'fred'
        while
            RandomPerson.get_instances_with_name'fred'() returns only 
            the objects that are RandomPerson or a subclass, and with
            matching name

        Also works if invoked on an object, getting all the instances
        of the class of the object

            p = Person(name='fred')
            p.get_instances_with_name('fred')

        """

        # better to write this as:
        # [ p for p in cls.get_all_instances if p.get_name() == name ]

        result = [ ]
        for p in Person._instances.values():
            if isinstance(p, cls) and p.get_name() == name:
                result.append(p)
        return result

    # Note: we could make the next two into @staticmethod, in which case
    # the class would not be passed through, but there might be cases
    # where the class is useful

    @classmethod
    def del_instance_with_id(cls, id):
        """
        Person.del_instance_with_id(id) removes the Person with the 
        given id from the inventory of instances.  It is hidden on 
        the canvas, but not immediately destroyed since there may be
        pending events on the object that have to be processed.

        Can we use sys.getrefcount() to tell us if it is safe to 
        "destroy" an object?
        """
        
        if id in Person._instances:
            Person._instances[id]._shape.hide()
            del(Person._instances[id])


    @classmethod
    def del_instance(cls, obj):
        """
        Percon.del_instance(p) is like del_instance_with_id but given
        the actual Person object p
        """

        # note the use of the cls variable that holds the name of 
        # the invoking class
        cls.del_instance_with_id(obj.get_id())


    def __init__(self, 
        name=None, 
        size=15,
        xpos=0,
        ypos=0,
        haircolor='blue',
        happiness=0.5,
        ):

        if agentsim.debug.get(2):
            print("Person init", self.__class__, self, 
                name, size, xpos, ypos, haircolor, happiness)

        self._id = Person._nextID
        Person._nextID += 1

        # set the name of the person from constructor parameters
        if name == None:
            self._name = "ID-" + str(self._id)
        else:
            self._name = name

        # size, haircolor, xpos, ypos, happiness are delegated to the
        # shape associated with the person
        # haircolor is mapped to color in the shape

        # create the shape associated with this instance
        # Arggh, the xpos = xpos form is confusing, but there is no way
        # around it without creating even more keyword names.  The xpos on 
        # the right is the value of the xpos argument to this function, 
        # which is begin provided to the xpos keyword of the HappyFace
        # constructor

        self._shape = HappyFace(
            xpos = xpos, ypos = ypos,
            size = size, color = haircolor,
            happiness = happiness,
            )

        # insert into collection of instances
        Person._instances[self._id] = self

    def arrive(self):
        """
        invoke this to have the person arrive at the simulation and become 
        visisble on the canvas
        """

        self._shape.draw()
        return self


    def leave(self):
        """
        invoke this to have the person leave the simulation and no longer
        be visisble on the canvas.  All the graphic components of the 
        associated Shape are destroyed.

        Note: does not delete the person, they still exist, and so if you
        want to avoid processing them, use is_present() to test their status
        They can rejoin the simulation later if they wish.
        """

        self._shape.erase()
        return self

    def is_present(self):
        """
        A person has a state, present or not present at the party.
        if they are not present, you might want to ignore them.

        is_present 
        returns 1 if the person is visible on the canvas
        returns 0 if the person is not visible on the canvas
        
        we do not have any explicit person state, the assumption is that
        if you are drawn, then you are present in the simulation
        """

        # NOTE: not good practice, should be asking shape if it is 
        # drawn or not, not inspect its state!  Yes I know about the
        # Law of Demeter
        if self._shape._gstate == Shape.DRAWN:
            return True
        else:
            return False

    def move_by(self, delta_x, delta_y):
        """
        """
        # move_by is delegated to the shape
        self._shape.move_by(delta_x, delta_y)
        return self

    def distances_to(self, other_person):
        """
        """
        delta_x = other_person.get_xpos() - self.get_xpos()
        delta_y = other_person.get_ypos() - self.get_ypos()
        d = (delta_x * delta_x + delta_y * delta_y) ** 0.5
        d_edge_edge = d - (self.get_size() + other_person.get_size())/2
        return  (d, delta_x, delta_y, d_edge_edge)

    # primary behaviour of the object
    def compute_next_move(self):
        return (0, 0)

    # accessors
    def get_id(self):
        return self._id

    def get_name(self):
        return self._name

    # all the remaining attributes are the responsibility of the shape
    # so the methods are delegate to corresponding methods in the shape
    def get_xpos(self):
        return self._shape.get_xpos()

    def get_ypos(self):
        return self._shape.get_ypos()

    def get_size(self):
        return self._shape.get_size()

    def get_min_size(self):
        return self._shape.get_min_size()

    def get_max_size(self):
        return self._shape.get_max_size()

    def set_size(self, size):
        return self._shape.set_size(size)

    def get_haircolor(self):
        return self._shape.get_color()

    def set_haircolor(self, haircolor):
        return self._shape.set_color(haircolor)

    def get_happiness(self):
        return self._shape.get_happiness()

    def set_happiness(self, happiness):
        return self._shape.set_happiness(happiness)