docs: def gen_schedule(user, num_blocks=6, surrounding_blocks=None):
      """Generate a list of information about a block and a student's current activity signup.
  
      Returns:
          schedule
          no_signup_today
  
      """
      no_signup_today = None
      schedule = []
  
      if surrounding_blocks is None:
          surrounding_blocks = EighthBlock.objects.get_upcoming_blocks(num_blocks)
  
      if len(surrounding_blocks) == 0:
          return None, False
  
      # Use select_related to reduce query count
      signups = (EighthSignup.objects.filter(user=user, scheduled_activity__block__in=surrounding_blocks).select_related(
          "scheduled_activity", "scheduled_activity__block", "scheduled_activity__activity"))
      block_signup_map = {s.scheduled_activity.block.id: s.scheduled_activity for s in signups}
  
      for b in surrounding_blocks:
          current_sched_act = block_signup_map.get(b.id, None)
          if current_sched_act:
              current_signup = current_sched_act.title_with_flags
              current_signup_cancelled = current_sched_act.cancelled
              current_signup_sticky = current_sched_act.activity.sticky
              rooms = current_sched_act.get_scheduled_rooms()
          else:
              current_signup = None
              current_signup_cancelled = False
              current_signup_sticky = False
              rooms = None
  
          # warning flag (red block text and signup link) if no signup today
          # cancelled flag (red activity text) if cancelled
          flags = "locked" if b.locked else "open"
          blk_today = b.is_today()
          if blk_today and not current_signup:
              flags += " warning"
          if current_signup_cancelled:
              flags += " cancelled warning"
  
          if current_signup_cancelled:
              # don't duplicate this info; already caught
              current_signup = current_signup.replace(" (Cancelled)", "")
  
          info = {
              "id": b.id,
              "block": b,
              "block_letter": b.block_letter,
              "current_signup": current_signup,
              "current_signup_cancelled": current_signup_cancelled,
              "current_signup_sticky": current_signup_sticky,
              "locked": b.locked,
              "date": b.date,
              "flags": flags,
              "is_today": blk_today,
              "signup_time": b.signup_time,
              "signup_time_future": b.signup_time_future,
              "rooms": rooms
          }
          schedule.append(info)
  
          if blk_today and not current_signup:
              no_signup_today = True
  
      return schedule, no_signup_today