From 15799130f8d34856b9cefe3c71103564413fa04a Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 16 May 2009 20:11:00 +0100 Subject: [PATCH] prettify the code a bit --- yoweb-scrape | 99 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/yoweb-scrape b/yoweb-scrape index a12ea23..a7f4c9b 100755 --- a/yoweb-scrape +++ b/yoweb-scrape @@ -1,5 +1,7 @@ #!/usr/bin/python +#---------- setup ---------- + import signal signal.signal(signal.SIGINT, signal.SIG_DFL) @@ -17,6 +19,7 @@ from BeautifulSoup import BeautifulSoup opts = None +#---------- YPP parameters and arrays ---------- puzzles = ('Swordfighting/Bilging/Sailing/Rigging/Navigating'+ '/Battle Navigation/Gunning/Carpentry/Rumble/Treasure Haul'+ @@ -31,10 +34,14 @@ pirate_ref_re = regexp.compile('^/yoweb/pirate\\.wm') max_pirate_namelen = 12 +#---------- general utilities ---------- + def debug(m): if opts.debug > 0: print m +#---------- caching and rate-limiting data fetcher ---------- + class Fetcher: def __init__(self, ocean, cachedir): debug('Fetcher init %s' % cachedir) @@ -133,6 +140,8 @@ class Fetcher: self.ocean, kind, tail) return self.fetch(url, max_age) +#---------- logging assistance for troubled screenscrapers ---------- + class SoupLog: def __init__(self): self.msgs = [ ] @@ -156,6 +165,8 @@ class SomethingSoupInfo(SoupLog): convertEntities=BeautifulSoup.HTML_ENTITIES ) +#---------- scraper for pirate pages ---------- + class PirateInfo(SomethingSoupInfo): # Public data members: # pi.standings = { 'Treasure Haul': 'Able' ... } @@ -255,6 +266,8 @@ u'\\s*\\S*/([-A-Za-z]+)\\s*$|\\s*\\S*/\\S*\\s*\\(ocean\\-wide(?:\\s|\\xa0)+([-A- def __str__(self): return `(self.crew, self.flag, self.standings, self.msgs)` +#---------- scraper for crew pages ---------- + class CrewInfo(SomethingSoupInfo): # Public data members: # ci.crew = [ ('Captain', ['Pirate', ...]), @@ -303,6 +316,8 @@ class CrewInfo(SomethingSoupInfo): def __str__(self): return `(self.crew, self.msgs)` +#---------- pretty-printer for tables of pirate puzzle standings ---------- + class StandingsTable: def __init__(self, use_puzzles=None, col_width=6): if use_puzzles is None: @@ -366,44 +381,18 @@ class StandingsTable: def results(self): return self.s -def do_pirate(pirates, bu): - print '{' - for pirate in pirates: - info = PirateInfo(pirate) - print '%s: %s,' % (`pirate`, info) - print '}' - -def prep_crew_of(args, bu, max_age=300): - if len(args) != 1: bu('crew-of takes one pirate name') - pi = PirateInfo(args[0], max_age) - if pi.crew is None: return None - return CrewInfo(pi.crew[0], max_age) - -def do_crew_of(args, bu): - ci = prep_crew_of(args, bu) - print ci - -def do_standings_crew_of(args, bu): - ci = prep_crew_of(args, bu, 60) - tab = StandingsTable() - tab.headings() - for (rank, members) in ci.crew: - if not members: continue - tab.literalline('%s:' % rank) - for p in members: - pi = PirateInfo(p, random.randint(900,1800)) - tab.pirate(pi) - print tab.results() +#---------- chat log parser ---------- class PirateAboard: - # pa.v - # pa.name - # pa.last_time - # pa.last_event - # pa.gunner - # pa.last_chat_time - # pa.last_chat_chan - # pa.pi + # This is essentially a transparent, dumb, data class. + # pa.v + # pa.name + # pa.last_time + # pa.last_event + # pa.gunner + # pa.last_chat_time + # pa.last_chat_chan + # pa.pi def __init__(pa, pn, v, time, event): pa.name = pn @@ -421,6 +410,9 @@ class PirateAboard: return pa.pi class ChatLogTracker: + # This is quite complex so we make it opaque. Use the + # official invokers, accessors etc. + def __init__(self, myself_pi, logfn): self._pl = {} # self._pl['Pirate'] = self._vl = {} # self._vl['Vessel']['Pirate'] = PirateAboard @@ -654,6 +646,37 @@ class ChatLogTracker: for pn in sorted(self._v.keys()) if not pn.startswith('#') ] +#---------- implementations of actual operation modes ---------- + +def do_pirate(pirates, bu): + print '{' + for pirate in pirates: + info = PirateInfo(pirate) + print '%s: %s,' % (`pirate`, info) + print '}' + +def prep_crew_of(args, bu, max_age=300): + if len(args) != 1: bu('crew-of takes one pirate name') + pi = PirateInfo(args[0], max_age) + if pi.crew is None: return None + return CrewInfo(pi.crew[0], max_age) + +def do_crew_of(args, bu): + ci = prep_crew_of(args, bu) + print ci + +def do_standings_crew_of(args, bu): + ci = prep_crew_of(args, bu, 60) + tab = StandingsTable() + tab.headings() + for (rank, members) in ci.crew: + if not members: continue + tab.literalline('%s:' % rank) + for p in members: + pi = PirateInfo(p, random.randint(900,1800)) + tab.pirate(pi) + print tab.results() + class ProgressPrintPercentage: def __init__(self, f=sys.stdout): self._f = f def progress(self,done,total): @@ -663,6 +686,8 @@ class ProgressPrintPercentage: self._f.write(' \r') self._f.flush() +#----- modes which use the chat log parser are quite complex ----- + def prep_chat_log(args, bu, progress=ProgressPrintPercentage(), max_myself_age=3600): @@ -743,6 +768,8 @@ def do_ship_aid(args, bu): time.sleep(1) rotate_nya = rotate_nya[1:2] + rotate_nya[0] +#---------- main program ---------- + def main(): global opts, fetcher -- 2.30.2