def build_trips(pfeed, routes, service_by_window):
    """
    Given a ProtoFeed and its corresponding routes (DataFrame),
    service-by-window (dictionary), return a DataFrame representing
    ``trips.txt``.
    Trip IDs encode route, direction, and service window information
    to make it easy to compute stop times later.
    """
    # Put together the route and service data
    routes = pd.merge(routes[['route_id', 'route_short_name']],
      pfeed.frequencies)
    routes = pd.merge(routes, pfeed.service_windows)

    # For each row in routes, add trips at the specified frequency in
    # the specified direction
    rows = []
    for index, row in routes.iterrows():
        shape = row['shape_id']
        route = row['route_id']
        window = row['service_window_id']
        start, end = row[['start_time', 'end_time']].values
        duration = get_duration(start, end, 'h')
        frequency = row['frequency']
        if not frequency:
            # No trips during this service window
            continue
        # Rounding down occurs here if the duration isn't integral
        # (bad input)
        num_trips_per_direction = int(frequency*duration)
        service = service_by_window[window]
        direction = row['direction']
        if direction == 2:
            directions = [0, 1]
        else:
            directions = [direction]
        for direction in directions:
            # Warning: this shape-ID-making logic needs to match that
            # in ``build_shapes``
            shid = '{}{}{}'.format(shape, cs.SEP, direction)
            rows.extend([[
              route,
              cs.SEP.join(['t', route, window, start,
              str(direction), str(i)]),
              direction,
              shid,
              service
            ] for i in range(num_trips_per_direction)])

    return pd.DataFrame(rows, columns=['route_id', 'trip_id', 'direction_id',
      'shape_id', 'service_id'])