コード例 #1
0
ファイル: world.py プロジェクト: NElias/swottc
class World(object):
    worlds = []

    @staticmethod
    def clear_all():
        for world in World.worlds:
            world.stop()
        World.worlds = []

    def __init__(self, cols, rows):
        self.cols = cols
        self.rows = rows
        self._objects = []
        self._field = []
        self._timer = None
        self.queue = []
        self.reproductions = 0
        self.plants = 0
        self.herbivores = 0
        self.predators = 0
        self.turns = 0
        self.deaths = 0
        for x in xrange(cols):
            self._field.append([ None for y in xrange(rows)])

        World.worlds.append(self)

    def check_queue(self):
        newqueue = []
        for turns, obj in self.queue:
            if turns == 0:
                self.add_creature(obj)
            else:
                newqueue.append((turns - 1, obj))
        return newqueue

    def loop(self):
        try:
            self.queue = self.check_queue()

            for obj in self._objects:
                obj.turn(self)
            deleted = filter(lambda obj: obj.is_nothing, self._objects)
            #todo: need lock
            for obj in deleted:
                logging.debug("Dead: %r, turns: %s, history: %s" % (obj, obj.turns, repr(obj.history.read())))
                self._field[obj.x][obj.y] = None
                self._objects.remove(obj)
                self.info_update_del(obj)
                self.deaths += 1
            self.stabilize()

            self.turns += 1
        except:
            import traceback
            logging.debug(traceback.format_exc())
            self._timer.cancel()

    def start(self, speed):
        if self._timer:
            raise Exception()
        self.init_count_objects = len(self._objects) + len(self.queue)
        self._timer = Timer(speed, self.loop)
        self._timer.start()

    def stop(self):
        self._timer.cancel()

    def begin_force(self):
        self._timer.is_force = True

    def end_force(self):
        self._timer.is_force = False

    def check_position(self, x, y):
        return 0 <= x < self.cols and 0 <= y < self.rows

    def add_creature(self, creature):
        if not self.check_position(creature.x, creature.y):
            return False
        if self._field[creature.x][creature.y] is not None:
            return False
        self._objects.append(creature)
        self._field[creature.x][creature.y] = creature
        self.info_update_add(creature)
        return True

    def info_update_add(self, creature):
        name = creature.__class__.__name__
        if name == 'Predator':
            self.predators += 1
        elif name == 'Herbivore':
            self.herbivores += 1
        elif name == 'Plant':
            self.plants += 1

    def info_update_del(self, creature):
        name = creature.__class__.__name__
        if name == 'Predator':
            self.predators -= 1
        elif name == 'Herbivore':
            self.herbivores -= 1
        elif name == 'Plant':
            self.plants -= 1

    def add_creature_square(self, creature):
        if self.add_creature(creature): return True
        creature.x -= 1
        creature.y -= 1
        if self.add_creature(creature): return True
        creature.x += 1
        if self.add_creature(creature): return True
        creature.x += 1
        if self.add_creature(creature): return True
        creature.y += 1
        if self.add_creature(creature): return True
        creature.y += 1
        if self.add_creature(creature): return True
        creature.x -= 1
        if self.add_creature(creature): return True
        creature.x -= 1
        if self.add_creature(creature): return True
        creature.y -= 1
        if self.add_creature(creature): return True
        return False

    def get_rnd_free_space(self):
        free_cells = self.rows * self. cols - len(self._objects)
        n = randint(1, free_cells)
        if n == 0:
            return None
        for x in xrange(self.cols):
            for y in xrange(self.rows):
                if self._field[x][y] is None:
                    n -= 1
                    if n == 0:
                        return (x, y)
        return None

    def get_creature(self, x, y):
        if not self.check_position(x, y):
            return
        return self._field[x][y]

    def move_creature(self, creature):
        cell, pos = self.get_creature_by_course(creature)
        if cell is None and pos is not None:
            #todo: need lock
            self._field[creature.x][creature.y] = None
            self._field[pos[0]][pos[1]] = creature
            creature.x, creature.y = pos

    def get_creature_by_course(self, creature):
        x, y = creature.x, creature.y
        if creature.course == COURSE_NORTH:
            x -= 1
        elif creature.course == COURSE_EAST:
            y += 1
        elif creature.course == COURSE_SOUTH:
            x += 1
        elif creature.course == COURSE_WEST:
            y -= 1
        if self.check_position(x, y):
            return self._field[x][y], (x, y)
        return None, None

    def stabilize(self):
        crnt = len(self._objects) + len(self.queue)
        if crnt < self.init_count_objects:
            from creatures import Predator, Herbivore, Plant
            for i in xrange(self.init_count_objects - crnt):
                pos = self.get_rnd_free_space()
                if pos is None:
                    break
                cs = [self.predators, self.herbivores, self.plants]
                n = cs.index(min(cs))
                cls = [Predator, Herbivore, Plant][n]
                creature = cls(x=pos[0], y=pos[1])
                self.add_creature(creature)

    @staticmethod
    def load_json(file_path):
        fp = open(file_path)
        data = json.load(fp)
        fp.close()

        world = World(cols=data['cols'], rows=data['rows'])

        constructors = dict((unicode(i.__name__), i) for i in [Predator, Herbivore, Plant])

        for obj in data['objects']:
            Create = constructors[obj['type']]
            creature = Create(x=obj['x'], y=obj['y'])
            creature.reproductive = obj['reproductive']
            creature.current_health = obj['current_health']
            creature.base_health = obj['base_health']
            if isinstance(obj, Mammals):
                creature.course = obj['course']
                creature.brain.whi = obj['brain']['whi']
                creature.brain.woh = obj['brain']['woh']
            world.add_creature(creature)
        world.start(0.1)
        return world

    def save_json(self, file_path):
        objects = []
        for obj in self._objects:
            data = {
                'type': obj.__class__.__name__,
                'x': obj.x,
                'y': obj.y,
                'reproductive': obj.reproductive,
                'base_health': obj.base_health,
                'current_health': obj.current_health,
            }
            if isinstance(obj, Mammals):
                data.update({
                    'course': obj.course,
                    'brain': {
                        'whi': obj.brain.whi,
                        'woh': obj.brain.woh,
                    },
                })
            objects.append(data)
        data = {
            'cols': self.cols,
            'rows': self.rows,
            'objects': objects,
        }
        fp = open(file_path, 'w')
        json.dump(data, fp, indent = 4)
        fp.close()
