<commit_before>import _ from 'lodash';
import { AirParsingError } from './AirErrors';

function getBaggage(baggageAllowance) {
  // Checking for allowance
  if (
    !baggageAllowance ||
    (
      !baggageAllowance['air:NumberOfPieces'] &&
      !baggageAllowance['air:MaxWeight']
    )
  ) {
    console.warn('Baggage information is not number and is not weight!', JSON.stringify(baggageAllowance));
    return { units: 'piece', amount: 0 };
  }
  // Checking for max weight
  if (baggageAllowance['air:MaxWeight']) {
    return {
      units: baggageAllowance['air:MaxWeight'].Unit.toLowerCase(),
      amount: Number(baggageAllowance['air:MaxWeight'].Value),
    };
  }
  // Returning pieces
  return {
    units: 'piece',
    amount: Number(baggageAllowance['air:NumberOfPieces']),
  };
}

function formatTrip(segment, flightDetails) {
  const flightInfo = Object.keys(flightDetails).map(
    detailsKey => flightDetails[detailsKey]
  );
  const plane = flightInfo.map(details => details.Equipment);
  const duration = flightInfo.map(details => details.FlightTime);
  const techStops = flightInfo.slice(1).map(details => details.Origin);
  return {
    from: segment.Origin,
    to: segment.Destination,
    departure: segment.DepartureTime,
    arrival: segment.ArrivalTime,
    airline: segment.Carrier,
    flightNumber: segment.FlightNumber,
    serviceClass: segment.CabinClass,
    plane,
    duration,
    techStops,
    uapi_segment_ref: segment.ProviderReservationInfoRef || segment.Key,
  };
}

