def candidatesC(qEnd, BSR, CSR):
  def opdist(bcp):
    bc, ip, raster_link = bcp
    oph = block.choice(bc, ip)
    d = rn.dist(qEnd, path.pini(oph))
    return d
  
  def find_raster_linkA(qEnd, bc, ip, ct):
    B_aux = block.choice(bc, ip)

    if contact.get_raster_link(ct) != [None, None]:
      pIni = path.pini(B_aux)
      links = contact.get_raster_link(ct)

      if links[0] != None:
        p0 = path.pini(links[0])
        q0 = path.pfin(links[0])

        if qEnd == p0 and pIni == q0:
          return links[0]
        
        elif qEnd == q0 and pIni == p0:
          return path.rev(links[0])

      if links[1] != None:
        p1 = path.pini(links[1])
        q1 = path.pfin(links[1])

        if qEnd == p1 and pIni == q1:
          return links[1]
        
        elif qEnd == q1 and pIni == p1:
          return path.rev(links[1])    
    
    return None

  def find_raster_linkB(qEnd, bc, ip, CSR):
    B_aux = block.choice(bc, ip)

    for ct in CSR:
      bc0 = contact.side_block(ct, 0)
      bc1 = contact.side_block(ct, 1)

      if bc0 == bc or bc1 == bc:
        if contact.get_raster_link(ct) != [None, None]:
          p_ini = path.pini(B_aux)
          links = contact.get_raster_link(ct)

          if links[0] != None:
            p0 = path.pini(links[0])
            q0 = path.pfin(links[0])

            if qEnd == p0 and p_ini == q0:
              return links[0]
            
            elif qEnd == q0 and p_ini == p0:
              return path.rev(links[0])

          if links[1] != None:
            p1 = path.pini(links[1])
            q1 = path.pfin(links[1])

            if qEnd == p1 and p_ini == q1:
              return links[1]
            
            elif qEnd == q1 and p_ini == p1:
              return path.rev(links[1])    
      
    return None

  ###

  BOC = []  # Blocks with open contacts.
  BCC = []  # Blocks without open contacts.

  ###

  for ct in CSR:
    bc0 = contact.side_block(ct, 0)
    bc1 = contact.side_block(ct, 1)
    
    done0 = block.used(bc0)
    done1 = block.used(bc1)

    if (done0 == True and done1 == False) or (done0 == False and done1 == True):
      bc = bc0 if done0 == False else bc1

      np = block.nchoices(bc)

      for ip in range(np):
        raster_link = find_raster_linkA(qEnd, bc, ip, ct)
        bcp = (bc, ip, raster_link)

        if bcp not in BOC and bc in BSR:
          BOC.append(bcp)
        
      BSR = remove_block(BSR, bc)

  ###

  y_dict = dict()
  y_list = list()

  for bc in BSR:
    y_aux = block.get_y(bc, 0)

    not_in_list = True   

    for y in y_dict.keys():
      if txt_read.is_equal(y, y_aux, 0.05):
        y_dict[y].append(bc)
        not_in_list = False
    
    if not_in_list:
      y_dict[y_aux] = []
      y_dict[y_aux].append(bc)
      y_list.append(y_aux)
  
  y_list.sort()

  if y_list != []:
    for bc in y_dict[y_list[0]]:
      np = block.nchoices(bc)

      for ip in range(np):
        bcp = (bc, ip, None)
        raster_link = find_raster_linkB(qEnd, bc, ip, CSR)
        bcp = (bc, ip, raster_link)

        BOC.append(bcp)
      
      BSR = remove_block(BSR, bc)  
  
  ###

  for bc in BSR:
    np = block.nchoices(bc)

    for ip in range(np):
      bcp = (bc, ip, None)

      if bcp not in BOC and bcp not in BCC:
        BCC.append(bcp)

  ###

  BOC.sort(key = opdist)
  BCC.sort(key = opdist)

  NEW_BCPS = BOC + BCC

  return tuple(NEW_BCPS)