Browse Source

[code] orari dopo le 24

che mufhd0 ce la manni bona
se si rompono cose, QUESTO è il commit da revertare

madonna la monnezza che ho fatto
boyska 5 years ago
parent
commit
eb3754ce0b
2 changed files with 135 additions and 84 deletions
  1. 132 81
      plugins/talks.py
  2. 3 3
      talks/_templates/grid.html

+ 132 - 81
plugins/talks.py

@@ -100,6 +100,25 @@ def get_global_data():
     return data
 
 
+def _get_time_shift(timestring):
+    ''' Il problema che abbiamo è che vogliamo dire che le 2 di notte del sabato sono in realtà "parte" del
+    venerdì. Per farlo accettiamo orari che superano le 24, ad esempio 25.30 vuol dire 1.30.
+
+    Questa funzione ritorna una timedelta in base alla stringa passata
+    '''
+    timeparts = re.findall(r'\d+', timestring)
+    if not timeparts or len(timeparts) > 2:
+        raise ValueError("Malformed time %s" % timestring)
+    timeparts += [0,0]  # "padding" per essere sicuro ci siano anche [1] e [2]
+    duration = datetime.timedelta(hours=int(timeparts[0]),
+            minutes=int(timeparts[1]),
+            seconds=int(timeparts[2]))
+    if duration.total_seconds() > 3600 * 31 or duration.total_seconds() < 0:
+        raise ValueError("Sforamento eccessivo: %d" % duration.hours)
+    return duration
+
+
+
 @memoize
 def get_talk_data(talkname):
     fname = os.path.join(pelican.settings['TALKS_PATH'], talkname, 'meta.yaml')
@@ -155,15 +174,18 @@ def get_talk_data(talkname):
         else:
             data['day'] = get_global_data()['startdate'] + \
                     datetime.timedelta(days=data['day'])
-            timeparts = re.findall(r'\d+', str(data['time']))
-            if 4 > len(timeparts) > 0:
-                timeparts = [int(p) for p in timeparts]
-                data['time'] = datetime.datetime.combine(
-                    data['day'], datetime.time(*timeparts))
-                data['time'] = data['time'].replace(
-                    tzinfo=dateutil.tz.gettz('Europe/Rome'))
-            else:
+            try:
+                shift = _get_time_shift(str(data['time']))
+            except ValueError:
                 logging.error("Talk <%s> has malformed `time`", talkname)
+
+            data['delta'] = shift
+            data['time'] = datetime.datetime.combine(
+                                      data['day'], datetime.time(0,0,0))
+            data['time'] += shift
+            data['time'] = data['time'].replace(tzinfo=dateutil.tz.gettz('Europe/Rome'))
+
+
         data['id'] = talkname
         resdir = os.path.join(pelican.settings['TALKS_PATH'], talkname,
                               pelican.settings['TALKS_ATTACHMENT_PATH'])
@@ -282,6 +304,27 @@ class TalkDirective(Directive):
         ]
 
 
