def _get_qss_files(self, paths=[]): """ Get qss files. :param list path: ist of paths to add to the scan. :returns: dictionary of stylesheet names/filenames. :rtype: dict """ qss_files = dict() if not paths: return [] for path in paths: for fn in os.listdir(path): bn, fext = os.path.splitext(fn) if fext.lower() in ['.qss', '.css']: qss_file = os.path.join(path, fn) if qss_file not in qss_files.values(): style_name = self._parse_stylesheet_name(qss_file) if style_name is None: log.warning('cannot parse style name from "%s".' % qss_file) style_name = 'no-style' log.debug('adding stylesheet "%s" from "%s".' % (style_name, qss_file)) if style_name not in qss_files: qss_files[style_name] = qss_file return qss_files
def discard_lowest(): """Discard lowest card, any suit (last resort) Note: always returns value, can be last in ruleset """ mincard = None minlevel = ace['level'] savecards = [] # attempt to preserve, only discard if no alternatives for idx in range(len(suitcards)): if idx == tru_idx: continue # avoid unguarding doubleton king, while making sure that A-K doubleton # takes precedence (if also present) if suitcount[idx] == 2 and king in (c.rank for c in suitcards[idx]): savecards.append(suitcards[idx][0]) continue # otherwise we just pick the first card found at the lowest level; chances # are that there is no other meaninful logic to apply here (e.g. choosing # between green suit doubletons) if suitcards[idx]: if suitcards[idx][0].level < minlevel: mincard = suitcards[idx][0] minlevel = mincard.level elif suitcards[idx][0].level == minlevel: # may need to stow an ace, if only outstanding card savecards.append(suitcards[idx][0]) assert mincard or savecards if not mincard: mincard = min(savecards, key=lambda c: c.level) log.debug("Have to unguard doubleton king or discard from A/A-K, oh well...") log.debug("Discard %s if %s trump, lowest card" % (mincard.tag, trump['tag'])) return mincard
def read_connect(self): buff = self.read_bin() if not buff: return msg = Message() r = msg.decode(buff) if r != 0: return if r < 0: self.close() return c = self.conn_proxy log.debug(0, '*%d read message: %s', c.index, msg) cmd = msg.get(0) if cmd != 'connect rsp': log.error(0, 'invalid command. msg:%s', msg) return err = msg.get(1) if err != 'ok': log.error(0, 'accept fail. msg:%s', msg) self.close() return Bridge(self.conn, self.conn_proxy) self.conn = None self.conn_proxy = None if self.timer: del_timer(self.timer) self.timer = None
def ready_connect_target(self): c = self.conn_target log.debug(0, '*%d connect: %s', c.index, c.addr.text) del_conn(c, WRITE_EVENT) self.ready_target = True self.check_ready()
def read(self): buff = self.read_bin() if not buff: return msg = Message() r = msg.decode(buff) if r != 0: return if r < 0: self.close() return c = self.conn_proxy log.debug(0, '*%d read message. msg:%s', c.index, msg) cmd = msg.get(0) if cmd != 'accept rsp': log.error(0, 'invalid message. msg:%s', msg) self.close() return err = msg.get(1) if err != 'ok': log.error(0, 'accept fail. msg:%s', msg) self.close() return self.ready_proxy = True del_conn(c, WRITE_EVENT) self.check_ready()
def _get_config_files(self, paths=[]): """ Get config files. :param list path: ist of paths to add to the scan. :returns: dictionary of config names/filenames. :rtype: dict """ cfg_files = dict() if not paths: return [] for path in paths: for fn in os.listdir(path): bn, fext = os.path.splitext(fn) if fext.lower() in ['.ini', '.cfg']: cfg_file = os.path.join(path, fn) names = bn.split('-') if len(names) < 2: log.warning('improperly named config file: "%s"' % cfg_file) continue style_name, cfg_type = names if style_name not in cfg_files: cfg_files[style_name] = dict(fonts=None, palette=None) log.debug('adding %s config "%s" from "%s".' % (cfg_type, style_name, cfg_file)) cfg_files[style_name][cfg_type] = cfg_file return cfg_files
def play_low_trump(): """Play lowest trump (assumes no non-trump remaining) """ if trump_cards and len(trump_cards) == len(analysis.cards): # REVISIT: are there cases where we want to play a higher trump??? log.debug("Play lowest trump") return trump_cards[0]
def accept(self): try: if not is_cygwin: s, sockaddr = self.socket().accept() else: begin = time.time() s, sockaddr = self.socket().accept() end = time.time() if end - begin > 1: log.info(0, 'accept cost %f seconds', end - begin) exit(-1) except IOError as exc: err = exc.errno if err != errno.EAGAIN and err != errno.EINTR: log.error(exc, 'accept() fail') return None except Exception as exc: log.error(exc, 'accept() fail') return None c = Connection() c.socket(s) c.listening = self c.nonblocking() c.keepalive() c.addr = Addr(self.addr) c.addr.parse_sockaddr(sockaddr) log.debug(0, '*%d accept: %s', c.index, c.addr.text) self.handler(c) return self
def all_trump_case(): """Handle all trump case (get it out of the way) """ if suitcount[tru_idx] == len(analysis.cards): discard = min(suitcards[tru_idx][0], turncard, key=lambda c: c.level) log.debug("Discard %s if %s trump, lowest trump" % (discard.tag, trump['tag'])) return discard
def listen(self, addr, backlog=32): if not isinstance(addr, Addr): addr = Addr(addr) s = self.socket(addr) if not s: return None if not self.reuse(): self.close() return None try: s.bind(addr.sockaddr) except Exception as exc: log.error(exc, '*%d bind(%s) fail', self.index, addr.text) self.close() return None try: s.listen(backlog) except Exception as exc: log.error(exc, '*%d listen(%s) fail', self.index, addr.text) self.close() return None log.debug(0, '*%d listen: %s', self.index, addr.text) self.nonblocking() self.addr = addr self.backlog = backlog return self
def follow_suit_low(): """Follow suit low """ if analysis.suitcards[lead_idx]: # REVISIT: are there cases where we want to try and take the lead??? log.debug("Follow suit low") return analysis.suitcards[lead_idx][0]
def update(self, grid, data): session = DBSession() session.query(self.model).filter(self.model.grid == grid).update(data) try: session.commit() except Exception as e: log.debug("Ocorreu um erro ao salvar as configurações !\n" + e) session.rollback()
def lead_random_card(): """This is a catchall, though we should look at cases where this happens and see if there is a better rule to insert before Note: always returns value, can be last in ruleset """ log.debug("Lead random card") return random.choice(analysis.cards)
def handle_join(event, message): client=Client.findByNick(message.source) if(client is None): return chan=Channel.findByName(message.parameters[0]) if(chan is None): chan=Channel(message.parameters[0], time.time()) Channel.addChannel(chan) chan.addClient(client) log.debug("%s has joined %s", client.nick, chan.name)
def handle_join(event, message): client = Client.findByNick(message.source) if (client is None): return chan = Channel.findByName(message.parameters[0]) if (chan is None): chan = Channel(message.parameters[0], time.time()) Channel.addChannel(chan) chan.addClient(client) log.debug("%s has joined %s", client.nick, chan.name)
def do_register(self, msg): err = msg.get(1) if err != 'ok': log.error(0, 'register fail. msg:%s', msg) self.send_msg(['register req', self.key]) return self.registered = True log.debug(0, 'register succ. key:%s', self.key)
def lead_suit_winner(): """Try to lead winner (non-trump) """ if my_high_cards: my_high_cards.sort(key=lambda c: c.efflevel[tru_idx]) log.debug("Try and lead suit winner") # REVISIT: is this the right logic (perhaps makes no sense if preceded by # off-ace rule)??? Should also examine remaining cards in suit!!! return my_high_cards[-1] if trick_no <= 3 else my_high_cards[0]
def model_to_fields(self, model: PersonGroup): self.check_active.SetValue(True if model.flag == 'A' else False) for k, v in model.__dict__.items(): try: prop = 'text_' + k self.prop.SetValue(v) except Exception as exc: log.debug(exc) self.grid = model.grid self.text_code.SetValue(model.code)
def lead_low_from_long_suit(): """Lead low from long suit (favor green if defeending?) Note: always returns value, can be last in ruleset """ suitcards = analysis.suitcards.copy() suitcards.sort(key=lambda s: len(s)) # TODO: a little more logic in choosing suit (perhaps avoid trump, if possible)!!! log.debug("Lead low from longest suit") return suitcards[-1][0]
def discard_from_next(): """Discard next if loner call from third seat (REVISIT: not sure it makes sense to extend this to the general, non-voiding, non-third-seat-loner case!!!) """ if suitcount[nxt_idx] == 2: # don't unguard doubleton king or break up A-K if king not in (c.rank for c in suitcards[nxt_idx]): discard = suitcards[nxt_idx][0] log.debug("Discard %s if %s trump, reducing next" % (discard.tag, trump['tag'])) return discard
def throw_off_low(): """Throw off lowest non-trump card """ if len(trump_cards) < len(analysis.cards): # NOTE: this will always pick the "lowest" suit in case multiple cards at min level non_trump_cards = [ c for c in analysis.cards if c.suit['idx'] != tru_idx ] non_trump_cards.sort(key=lambda c: c.efflevel[tru_idx]) log.debug("Throw-off lowest non-trump") return non_trump_cards[0]
def lead_low_non_trump(): """If still trump in hand, lead lowest card (non-trump) """ if trump_cards and len(trump_cards) < len(analysis.cards): # NOTE: will always pick the "lowest" suit if multiple cards at min level non_trump_cards = [ c for c in analysis.cards if c.suit['idx'] != tru_idx ] non_trump_cards.sort(key=lambda c: c.efflevel[tru_idx]) log.debug("Lead lowest non-trump") return non_trump_cards[0]
def create_doubleton(): """Create doubletons, if possible (favor over creating singletons) """ if suitcount.count(3) > 0: idx = suitcount.index(3) # REVISIT: perhaps only do if high card in suit is actually viable (like # queen or higher)!!! if idx != tru_idx: # note that first element is the loweest (cards sorted ascending) discard = suitcards[idx][0] log.debug("Discard %s if %s trump, creating doubleton" % (discard.tag, trump['tag'])) return discard
def lead_to_create_void(): """If trump in hand, try and void a suit """ if trump_cards and singletons: # REVISIT: perhaps only makes sense in earlier rounds (2 and 3), and otherwise # add some logic for choosing if more than one singleton!!! if len(singletons) == 1: log.debug("Lead singleton to void suit") return singletons[0] else: log.debug("Lead singleton to void suit (random for now)") return random.choice(singletons)
def lead_off_ace(): """Off-ace (short suit, or green if defending?) """ if off_aces: # TODO: choose more wisely if more than one, or possibly preserve ace to # avoid being trumped!!! if len(off_aces) == 1: log.debug("Lead off-ace") return off_aces[0] else: log.debug("Lead off-ace (random choice)") return random.choice(off_aces)
def main(): db.connect(config.dbhost, config.dbuser, config.dbpass, config.dbname) hon_monitor = HoNStatus() test_count = 1 while True: log.info("Running test #" + str(test_count)) # Reconfigure the monitor. hon_monitor.configure() login_status, login_reason = hon_monitor.login_test() log.info("Login server: %s - %s" % (login_status, login_reason)) chat_status, chat_reason = hon_monitor.chat_test() log.info("Chat Server: %s - %s" % (chat_status, chat_reason)) # MotD data can be checked each test, regardless of the server statuses. try: hon_monitor.motd_parser() except MasterServerError, e: if e.code == 108: log.error('Could not obtain MotD data from the Master server') # Check that all tests returned good, otherwise the test fails and should # be re-attempted in 90 seconds if login_status is "Up" and chat_status is "Up": hon_monitor.logged_in = True timer = 0 while hon_monitor.is_logged_in: timer += 1 if timer >= 300: hon_monitor.disconnect_logout() break else: time.sleep(1) # Client disconnected, cool down for a moment log.debug("Client disconnected, cooling..") time.sleep(2) else: # Start dropping the players online to zero once it's been determined that # the servers are down. if down_count > 5: db.execute("""INSERT INTO players (time, value) VALUES (%s, %s)""", [str(int(time.time())), 0]) time.sleep(90) # Loop increment test_count += 1 # And log back out again hon_monitor.logged_in = False
def get_modules(path): """ Returns all sub-modules of this package. :returns: list of module names in the current package. :rtype: list """ mod_names = [] modules = pkgutil.iter_modules(path=[path]) for loader, mod_name, ispkg in modules: mod_names.append(mod_name) log.debug('reading module: "%s"' % mod_name) return sorted(mod_names)
def do_accept(self, msg): key = msg.get(1) if not key: log.error(0, 'invalid message: %s', msg) return if self.register_key: log.error(0, '*%d has registered. key:%s', self.register_key) self.send_msg([ 'connect rsp', 'error', 'has registered. key:%s' % self.register_key ]) return if self.connect_key: log.error(0, '*%d has connected. key:%s', self.connect_key) self.send_msg([ 'connect rsp', 'error', 'has connected. key:%s' % self.connect_key ]) return if not CONNECT.has_key(key): self.send_msg( ['accept rsp', 'error', 'has not connect. key:%s' % key]) return e = CONNECT[key] log.debug(0, '*%d del connect: %s', e.conn.index, e.connect_key) del CONNECT[key] e.connect_key = None self.send_msg(['accept rsp', 'ok']) e.send_msg(['connect rsp', 'ok']) if e.conn and self.conn: Bridge(e.conn, self.conn) e.conn = None self.conn = None if e.timer: del_timer(e.timer) e.timer = None if self.timer: del_timer(self.timer) self.timer = None else: e.close() self.close()
def throw_off_to_create_void(): """Create void (if early in deal)--NOTE: this only matters if we've decided not to trump (e.g. to preserve for later) """ if trump_cards and singletons: if len(singletons) == 1: log.debug("Throw off singleton to void suit (lowest)") return singletons[0] else: # REVISIT: perhaps only makes sense in earlier rounds (2 and 3), and also # reconsider selection if multiple (currently lowest valued)!!! singletons.sort(key=lambda c: c.efflevel[tru_idx]) log.debug("Throw off singleton to void suit (lowest)") return singletons[0]
def play_random_card(): """Play random card, but follow suit if possible Note: always returns value, can be last in ruleset """ if plays: lead_card = plays[0][1] suit_idx = lead_card.suit['idx'] if analysis.suitcards[suit_idx]: log.debug("Follow suit, random card") return random.choice(analysis.suitcards[suit_idx]) log.debug("Play random card") return random.choice(analysis.cards)
def delete(self, grid): session = DBSession() session.query(self.model).filter(self.model.grid == grid).update( {'flag': 'D'}) try: session.commit() log.info("Comando executado com sucesso !") log.info(session) return session except Exception as e: log.debug("Ocorreu um erro ao salvar as configurações !\n" + e.__str__()) session.rollback() return None
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 handle_leave(event, message): source=Client.findByNick(message.source) if(source is None): source=Server.findByName(message.source) if(source is None): return targetchan=Channel.findByName(message.parameters[0]) if(targetchan is None): return if(message.command=="PART"): targetuser=source reason=message.parameters[-1] if len(message.parameters)>1 else "[none]" elif(message.command=="KICK"): targetuser=Client.findByNick(message.parameters[1]) if(targetuser is None): return reason=message.parameters[-1] log.debug("%s has left %s: %s: %s", targetuser.nick, targetchan.name, "kicked by "+(source.nick if source.__class__.__name__=="Client" else source.name) if message.command=="KICK" else "PART", reason ) targetchan.removeClient(targetuser)
def parse_message(self, event, source, target, message): """ Processes the message received and decides what a response would be. `event` The type of message received. Either MSG_N, MSG_W or MSG_P. `source` The location the message came from, usualy a player. `target` The location the message went to. Either a channel, or one's self in the case of a whisper or PM. `message` The actual message to be processed. """ # Ignore the bot's own messages. if source == self.bot.nickname: return # Ignore empty messages if message == "": return # Search for commands or queries in the message if message[0] == "!": command = message[1:].split(" ")[0] # Split on spaces, and grab the first word, the command. args = message[2 + len(command):] # Grab a list of arguments log.debug("(Command) %s: %s" % (command, ''.join(args))) if command in self.bot_commands: f = self.bot_commands[command] # Set the owner bit if strip_clan(source) in self.bot.owners: owner = 1 else: owner = 0 return f(source, target, args, owner) else: # If the bot is allowed to learn then let it learn! if (target in self.channels and self.channels[target]['learning']) or event == MSG_P or event == MSG_W: self.bot.learn(message) # Check if the bot is to reply with a generated response. if ((target in self.channels and self.channels[target]['speaking']) or event == MSG_P or event == MSG_W) \ and self.bot.check_replying(event, message): response = self.bot.create_reply(message) return response # If None is returned, then the bot does nothing. return None
def handle_sjoin(event, message): chan_name=message.parameters[1] timestamp=message.parameters[0] chan=Channel.findByName(chan_name) if(chan is None): chan=Channel(chan_name, timestamp) Channel.addChannel(chan) p_idx=2 if(message.parameters[p_idx][0]=="+"): #we have modes if(chan.timestamp==timestamp): #merge modes chan.setModes(message.parameters[p_idx], message.parameters[p_idx+1:-1], True) elif(chan.timestamp>timestamp): #clear existing modes and use sjoin modes chan.clearModes() chan.setModes(message.parameters[p_idx], message.parameters[p_idx+1:-1]) #else ignore sjoin modes new_modes=[] new_params=[] for item in message.parameters[-1].split(): #this could be a channel member, ban, exemption, or invex -- very confusing! # *~@%+ are user statuses qaohv, respectively # & is a ban, " is an exemption, ' is an invex item_type=item[0] if(sjoin_prefix_to_mode.has_key(item_type)): item=item[1:] new_modes.append(sjoin_prefix_to_mode[item_type]) new_params.append(item) if(not sjoin_prefix_to_mode.has_key(item_type) or item_type in ("*", "~", "@", "%", "+")): member=Client.findByNick(item) if(not member is None): log.debug("SJOIN: %s to %s", member.nick, chan.name) chan.addClient(member) if(len(new_modes)>0): chan.setModes("+"+"".join(new_modes), new_params)
def motd_parser(self): """ Retrieves the dictionary of message of the day(s(?)) and replaces S2's colour formatting with html classes. Then places any new items into the database. """ colour_map = ["00","1C","38","54","70","8C","A8","C4","E0","FF"] s2colours = lambda m: '<span style="color: #' + ''.join([colour_map[int(x)] for x in m.group(1)]) + '">' def urlfix(x): """ Replaces urls which only contain a 'www' with a 'http://wwww'. """ if x.group(2) in ['http://', 'www']: colour = "y" url = x.group(1) else: colour = x.group(1) url = x.group(2) r = re.compile(r"(?<!http://)www") if r.match(url): url = 'http://' + ''.join(url) return '<a href=' + url + ' class=' + colour + ' target="_blank">' + url + '</a>' motd_data = self.motd_get() motd_list = motd_data['motd_list'] ## NOTE: This entire thing is fairly broken due to glows, and when retards use rainbows in their text. # Iterate over the list in reverse because entries are retrieved in order newest -> oldest # and must be entered into the database oldest -> newest. for motd in motd_list[::-1]: # First find any un-coloured hyperlinks and fill them with html tags. # This regex matches any hyperlink which is not preceeded by a ^g formatter for EG. # It is not very accurate at the moment as it will match a http which has a ^* at the end. # http://gskinner.com/RegExr/?2u79l r = re.compile(r"(?<=[^\^a-zA-Z])((http://|(?<!http://)www)[-a-zA-Z0-9@:%_\+.~#?&//=]+)[^\^\*]") motd['body'] = r.sub(urlfix, motd['body']) # Then find all hyperlinks that contain colour formatting and replace with HTML tags. r = re.compile(r"\^([a-zA-Z])((http://|(?<!http://)www)[-a-zA-Z0-9@:%_\+.~#?&//=]+)(\^\*)") motd['body'] = r.sub(urlfix, motd['body']) # Find all coded colours eg ^428 and replace with inline html styling # ''.join([color_map[int(x)] for x in r.search(msg).group(1)]) r = re.compile(r"\^([0-9]{3})") motd['body'] = r.sub(s2colours, motd['body']) # Replace the colours with HTML classes # Replace ^* with </span> motd['body'] = motd['body'].replace("^*", "</span>") # Find all basic colour codes eg ^y or ^r or ^o and replace with inline html r = re.compile(r"\^([a-z]{1})") motd['body'] = r.sub(r"<span class='\1'>", motd['body']) # Replace \r\n with <br /> motd['body'] = motd['body'].replace("\r\n", "<br />") title_exists = db.query("""SELECT id FROM motds WHERE title = %s AND date = %s""", [motd['title'], motd['date']]) msg_exists = db.query("""SELECT id, title FROM motds WHERE body = %s AND date = %s""", [motd['body'], motd['date']]) if not title_exists: # Check if the message was simply updated by the staff. # If it's been changed then update it in the database automatically. # TODO: Is this level of comparison okay? if msg_exists: # Title doesn't exist, but message body does, title changed. db.execute("""UPDATE motds SET title=%s, author=%s, date=%s, body=%s WHERE id = %s""", [motd['title'], motd['author'], motd['date'], motd['body'], msg_exists[0][0]]) log.info("Updated motd #%s - %s. Title updated to %s" % (msg_exists[0][0], msg_exists[0][1], motd['title'])) elif title_exists: log.debug("Duplicate title for motd id %s with title %s" % (title_exists[0][0], motd['title'])) # This entry is already here, possibly it could have been updated. # Note: Seems they like to change the titles after publishing them. if not msg_exists: # Title exists but the msg body doesn't, so it was likely updated. db.execute("""UPDATE motds SET title=%s, author=%s, date=%s, body=%s WHERE id = %s""", [motd['title'], motd['author'], motd['date'], motd['body'], title_exists[0][0]]) log.info("Updated motd #%s - %s. Message updated" % (title_exists[0][0], motd['title'])) if not msg_exists and not title_exists: # Neither the title or message are there, either both are changed or this is a brand new motd # Treat it as new for now. # Add this motd to the database db.execute("""INSERT INTO motds (title, author, date, body) VALUES(%s, %s, %s, %s)""", [motd['title'], motd['author'], motd['date'], motd['body']]) log.info("Added new message of the day - %s - %s" % (motd['title'], motd['date'])) # Get the image from S2 for the motd. # Save it to static/img/motd/ if it does not exist. image_file = motd_data['image'].split("`")[0] image_name = re.search(r'\/([a-f0-9]+.jpg)', image_file).group(1) if not os.path.isfile(os.path.join(config.motd_img_dir, image_name)): urllib.urlretrieve(image_file, os.path.join(config.motd_img_dir, image_name)) # Set the image name in the database so it can be retrieved. db.execute("""UPDATE `motd_extra` SET `value`=%s WHERE `key`=%s""", [image_name, 'image']) log.info("New MOTD image.")