function formatLowFaresSearch(searchRequest, searchResult) {
  const pricesList = searchResult['air:AirPricePointList'];
  const fareInfos = searchResult['air:FareInfoList'];
  const segments = searchResult['air:AirSegmentList'];
  const flightDetails = searchResult['air:FlightDetailsList'];

  // const legs = _.first(_.toArray(searchResult['air:RouteList']))['air:Leg'];

  // TODO filter pricesList by CompleteItinerary=true & ETicketability = Yes, etc

  const fares = [];

  _.forEach(pricesList, (price, fareKey) => {
    const firstKey = _.first(Object.keys(price['air:AirPricingInfo']));
    const thisFare = price['air:AirPricingInfo'][firstKey]; // get trips from first reservation
    if (!thisFare.PlatingCarrier) {
      return;
    }

    const directions = _.map(thisFare['air:FlightOptionsList'], direction =>
      _.map(direction['air:Option'], (option) => {
        const trips = option['air:BookingInfo'].map(
          (segmentInfo) => {
            const fareInfo = fareInfos[segmentInfo.FareInfoRef];
            const segment = segments[segmentInfo.SegmentRef];
            const tripFlightDetails = segment['air:FlightDetailsRef'].map(
              flightDetailsRef => flightDetails[flightDetailsRef]
            );
            const seatsAvailable = (
              segment['air:AirAvailInfo'] &&
              segment['air:AirAvailInfo'].ProviderCode === '1G'
            ) ? (Number(
              segment['air:AirAvailInfo']['air:BookingCodeInfo'].BookingCounts
                .match(new RegExp(`${segmentInfo.BookingCode}(\\d+)`))[1]
            )) : null;
            return Object.assign(
              formatTrip(segment, tripFlightDetails),
              {
                serviceClass: segmentInfo.CabinClass,
                bookingClass: segmentInfo.BookingCode,
                baggage: [getBaggage(fareInfo['air:BaggageAllowance'])],
              },
              seatsAvailable ? { seatsAvailable } : null,
            );
          }
        );
        return {
          from: direction.Origin,
          to: direction.Destination,
          // duration
          // TODO get overnight stops, etc from connection
          platingCarrier: thisFare.PlatingCarrier,
          segments: trips,
        };
      })
    );

<commit_msg>Added back fareBasis<commit_after>import _ from 'lodash';
import { AirParsingError } from './AirErrors';

function getBaggage(baggageAllowance) {
  // Checking for allowance
  if (
    !baggageAllowance ||
    (
      !baggageAllowance['air:NumberOfPieces'] &&
      !baggageAllowance['air:MaxWeight']
    )
  ) {
    console.warn('Baggage information is not number and is not weight!', JSON.stringify(baggageAllowance));
    return { units: 'piece', amount: 0 };
  }
  // Checking for max weight
  if (baggageAllowance['air:MaxWeight']) {
    return {
      units: baggageAllowance['air:MaxWeight'].Unit.toLowerCase(),
      amount: Number(baggageAllowance['air:MaxWeight'].Value),
    };
  }
  // Returning pieces
  return {
    units: 'piece',
    amount: Number(baggageAllowance['air:NumberOfPieces']),
  };
}

function formatTrip(segment, flightDetails) {
  const flightInfo = Object.keys(flightDetails).map(
    detailsKey => flightDetails[detailsKey]
  );
  const plane = flightInfo.map(details => details.Equipment);
  const duration = flightInfo.map(details => details.FlightTime);
  const techStops = flightInfo.slice(1).map(details => details.Origin);
  return {
    from: segment.Origin,
    to: segment.Destination,
    departure: segment.DepartureTime,
    arrival: segment.ArrivalTime,
    airline: segment.Carrier,
    flightNumber: segment.FlightNumber,
    serviceClass: segment.CabinClass,
    plane,
    duration,
    techStops,
    uapi_segment_ref: segment.ProviderReservationInfoRef || segment.Key,
  };
}

function formatLowFaresSearch(searchRequest, searchResult) {
  const pricesList = searchResult['air:AirPricePointList'];
  const fareInfos = searchResult['air:FareInfoList'];
  const segments = searchResult['air:AirSegmentList'];
  const flightDetails = searchResult['air:FlightDetailsList'];

  // const legs = _.first(_.toArray(searchResult['air:RouteList']))['air:Leg'];

  // TODO filter pricesList by CompleteItinerary=true & ETicketability = Yes, etc

  const fares = [];

  _.forEach(pricesList, (price, fareKey) => {
    const firstKey = _.first(Object.keys(price['air:AirPricingInfo']));
    const thisFare = price['air:AirPricingInfo'][firstKey]; // get trips from first reservation
    if (!thisFare.PlatingCarrier) {
      return;
    }

    const directions = _.map(thisFare['air:FlightOptionsList'], direction =>
      _.map(direction['air:Option'], (option) => {
        const trips = option['air:BookingInfo'].map(
          (segmentInfo) => {
            const fareInfo = fareInfos[segmentInfo.FareInfoRef];
            const segment = segments[segmentInfo.SegmentRef];
            const tripFlightDetails = segment['air:FlightDetailsRef'].map(
              flightDetailsRef => flightDetails[flightDetailsRef]
            );
            const seatsAvailable = (
              segment['air:AirAvailInfo'] &&
              segment['air:AirAvailInfo'].ProviderCode === '1G'
            ) ? (Number(
              segment['air:AirAvailInfo']['air:BookingCodeInfo'].BookingCounts
                .match(new RegExp(`${segmentInfo.BookingCode}(\\d+)`))[1]
            )) : null;
            return Object.assign(
              formatTrip(segment, tripFlightDetails),
              {
                serviceClass: segmentInfo.CabinClass,
                bookingClass: segmentInfo.BookingCode,
                baggage: [getBaggage(fareInfo['air:BaggageAllowance'])],
                fareBasisCode: fareInfo.FareBasis,
              },
              seatsAvailable ? { seatsAvailable } : null,
            );
          }
        );
        return {
          from: direction.Origin,
          to: direction.Destination,
          // duration
          // TODO get overnight stops, etc from connection
          platingCarrier: thisFare.PlatingCarrier,
          segments: trips,
        };
      })
    );


{'fraction_non_alphanumeric': 0.1235587002096436, 'fraction_numerical': 0.0010482180293501049, 'mean_word_length': 2.93859649122807, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1438584', 'n_tokens_mistral': 2227, 'n_tokens_neox': 2180, 'n_words': 396}