+def _delta_to_position(delta):
+    gridstep = pelican.settings['TALKS_GRID_STEP']
+    sec = delta.total_seconds() // gridstep * gridstep
+    return int('%2d%02d' % (sec // 3600, (sec % 3600) // 60))
+
+
+def _delta_inc_position(delta, i):
+    gridstep = pelican.settings['TALKS_GRID_STEP']
+    delta = delta + datetime.timedelta(minutes=i*gridstep)
+    sec = delta.total_seconds() // gridstep * gridstep
+    return int('%2d%02d' % (sec // 3600, (sec % 3600) // 60))
+
+def _approx_timestr(timestr):
+    gridstep = pelican.settings['TALKS_GRID_STEP']
+    t = str(timestr)
+    minutes = int(t[-2:])
+    hours = t[:-2]
+    minutes = minutes // gridstep * gridstep
+    return int('%s%02d' % (hours, minutes))
+
+
 class TalkGridDirective(Directive):
     '''A complete grid'''
     final_argument_whitespace = True
@@ -291,79 +334,87 @@ class TalkGridDirective(Directive):
     }
 
     def run(self):
-        lang = self.options.get('lang', 'C')
-        tmpl = jinja_env().get_template('grid.html')
-        output = []
-        days = unique_attr(all_talks(), 'day')
-        gridstep = pelican.settings['TALKS_GRID_STEP']
-        for day in sorted(days):
-            talks = {talk['id'] for talk in all_talks()
-                     if talk.get('day', None) == day
-                     and 'time' in talk
-                     and 'room' in talk}
-            if not talks:
-                continue
-            talks = [get_talk_data(t) for t in talks]
-            rooms = set()
-            for t in talks:
-                if type(t['room']) is list:
-                    for r in t['room']:
-                        rooms.add(r)
-                else:
-                    rooms.add(t['room'])
-            # TODO: ordina in base a qualcosa nel meta.yaml globale
-            rooms = list(sorted(rooms))
-
-            # room=* is not a real room.
-            # Remove it unless that day only has special rooms
-            if '*' in rooms and len(rooms) > 1:
-                del rooms[rooms.index('*')]
-            mintime = min({talk['time'].hour * 60 +
-                           talk['time'].minute
-                           for talk in talks}) // gridstep * gridstep
-            maxtime = max({talk['time'].hour * 60 +
-                           talk['time'].minute +
-                           talk['duration']
-                           for talk in talks})
-            times = {}
-
-            for t in range(mintime, maxtime, gridstep):
-                times[t] = [None] * len(rooms)
-            for talk in sorted(talks, key=lambda x: x['time']):
-                talktime = talk['time'].hour * 60 + talk['time'].minute
-                position = talktime // gridstep * gridstep  # round
-                assert position in times
-                if talk['room'] == '*':
-                    roomnums = range(len(rooms))
-                elif type(talk['room']) is list:
-                    roomnums = [rooms.index(r) for r in talk['room']]
-                else:
-                    roomnums = [rooms.index(talk['room'])]
-                for roomnum in roomnums:
-                    if times[position][roomnum] is not None:
-                        logging.error("Talk %s and %s overlap! (room %s)",
-                                      times[position][roomnum]['id'],
-                                      talk['id'],
-                                      rooms[roomnum]
-                                      )
-                        continue
-                    times[position][roomnum] = copy(talk)
-                    times[position][roomnum]['skip'] = False
-                    for i in range(1, talk['duration'] // gridstep):
-                        times[position + i*gridstep][roomnum] = copy(talk)
-                        times[position + i*gridstep][roomnum]['skip'] = True
-
-            render = tmpl.render(times=times,
-                                 rooms=rooms,
-                                 mintime=mintime, maxtime=maxtime,
-                                 timestep=gridstep,
-                                 lang=lang,
-                                 )
-            output.append(nodes.raw(
-                '', u'<h4>%s</h4>' % format_date(day, format='full',
-                                                 locale=lang),
-                format='html'))
-            output.append(nodes.raw('', render, format='html'))
+        try:
+            lang = self.options.get('lang', 'C')
+            tmpl = jinja_env().get_template('grid.html')
+            output = []
+            days = unique_attr(all_talks(), 'day')
+            gridstep = pelican.settings['TALKS_GRID_STEP']
+            for day in sorted(days):
+                talks = {talk['id'] for talk in all_talks()
+                         if talk.get('day', None) == day
+                         and 'time' in talk
+                         and 'room' in talk}
+                if not talks:
+                    continue
+                talks = [get_talk_data(t) for t in talks]
+                rooms = set()
+                for t in talks:
+                    if type(t['room']) is list:
+                        for r in t['room']:
+                            rooms.add(r)
+                    else:
+                        rooms.add(t['room'])
+                # TODO: ordina in base a qualcosa nel meta.yaml globale
+                rooms = list(sorted(rooms))
+
+                # room=* is not a real room.
+                # Remove it unless that day only has special rooms
+                if '*' in rooms and len(rooms) > 1:
+                    del rooms[rooms.index('*')]
+                mintimedelta = min({talk['delta'] for talk in talks})
+                maxtimedelta = max({talk['delta'] + datetime.timedelta(minutes=talk['duration']) for talk in talks})
+                mintime = _delta_to_position(mintimedelta)
+                maxtime = _delta_to_position(maxtimedelta)
+                times = {}
+
+                t = mintimedelta
+                while t <= maxtimedelta:
+                    times[_delta_to_position(t)] = [None] * len(rooms)
+                    t += datetime.timedelta(minutes=gridstep)
+                print(list(times.keys()))
+                for talk in sorted(talks, key=lambda x: x['delta']):
+                    talktime = _delta_to_position(talk['delta'])
+                    position = _approx_timestr(talktime)
+                    assert position in times, 'pos=%d,time=%d' % (position, talktime)
+                    if talk['room'] == '*':
+                        roomnums = range(len(rooms))
+                    elif type(talk['room']) is list:
+                        roomnums = [rooms.index(r) for r in talk['room']]
+                    else:
+                        roomnums = [rooms.index(talk['room'])]
+                    for roomnum in roomnums:
+                        if times[position][roomnum] is not None:
+                            logging.error("Talk %s and %s overlap! (room %s)",
+                                          times[position][roomnum]['id'],
+                                          talk['id'],
+                                          rooms[roomnum]
+                                          )
+                            continue
+                        times[position][roomnum] = copy(talk)
+                        times[position][roomnum]['skip'] = False
+                        for i in range(1, talk['duration'] // gridstep):
+                            p = _approx_timestr(_delta_inc_position(talk['delta'], i))
+                            times[p][roomnum] = copy(talk)
+                            times[p][roomnum]['skip'] = True
+
+
+                render = tmpl.render(times=times,
+                                     rooms=rooms,
+                                     mintime=mintime, maxtime=maxtime,
+                                     timestep=gridstep,
+                                     lang=lang,
+                                     )
+                output.append(nodes.raw(
+                    '', u'<h4>%s</h4>' % format_date(day, format='full',
+                                                     locale=lang),
+                    format='html'))
+                output.append(nodes.raw('', render, format='html'))
+        except:
+            logging.exception("Error on talk grid")
+            import traceback
+            traceback.print_exc()
+            return []
         return output
 
 

+ 3 - 3
talks/_templates/grid.html

@@ -8,10 +8,10 @@
         </tr>
     </thead>
     <tbody>
-        {% for time in range (mintime, maxtime, timestep) %}
+        {% for time in times %}
         <tr>
-            <td>{{time//60}}:{{ "%02d" % (time % 60)}}</td>
-            {% for talk in times[time / timestep * timestep] %}
+            <td>{{time}}</td>
+            {% for talk in times[time] %}
                 {% if not loop.first and talk.room == '*' %}
                     {# skip: covered by colspan #}
                 {% elif talk == None %}