def _render_multirow(events, time_map, max_height): """Render a complex format that contains a multi-row R3 event. """ sp_event, *events = events # Sort events by time, and then location. This is done here because # we need to exclude the R3 event (by putting it first). events = sorted(events, key=lambda e: (e.begin_time.value, e.location)) event_iter = iter(events) # Render R0-R2 events in the first time period. cells = _render_multirow_subrow(event_iter, time_map, events) # Render the multi-row R3 event. cells.extend([ render_attached_period(sp_event.begin_time, sp_event.end_time), render_block( sp_event, time_map, events, ['pull-right'], max_height=max_height, ), ]) # Render the rest of the events. try: while True: cells += _render_multirow_subrow(event_iter, time_map, events) except StopIteration: pass # Join the results. return html_join('', cells)
def render_table(day): events = itertools.chain.from_iterable( _filter_events(Cls, day) for Cls in EVENT_CLASSES ) groups = collect_event_groups(events) head = mark_safe(""" <div class="time-table__header"> <div class="time-table__time"></div> <div class="time-table__slot"> <div class="row"> <div class="slot-item header-cell header-cell--r0">R0</div> <div class="slot-item header-cell header-cell--r1">R1</div> <div class="slot-item header-cell header-cell--r2">R2</div> <div class="slot-item header-cell header-cell--r3">R3</div> </div> </div> </div> """) body = html_join('', ( render_row(times, group) for times, group in groups.items() )) return format_html( '<div class="time-table clearfix">{head}{body}</div>', head=head, body=body, )
def block_diff(current, snapshot): return html_join( mark_safe('<br>'), difftools.make_diff( snapshot.splitlines(), current.splitlines(), ))
def _render_blocks(events, time_map): """Render a R0-3 belt, a R0-2 partial belt (plus optionally a R3 event), or an all-block (with or without R3) format. """ if events[0].location == Location.R3: # If this contains R3, shuffle it to the back. r3_event, *events = events # If this is not a smooth row, we need to prevent any block from # being rendered as short because we can't handle it with multi-height. if any(r3_event.end_time != e.end_time for e in events): min_height = 1 else: min_height = 0 r3_block = render_block( r3_event, time_map, events, min_height=min_height, ) else: r3_event = None r3_block = '' # Render period block for R3. # We cheat a little here: Times in R0-2 are supposed to be identical; # only R3 can be different. We just compare the first event's times # and R3's. If they are identical, R3 does not need its own period block, # otherwise it does. r3_period = '' rx_begin, rx_end = events[0].begin_time, events[0].end_time if r3_event: r3_begin = r3_event.begin_time r3_end = r3_event.end_time if r3_begin != rx_begin or r3_end != rx_end: r3_period = render_attached_period(r3_begin, r3_end) return format_html( '{r012_period}{r012_blocks}{r3_period}{r3_block}', r012_period=render_attached_period(rx_begin, rx_end), r012_blocks=html_join( '', (render_block(e, time_map, events) for e in events), ), r3_period=r3_period, r3_block=r3_block, )
def render_all(): return html_join('', ( render_day(day, display) for day, display in settings.EVENTS_DAY_NAMES.items() ))
def dump_replace(a, b, alo, blo, ahi, bhi): # noqa # Based on `difflib.Differ._fancy_replace`. # When replacing one block of lines with another, search the blocks # for *similar* lines; the best-matching pair (if any) is used as a # sync point, and intraline difference marking is done on the # similar pair. Lots of work, but often worth it. best_ratio = 0 cutoff = 0.8 cruncher = difflib.SequenceMatcher(difflib.IS_CHARACTER_JUNK) eqi, eqj = None, None # Search for the first sync point. for j in range(blo, bhi): bj = b[j] cruncher.set_seq2(bj) for i in range(alo, ahi): ai = a[i] if ai == bj: if eqi is None: eqi, eqj = i, j continue cruncher.set_seq1(ai) if (cruncher.real_quick_ratio() > best_ratio and cruncher.quick_ratio() > best_ratio and cruncher.ratio() > best_ratio): best_ratio, best_i, best_j = cruncher.ratio(), i, j # No "pretty close" pair. if best_ratio < cutoff: if eqi is None: # No identical pairs. Just dump. yield from dump_delete(a, b, alo, blo, ahi, bhi) yield from dump_insert(a, b, alo, blo, ahi, bhi) return # There's an identical pair. Use that. best_i, best_j, best_ratio = eqi, eqj, 1.0 else: eqi = None # Dump things before the sync point. yield from replace_helper(a, alo, best_i, b, blo, best_j) # Intraline marking. aelt, belt = a[best_i], b[best_j] if eqi is None: atags = [] btags = [] cruncher.set_seqs(aelt, belt) for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes(): acon, bcon = aelt[ai1:ai2], belt[bj1:bj2] if tag == 'replace': atags.append(format_html('<del>{}</del>', acon)) btags.append(format_html('<ins>{}</ins>', bcon)) elif tag == 'delete': atags.append(format_html('<del>{}</del>', acon)) elif tag == 'insert': btags.append(format_html('<ins>{}</ins>', bcon)) else: # Equal. atags.append(acon) btags.append(bcon) yield format_html('<del>{}</del>', html_join('', atags)) yield format_html('<ins>{}</ins>', html_join('', btags)) else: # Identical. yield aelt # Dump things after the sync point. yield from replace_helper(a, best_i + 1, ahi, b, best_j + 1, bhi)
def render_all(): return html_join('', ( render_day(day, display) for day, display in DAY_NAMES.items() ))
def dump_replace(a, b, alo, blo, ahi, bhi): # Based on `difflib.Differ._fancy_replace`. # When replacing one block of lines with another, search the blocks # for *similar* lines; the best-matching pair (if any) is used as a # sync point, and intraline difference marking is done on the # similar pair. Lots of work, but often worth it. best_ratio = 0 cutoff = 0.8 cruncher = difflib.SequenceMatcher(difflib.IS_CHARACTER_JUNK) eqi, eqj = None, None # Search for the first sync point. for j in range(blo, bhi): bj = b[j] cruncher.set_seq2(bj) for i in range(alo, ahi): ai = a[i] if ai == bj: if eqi is None: eqi, eqj = i, j continue cruncher.set_seq1(ai) if (cruncher.real_quick_ratio() > best_ratio and cruncher.quick_ratio() > best_ratio and cruncher.ratio() > best_ratio): best_ratio, best_i, best_j = cruncher.ratio(), i, j # No "pretty close" pair. if best_ratio < cutoff: if eqi is None: # No identical pairs. Just dump. yield from dump_delete(a, b, alo, blo, ahi, bhi) yield from dump_insert(a, b, alo, blo, ahi, bhi) return # There's an identical pair. Use that. best_i, best_j, best_ratio = eqi, eqj, 1.0 else: eqi = None # Dump things before the sync point. yield from replace_helper(a, alo, best_i, b, blo, best_j) # Intraline marking. aelt, belt = a[best_i], b[best_j] if eqi is None: atags = [] btags = [] cruncher.set_seqs(aelt, belt) for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes(): acon, bcon = aelt[ai1:ai2], belt[bj1:bj2] if tag == 'replace': atags.append(format_html('<del>{}</del>', acon)) btags.append(format_html('<ins>{}</ins>', bcon)) elif tag == 'delete': atags.append(format_html('<del>{}</del>', acon)) elif tag == 'insert': btags.append(format_html('<ins>{}</ins>', bcon)) else: # Equal. atags.append(acon) btags.append(bcon) yield format_html('<del>{}</del>', html_join('', atags)) yield format_html('<ins>{}</ins>', html_join('', btags)) else: # Identical. yield aelt # Dump things after the sync point. yield from replace_helper(a, best_i + 1, ahi, b, best_j + 1, bhi)