Handle pending and recovering states from the journal.
authorCMDR furrycat <elite@furrycat.net>
Tue, 27 Jun 2017 17:13:28 +0000 (18:13 +0100)
committerCMDR furrycat <elite@furrycat.net>
Tue, 27 Jun 2017 17:13:28 +0000 (18:13 +0100)
plugin/faction/faction.py

index 2c90b49..a062587 100644 (file)
@@ -57,6 +57,8 @@ class Faction(DBConnection):
     cursor = self.query('create index if not exists faction_influence_system on faction_influence (eddb_id)')
     cursor = self.query('create index if not exists faction_influence_faction on faction_influence (faction_id)')
     cursor = self.query('create unique index if not exists faction_influence_checksum on faction_influence (checksum, eddb_id, faction_id)')
+    cursor = self.query('create table if not exists faction_trend (checksum char(32) not null, eddb_id int not null, faction_id int not null, state_id int not null, trend int not null, pending boolean)')
+    cursor = self.query('create unique index if not exists faction_trend_state on faction_trend (checksum, eddb_id, faction_id, pending)')
     self.dbh.commit()
     self.close_db()
 
@@ -819,6 +821,11 @@ class Faction(DBConnection):
     update = False
     announce = {}
     for faction in factions:
+      trending_states = []
+      if 'PendingStates' in faction:
+        trending_states += map(lambda s: (eddb.get_state_id(s['State']), s['Trend'], 'true'), faction['PendingStates'])
+      if 'RecoveringStates' in faction:
+        trending_states += map(lambda s: (eddb.get_state_id(s['State']), s['Trend'], 'false'), faction['RecoveringStates'])
       state_id = eddb.get_state_id(faction['FactionState'])
       if state_id is None:
         state_id = eddb.get_state_id('None')
@@ -845,6 +852,17 @@ class Faction(DBConnection):
       if not cursor.rowcount:
         log.debug('No update for {} with checksum {}'.format(system, checksum))
         update = True
+      if len(trending_states):
+        sql = 'insert or ignore into faction_trend values '
+        clauses = []
+        params = []
+        for trending_tuple in trending_states:
+          clauses.append('(?, ?, ?, ?, ?, ?)')
+          params += [checksum, system_id, faction_id]
+          params += list(trending_tuple)
+        sql += ', '.join(clauses)
+        cursor = self.query(sql, params)
+
     if update:
       # We need a value for faction_id to use the index.
       cursor = self.query('update faction_influence set timestamp=? where checksum=? and eddb_id=? and faction_id>0', [timestamp, checksum, system_id])
@@ -856,10 +874,28 @@ class Faction(DBConnection):
       log.debug('Updated influence in {}: {}'.format(system, influence))
       for system, channel in announce.items():
         await self.report_faction_influence(channel, system = system, update = True, yelp_if_no_data = False)
-
     self.close_db()
     return True
 
+  def null_report(self):
+    return { 'faction_id': 0, 'text': '', 'state': '', 'pending': [], 'recovering': [] }
+
+  def format_report(self, report, *, id = None):
+    if not report['text']:
+      return None
+
+    states = [report['state']]
+    for key in ['pending', 'recovering']:
+      if len(report[key]):
+        states.append('{} {}'.format(key, ', '.join(report[key])))
+
+    line = '{} ({})'.format(report['text'], '; '.join(states))
+
+    if report['faction_id'] == id:
+      line = '**{}**'.format(line)
+
+    return line
+
   async def report_faction_influence(self, destination, *, id = None, name = None, system = None, update = False, yelp_if_no_data = True):
     if id is None:
       if name is None:
@@ -872,7 +908,7 @@ class Faction(DBConnection):
           log.error("Can't report influence of unknown faction {}".format(name))
           return False
 
-    sql = 'select s.name as system_name, i.timestamp as timestamp, i.faction_id as faction_id, n.name as faction_name, i.influence as influence, i.state_id as state_id from faction_influence i, faction_systems s, faction_names n, (select eddb_id, max(timestamp) as timestamp from faction_influence group by eddb_id) j where i.faction_id=n.faction_id and i.eddb_id=s.eddb_id and i.timestamp=j.timestamp'
+    sql = 'select s.name as system_name, i.timestamp as timestamp, i.faction_id as faction_id, n.name as faction_name, i.influence as influence, i.state_id as state_id, t.pending as pending, t.state_id as pending_state_id, t.trend as trend from faction_influence i, faction_systems s, faction_names n, (select eddb_id, max(timestamp) as timestamp from faction_influence group by eddb_id) j left join faction_trend t using(checksum, eddb_id, faction_id) where i.faction_id=n.faction_id and i.eddb_id=s.eddb_id and i.timestamp=j.timestamp'
     params = []
     if id is not None:
       sql += ' and i.eddb_id in (select distinct eddb_id from faction_influence where faction_id=?)'
@@ -880,24 +916,38 @@ class Faction(DBConnection):
     if system is not None:
       sql += ' and s.name=?'
       params.append(system)
-    sql += ' order by system_name, influence desc'
+    sql += ' order by system_name, influence desc, pending, trend desc'
     cursor = self.query(sql, params)
+    report = {}
     last_system = ''
     lines = []
+    report = self.null_report()
     for row in cursor.fetchall():
       if row['system_name'] != last_system:
         if len(lines):
           lines.append('** **')
           await bot.say_many(destination, lines)
           lines = []
-        log.info('Reporting {} influence to {}'.format(row['system_name'], destination))
+          report = self.null_report()
         lines.append('{}__Influence in **{}** at *{}*__'.format('News flash: ' if update else '', row['system_name'], bot.iso8601(row['timestamp'])))
         lines.append(' ')
       last_system = row['system_name']
-      line = '{} {:.2f}% ({})'.format(row['faction_name'], row['influence'] * 100.0, eddb.state_name(row['state_id']))
-      if row['faction_id'] == id:
-        line = '**{}**'.format(line)
+      if row['faction_id'] != report['faction_id']:
+        line = self.format_report(report, id = id)
+        if line is not None:
+          lines.append(line)
+        report = self.null_report()
+      report['faction_id'] = row['faction_id']
+      report['text'] = '{} {:.2f}%'.format(row['faction_name'], row['influence'] * 100.0)
+      report['state'] = eddb.state_name(row['state_id'])
+      if row['trend'] is not None:
+        key = 'pending' if bot.parse_boolean(row['pending']) else 'recovering'
+        report[key].append('{} {}'.format(eddb.state_name(row['pending_state_id']), row['trend']))
+
+    line = self.format_report(report, id = id)
+    if line is not None:
       lines.append(line)
+
     if len(lines):
       lines.append('** **')
       await bot.say_many(destination, lines)