<commit_before>let config = require('../config/global');
let BaseDataService = require('./baseDataService');

class LineDataService extends BaseDataService {

  constructor(lineRepository) {
    super();
    this.lineRepository = lineRepository;
  }

  updateDayBusLines() {
    return this.updateData('bus', true);
  }

  updateNightBusLines() {
    return this.updateData('bus', false);
  }

  updateDayTramLines() {
    return this.updateData('tram', true);
  }

  updateNightTramLines() {
    return this.updateData('tram', false);
  }

  updateData(lineType, day) {
    return this.getLines(lineType, day)
               .then(this.getDirections.bind(this));
  }

  getLines(lineType, day) {
    let url = this.getUrl(lineType, day);
    return this.fetchDataFromApi(url)
      .then((responseBody) => {
        let data = this.extractJson(responseBody);
        if (data.status !== 'ok') {
          throw Error(`api ${url} responses with status: ${data.status}`);
        }

        return data.lines.map((line) => {
          return { 
            name: line,
            type: lineType,
            day: day
          };
        });
      });
  }

  getDirections(lines) {
    if (!lines.length) {
      return Promise.resolve();
    }

    let createFunction = (line) => {
      return () => {
        return this.createPromiseForLine(line);
      };
    };

    /*
    It would be better, but in environments with small RAM 
    it exhauts all resoruces and system stops.

    let promises = lines.map(this.createPromiseForLine.bind(this));
    return Promise.all(promises);
    */     
    let promise = this.createPromiseForLine(lines[0]);
    for (let i = 1; i < lines.length; i++) {
      let next = createFunction(lines[i]);
      promise = promise.then(next);
    }
    return promise;
  }

  createPromiseForLine(line) {
    return this.fetchDirections(line)
      .then(this.persistLine.bind(this));
  }

  fetchDirections(line) {
    let url = config.services.linesDataService
                  .directionsApiUrlFormat.replace('<<line>>', line.name);
    return this.fetchDataFromApi(url)
      .then((responseBody) => {
        let data = this.extractJson(responseBody);
        if (data.status !== 'ok') {
          throw Error(`api ${url} responses with status: ${data.status}`);
        }

        line.directions = data.relations.map((rel) => {
          return { 
            direction: rel.direction,
            relation: rel.relation
          };
        });

        return Promise.resolve(line);
      });
  }

  persistLine(line) {
    return this.lineRepository
      .lineExist(line.name)
      .then((exist) => {
        if (!exist) {
          return this.lineRepository.insert(line);
        } else {
          return Promise.resolve();
        }
      });<commit_msg>refactor for more readable code<commit_after>let config = require('../config/global');
let BaseDataService = require('./baseDataService');

class LineDataService extends BaseDataService {

  constructor(lineRepository) {
    super();
    this.lineRepository = lineRepository;
  }

  updateDayBusLines() {
    return this.updateData('bus', true);
  }

  updateNightBusLines() {
    return this.updateData('bus', false);
  }

  updateDayTramLines() {
    return this.updateData('tram', true);
  }

  updateNightTramLines() {
    return this.updateData('tram', false);
  }

  updateData(lineType, day) {
    return this.getLines(lineType, day)
               .then(this.getDirections.bind(this))
               .then(this.persistLines.bind(this));
  }

  getLines(lineType, day) {
    let url = this.getUrl(lineType, day);
    return this.fetchDataFromApi(url)
      .then((responseBody) => {
        let data = this.extractJson(responseBody);
        if (data.status !== 'ok') {
          throw Error(`api ${url} responses with status: ${data.status}`);
        }

        return data.lines.map((line) => {
          return { 
            name: line,
            type: lineType,
            day: day
          };
        });
      });
  }

  getDirections(lines) {
    if (!lines.length) {
      return Promise.resolve([]);
    }

    /*
    It would be better, but in environments with small RAM 
    it exhauts all resoruces and system stops.

    let promises = lines.map(this.fetchDirections.bind(this));
    return Promise.all(promises);

    so workaround is:
    */

    let createFunction = (line) => {
      return () => {
        return this.fetchDirections(line);
      };
    };

    return new Promise((resolve, reject) => {
      let promise = this.fetchDirections(lines[0]);
      for (let i = 1; i < lines.length; i++) {
        let next = createFunction(lines[i]);
        promise = promise.then(next);
      }

      promise.then(() => {
        resolve(lines);
      }).catch((error) => {
        reject(error);
      });
    });
  }

  fetchDirections(line) {
    let url = config.services.linesDataService
                  .directionsApiUrlFormat.replace('<<line>>', line.name);
    return this.fetchDataFromApi(url)
      .then((responseBody) => {
        let data = this.extractJson(responseBody);
        if (data.status !== 'ok') {
          throw Error(`api ${url} responses with status: ${data.status}`);
        }

        line.directions = data.relations.map((rel) => {
          return { 
            direction: rel.direction,
            relation: rel.relation
          };
        });

        return Promise.resolve(line);
      });
  }

  persistLines(lines) {
    let promises = lines.map((line) => {
      return this.lineRepository
        .lineExist(line.name)
        .then((exist) => {
          if (!exist) {
            return this.lineRepository.insert(line);
          } else {
            return Promise.resolve();
          }
        });
    });

    return Promise.all(promises);
{'fraction_non_alphanumeric': 0.13825042881646654, 'fraction_numerical': 0.0006861063464837049, 'mean_word_length': 2.2144432194046306, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 25, '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': '813097', 'n_tokens_mistral': 1756, 'n_tokens_neox': 1697, 'n_words': 343}