コード例 #2
0
class DanmuWebSocket(WebSocketClient):
    def __init__(self,
                 info,
                 serveraddress='wss://broadcastlv.chat.bilibili.com/sub'):
        self.serveraddress = serveraddress
        WebSocketClient.__init__(self, serveraddress)
        DanmuWebSocket.event = event
        DanmuWebSocket.headerLength = 16
        self.Info = info

    def opened(self):
        self.sendLoginPacket(self.Info['uid'], self.Info['roomid'],
                             self.Info['protover'], self.Info['platform'],
                             self.Info['clientver'])
        self.sendHeartBeatPacket()
        self.heartBeatHandler = Timer(20, self.sendHeartBeatPacket)
        print("opened")

    def delay_close(self):
        dws = DanmuWebSocket(self.Info, self.serveraddress)
        event.emit('reconnect', dws)

    def closed(self, code, reason=None):
        print("Closed", code, reason)
        if hasattr(self, "heartBeatHandler"): self.heartBeatHandler.cancel()
        if code == 1006: return
        threading.Timer(5, self.delay_close).start()

    def received_message(self, message):
        position, length = 0, len(message.data) - 1
        while position < length:
            header_pack = struct.unpack(">IHHII",
                                        message.data[position:position + 16])
            length_pack = header_pack[0]
            operation = header_pack[3]
            if operation == 3:
                num = header_pack[1] + position
                num = struct.unpack(">I", message.data[num:num + 4])[0]
                event.emit('heartbeat', num)
            elif operation == 5:
                data = json.loads(message.data[position + 16:position +
                                               length_pack])
                event.emit('cmd', data)
                #print("recv:"+data["cmd"])
            else:
                event.emit('login')
            position += length_pack

    def sendData(self, data, protover=1, operation=2, sequence=1):
        if type(data) == dict:
            data = json.dumps(data).encode()
        elif type(data) == str:
            data = data.encode()
        header = struct.pack(">IHHII", DanmuWebSocket.headerLength + len(data),
                             DanmuWebSocket.headerLength, protover, operation,
                             sequence)
        self.send(header + data)

    def sendLoginPacket(self,
                        uid,
                        roomid,
                        protover=1,
                        platform='web',
                        clientver='1.4.6'):
        # Uint(4byte) + 00 10 + 00 01 + 00 00 00 07 + 00 00 00 01 + Data 登录数据包
        data = {
            'uid': int(uid),
            'roomid': int(roomid),
            'protover': protover,
            'platform': platform,
            'clientver': clientver
        }
        print("sendLoginPacket")
        data = json.dumps(data)
        data = data.replace(' ', '')
        self.sendData(data.encode(), 1, 7, 1)

    def sendHeartBeatPacket(self):
        # Uint(4byte) + 00 10 + 00 01 + 00 00 00 02 + 00 00 00 01 + Data 心跳数据包
        self.sendData(b'[object Object]', 1, 2, 1)

    def bind(self,
             onreconnect=None,
             onlogin=None,
             onheartbeat=None,
             oncmd=None,
             onreceive=None):
        if "cmd" in event.keys: return
        if hasattr(onreconnect, "__call__"): event.on("reconnect", onreconnect)
        if hasattr(onlogin, "__call__"): event.on("login", onlogin)
        if hasattr(onheartbeat, "__call__"): event.on("heartbeat", onheartbeat)
        if hasattr(oncmd, "__call__"): event.on("cmd", oncmd)
        if hasattr(onreceive, "__call__"): event.on("receive", onreceive)
