def analyze(hand, turncard): """ """ log.trace("Analyzing hand for %s: %s" % (hand.seat['name'], hand.card_tags)) discard = None bid_analysis = [BidAnalysis(hand.cards, s, turncard) for s in SUITS] # penalty/reward for ordering trump into dealer hand (note, this should be # pushed into BidAnalysis, one way or another!) turn_idx = turncard.suit['idx'] if hand.pos in (0, 2): penalty = turncard.efflevel[turn_idx] bid_analysis[turn_idx].hand_score -= penalty elif hand.pos == 1: reward = turncard.efflevel[turn_idx] // 2 bid_analysis[turn_idx].hand_score += reward # fix up dealer hand based on turncard if hand.pos == 3: suit_idx = turncard.suit['idx'] # note that the following may actually return the turncard, e.g. if it # would be the lowest trump (or perhaps some wacky other reason) discard = _bestdiscard(bid_analysis[suit_idx], turncard) newcards = hand.cards.copy() newcards.append(turncard) newcards.remove(discard) log.trace("Reanalyzing dealer hand with turncard (%s) and discard (%s)" % (turncard.tag, discard.tag)) reanalysis = BidAnalysis(newcards, turncard.suit, turncard, discard) bid_analysis[suit_idx] = reanalysis return (bid_analysis, discard)
def nonblocking(self): s = self.socket() try: s.setblocking(0) except Exception as exc: log.error(exc, 'nonblocking(%d) fail', s.fileno()) return None log.trace(0, 'connection nonblocking *%d', self.index) return self
def parse_sockaddr(self, sockaddr): self.sockaddr = sockaddr if isinstance(sockaddr, tuple) or isinstance(sockaddr, list): self.text = ':'.join([str(i) for i in sockaddr]) else: self.text = str(sockaddr) self.addr_text = self.text log.trace(0, 'Addr.parse_sockaddr() result: %s', self.sockaddr) return self
def create_socket(addr): try: s = socket.socket(addr.family, addr.socktype, addr.proto) except Exception as exc: log.error(exc, 'socket.socket(%s) fail', addr.text) return None log.trace(0, 'socket create: %d(%s) family:%r socktype:%r proto:%r', s.fileno(), addr.text, addr.family, addr.socktype, addr.proto) return s
def reuse(self): s = self.socket() try: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except Exception as exc: log.error(exc, 'reuse(%d) fail', s.fileno()) return None log.trace(0, 'connection reuse *%d', self.index) return self
def socket(self, s=None): if isinstance(s, Addr) or isinstance(s, socket.socket): if isinstance(s, Addr): s = create_socket(s) elif isinstance(s, socket.socket): s = s.dup() self.close() self.sock = s log.trace(0, 'connection socket *%d: %d', self.index, s.fileno()) return self.sock
def keepalive(self, interval=30): s = self.socket() try: # if not is_darwin: # s.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, interval) s.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, interval) except Exception as exc: log.error(exc, 'keepalive(%d) fail', s.fileno()) return None log.trace(0, 'connection keepalive *%d', self.index) return self
def close(self): if self.sock: log.trace(0, 'connection close *%d: %d', self.index, self.sock.fileno()) if self.rev.active or self.wev.active: del_conn(self, WRITE_EVENT | READ_EVENT) self.wev.handler = None self.rev.handler = None self.wev.buff = '' self.rev.buff = '' close_socket(self.sock) self.sock = None return self
def __init__(self): self.index = get_sequence() log.trace(0, 'connection create *%d', self.index) if is_cygwin and self.index > 500: exit(0) # 防止循环引用,无法释放 self.wev = Event(weakref.proxy(self)) self.rev = Event(weakref.proxy(self)) self.wev.write = True self.rev.read = True self.sock = None
def __set_addr_info(self, index): if not self.addr_infos or index >= len(self.addr_infos): return None self.info_index = index # addr info: (family, socktype, proto, canonname, sockaddr) info = self.addr_infos[index] log.trace(0, 'text: %s, index: %d, addr info: %r', self.text, index, info) self.__set_procotol(info[0], info[1], info[2]) self.sockaddr = info[4] self.__set_addr_text() return self
def process(self, msg): c = self.conn cmd = msg.get(0) if cmd != 'heartbeat rsp': log.debug(0, '*%d read message: %s', c.index, msg) else: log.trace(0, '*%d read message: %s', c.index, msg) if not self.DO_MAP.has_key(cmd): log.error(0, 'invalid command. msg:%s', msg) return add_timer(self.stimer, HEARTBEAT_INTERVAL) add_timer(self.rtimer, HEARTBEAT_TIMEOUT) self.DO_MAP[cmd](self, msg)
def process(self, msg): c = self.conn cmd = msg.get(0) if cmd != 'heartbeat req': log.debug(0, '*%d read message: %s', c.index, msg) else: log.trace(0, '*%d read message: %s', c.index, msg) if not self.DO_MAP.has_key(cmd): log.error(0, 'invalid command. msg:%s', msg) return if self.register_key: add_timer(self.timer, EXPIRE_TIME) self.DO_MAP[cmd](self, msg)
def send_msg(self, msg): c = self.conn if isinstance(msg, str) or isinstance(msg, list) or isinstance( msg, Message): msg = Message(msg) if msg.get(0) != 'heartbeat req': log.debug(0, '*%d send message: %s', c.index, msg) else: log.trace(0, '*%d send message: %s', c.index, msg) buff = msg.encode() if not buff: log.error(0, 'invalid message: %s', msg) return self.send_bin(buff)
def close_socket(s): if not isinstance(s, socket.socket): log.warn('it is not socket') return try: s.shutdown(socket.SHUT_RDWR) log.trace(0, 'socket close: %d', s.fileno()) return except Exception as exc: log.error(exc, 'socket.shutdown(%d) fail', s.fileno()) try: s.close() return except Exception as exc: log.error(exc, 'socket.close(%d) fail', s.fileno())
def forward(self, rc, wc): add_timer(self.timer, EXPIRE_TIME) log.trace(0, 'recv: *%d(%s) send: *%d(%s)', rc.index, rc.addr.text, wc.index, wc.addr.text) buff = rc.rev.buff while True: r = 0 if not buff: r, buff = rc.recv(4096) if r != 0: if r == 1: log.debug(0, '*%d(%s) closed', rc.index, rc.addr.text) rc.rev.ready = False break if not buff: rc.rev.buff = '' add_conn(rc, READ_EVENT) del_conn(wc, WRITE_EVENT) rc.rev.ready = False return r, size = wc.send(buff) if r != 0: if r == 1: log.debug(0, '*%d(%s) closed', wc.index, wc.addr.text) wc.wev.ready = False break if not size: rc.rev.buff = buff del_conn(rc, READ_EVENT) add_conn(wc, WRITE_EVENT) wc.wev.ready = False return buff = buff[size:] c0 = self.c0 c1 = self.c1 log.info(0, 'bridge break *%d(%s) *%d(%s)', c0.index, c0.addr.text, c1.index, c1.addr.text) self.close()
def connect(self, addr): s = self.socket() if not s: s = self.socket(addr) if not s: return None try: s.connect(addr.sockaddr) except Exception as exc: err = exc.errno if err != errno.EINPROGRESS: log.error(exc, 'connect(%s) fail', addr.text) return None self.addr = addr log.trace(0, 'connection connect *%d: %s', self.index, addr.text) self.keepalive() return self
def parse_text(self, text, *args): self.text = text self.sockaddr = None arr = text.split(':') if len(arr) != 2: log.error(0, 'invalid addr text: %s', text) return None try: addr_infos = socket.getaddrinfo(arr[0], arr[1], *args) except Exception as exc: log.error(exc, 'socket.getaddrinfo(%s) fail', text) return None if not addr_infos: log.error(0, 'socket.getaddrinfo(%s) is empty', text) return None self.addr_infos = addr_infos log.trace(0, 'socket.getaddrinfo(%s): %r', text, addr_infos) self.__set_addr_info(0) log.trace(0, 'Addr.parse_text(%s): %s', text, self.sockaddr) return self
def next_sockaddr(self): index = self.info_index + 1 if not self.__set_addr_info(index): return None log.trace(0, 'Addr.next_sockaddr(): %s', self.sockaddr) return self
def __del__(self): self.close() log.trace(0, 'connection destroy *%d', self.index)
def log_trace(self): """ """ log.trace(" with %s as trump:" % (self.trump['tag'])) log.trace(" cards by suit: %s" % (self.card_tags_by_suit)) log.trace(" count by suit: %s" % (self.suitcount)) log.trace(" trump score: %s" % (self.trump_score)) log.trace(" next score: %s" % (self.next_score)) log.trace(" green score: %s" % (self.green_score)) log.trace(" purple score: %s" % (self.purple_score)) log.trace(" trumps: %s" % (self.trumps)) log.trace(" top trump scores: %s" % (self.top_trump_scores)) log.trace(" aces: %s" % (self.aces)) log.trace(" voids: %s" % (self.voids)) log.trace(" singletons: %s" % (self.singletons)) log.trace(" hand score: %s" % (self.hand_score))