コード例 #3
0
ファイル: motors.py プロジェクト: Adridri24/Robocup
class Motor:
    """A class to represent a motor and offers an API to control it.

    Additionnal documentation can be found here:
        - http://learn.makeblock.com/en/me-encoder-motor-driver/
        - https://github.com/Makeblock-official/Makeblock-Libraries/blob/master/src/MeEncoderMotor.cpp
    """

    HEADER = [0xA5, 0x01]
    END = 0x5A
    CMD_MOVE_SPD = 0x05
    CMD_MOVE_SPD_TIME = 0x08
    CMD_RESET = 0x07
    CMD_MOVE_AGL = 0x11

    def __init__(self, pin: int, addr: int, slot: int):
        """Initialize I2C communication to motor.

        Args:
            pin: I2C bus' pin (2 or 4)
            addr: slave's address
            slot: motor's slot (1 or 2)
        """
        self.__slot = slot - 1
        self.__addr = addr
        self.__i2c = I2C(pin)
        self.__i2c.init(I2C.MASTER)
        self.__speed = 0
        self._stopper = Timer(callback=self.stop)

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

    async def __send_data(self, data: list):
        """Creates a trame from the data and send it to motor via I2C.

        Args:
            data: [slot, CMD, args]: data to send
        """
        lrc = self._lrc_calc(data)
        data_size = self._to_bytes("l", len(data))
        trame = Motor.HEADER + data_size + data + [lrc, Motor.END]
        self.__i2c.send(bytearray(trame), self.__addr)
        await asyncio.sleep_ms(20)  # A few wait time is needed for the motor.

    def __recv_data(self, length: int) -> bytearray:
        """Receives data from I2C slave's address

        Args:
            length number of bytes to receive

        Returns:
            buffer: data received in bytes
        """
        buffer = bytearray(length)
        self.__i2c.recv(buffer, self.__addr)
        return buffer

    def scan(self) -> list:
        """Scan slaves connected to the current I2C pin.

        Returns:
            list_of_slaves: addresses of slaves that respond
        """
        list_of_slaves = self.__i2c.scan()
        return list_of_slaves

    async def run(self, speed: float, time=None) -> None:
        """Controls motor rotation with speed given for an optional time.

        Args:
            speed: rotation speed (RPM) in [-200, +200]
            time: in seconds, runs for a specified time
        """
        if self.__i2c.is_ready(self.__addr):
            # Sets time limits to [-200 , +200] and convert it in bytes
            if speed < -200:
                speed = -200
            elif speed > 200:
                speed = 200
            if speed != self.__speed:
                speed_bytes = self._to_bytes("f", speed)
                data = [self.__slot, Motor.CMD_MOVE_SPD] + speed_bytes
                self.__speed = speed
                await self.__send_data(data)
            if time:
                self._stopper.cancel()
                self._stopper.start(timeout=time)
        else:
            raise RuntimeError("Motor {} cannot be run.".format(self.__slot))

    async def move(self, angle: float, speed: float) -> None:
        """Move motor of angle degrees at a speed given.

        Args:
            speed: rotation speed (RPM) in [-200, +200]
            angle: angle in degrees to rotate.
        """
        if speed < -200:
            speed = -200
        elif speed > 200:
            speed = 200
        if speed != self.__speed:
            self.__speed = speed
            time = (angle / 360 * 60) / speed
            await self.run(speed, time)

    async def stop(self):
        """Reset motor position to 0 and reinitialize data received."""
        data = [self.__slot, Motor.CMD_RESET]
        await self.__send_data(data)
        self.__speed = 0

    @staticmethod
    def _lrc_calc(data) -> int:
        """Calculate the Longitudinal Redondancy Check (LRC)

        Returns:
            lrc: the value of LRC
        """
        lrc = 0x00
        for byte in data:
            lrc ^= byte
        return lrc

    @staticmethod
    def _to_bytes(fmt: str, data) -> list:
        """Convert and pack data with a given format

        The list of available formats can be found here:
        https://docs.python.org/3/library/struct.html

        Args:
            fmt: string used to pack the data from a given format.
            data: data to be converted to bytes.

        Returns:
            data_bytes: a list of each element of data converted to bytes.
        """
        data_bytes = list(struct.pack(fmt, data))
        return data_bytes