<commit_before>/* global Movement, Detainee, Event, Prebooking, Heartbeat, Bed */
'use strict';

const ValidationError = require('../lib/exceptions/ValidationError');
const BedCountService = require('../services/BedCountService');
const LinkingModels = require('sails-linking-models');

const unreconciledMovementReducer = (movements, gender, direction) => movements.reduce((reduced, m) => {
  if (m.gender === gender && m.direction === direction) {
    reduced.push({id: m.id, cid_id: m.cid_id});
  }
  return reduced;
}, []);
const unreconciledEventReducer = (events, gender, operations) => events.reduce((reduced, event) => {
  if (event.detainee.gender === gender && operations.indexOf(event.operation) >= 0) {
    reduced.push({id: event.id, cid_id: event.detainee.cid_id});
  }
  return reduced;
}, []);

const model = {
  schema: true,
  autoCreatedAt: true,
  autoUpdatedAt: true,
  attributes: {
    heartbeat_received: {
      type: 'datetime'
    },
    cid_received_date: {
      type: 'datetime'
    },
    prebooking_received: {
      type: 'datetime'
    },
    name: {
      type: 'string',
      defaultsTo: 0,
      required: true,
      unique: true
    },
    male_capacity: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_capacity: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_in_use: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_in_use: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_out_of_commission: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_out_of_commission: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_cid_name: {
      type: 'array'
    },
    female_cid_name: {
      type: 'array'
    },
    male_prebooking: {
      collection: 'prebooking',
      note: 'this is a workaround until waterline supports conditional joins see balderdashy/waterline#988 and balderdashy/waterline#645',
      via: 'male_prebooking'
    },
    female_prebooking: {
      collection: 'prebooking',
      note: 'this is a workaround until waterline supports conditional joins see balderdashy/waterline#988 and balderdashy/waterline#645',
      via: 'female_prebooking'
    },
    male_contingency: {
      collection: 'prebooking',
      note: 'this is a workaround until waterline supports conditional joins see balderdashy/waterline#988 and balderdashy/waterline#645',
      via: 'male_contingency'
    },
    female_contingency: {
      collection: 'prebooking',
      note: 'this is a workaround until waterline supports conditional joins see balderdashy/waterline#988 and balderdashy/waterline#645',
      via: 'female_contingency'
    },
    events: {
      collection: 'event',
      via: 'centre'
    },
    detainees: {
      collection: 'detainee',
      via: 'centre'
    },
    movements: {
      collection: 'movement',
      via: 'centre'
    },
    toJSON: function () {
      const response = {
        type: 'centre',
        id: this.id.toString(),
        attributes: {
          cidReceivedDate: this.cid_received_date ? this.cid_received_date.toString() : null,
          updated: this.updatedAt,
          heartbeatReceived: this.heartbeat_received ? this.heartbeat_received.toString() : null,
          prebookingReceived: this.prebooking_received ? this.prebooking_received.toString() : null,
          name: this.name
        },
        links: this.modelLinks('centres', reverseRouteService)
      };
      ['male', 'female'].forEach((gender) => {
        response.attributes[gender + 'Capacity'] = this[gender + '_capacity'];
        response.attributes[gender + 'InUse'] = this[gender + '_in_use'];
        response.attributes[gender + 'OutOfCommissionTotal'] = this[gender + '_out_of_commission'];
        response.attributes[gender + 'OutOfCommissionDetail'] = this.outOfCommission ? this.outOfCommission[gender] : null;
        response.attributes[gender + 'Prebooking'] = this[gender + '_prebooking'].length;
        response.attributes[gender + 'Contingency'] = this[gender + '_contingency'].length;
        response.attributes[gender + 'Availability'] = response.attributes[gender + 'Capacity'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'InUse'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'OutOfCommissionTotal'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'Prebooking'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'Contingency'];
        if (this.reconciled) {
          response.attributes[gender + 'UnexpectedIn'] = unreconciledEventReducer(this.unreconciledEvents, gender, ['check in']);
          response.attributes[gender + 'ExpectedIn'] = unreconciledMovementReducer(this.unreconciledMovements, gender, 'in');
          response.attributes[gender + 'ExpectedOut'] = unreconciledMovementReducer(this.unreconciledMovements, gender, 'out');
          response.attributes[gender + 'Availability'] -= response.attributes[gender + 'ExpectedIn'].length;
        }
      });
      return response;
    }
  },
  getGenderAndCentreByCIDLocation: function (location) {
    return this.find().then(centres =>
      _.compact(_.map(centres, centre => {
        if (_.contains(centre.male_cid_name, location)) {
          return {
            centre: centre.id,
            gender: 'male'
          };
        }
        if (_.contains(centre.female_cid_name, location)) {
          return {
            centre: centre.id,
            gender: 'female'
          };
        }
      }))[0]
    );
  },<commit_msg>IBM-316: Lodash - no backward compatibility with _.contains<commit_after>/* global Movement, Detainee, Event, Prebooking, Heartbeat, Bed */
'use strict';

const ValidationError = require('../lib/exceptions/ValidationError');
const BedCountService = require('../services/BedCountService');
const LinkingModels = require('sails-linking-models');

const unreconciledMovementReducer = (movements, gender, direction) => movements.reduce((reduced, m) => {
  if (m.gender === gender && m.direction === direction) {
    reduced.push({id: m.id, cid_id: m.cid_id});
  }
  return reduced;
}, []);
const unreconciledEventReducer = (events, gender, operations) => events.reduce((reduced, event) => {
  if (event.detainee.gender === gender && operations.indexOf(event.operation) >= 0) {
    reduced.push({id: event.id, cid_id: event.detainee.cid_id});
  }
  return reduced;
}, []);

const model = {
  schema: true,
  autoCreatedAt: true,
  autoUpdatedAt: true,
  attributes: {
    heartbeat_received: {
      type: 'datetime'
    },
    cid_received_date: {
      type: 'datetime'
    },
    prebooking_received: {
      type: 'datetime'
    },
    name: {
      type: 'string',
      defaultsTo: 0,
      required: true,
      unique: true
    },
    male_capacity: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_capacity: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_in_use: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_in_use: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_out_of_commission: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_out_of_commission: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_cid_name: {
      type: 'array'
    },
    female_cid_name: {
      type: 'array'
    },
    male_prebooking: {
      collection: 'prebooking',
      note: 'this is a workaround until waterline supports conditional joins see balderdashy/waterline#988 and balderdashy/waterline#645',
      via: 'male_prebooking'
    },
    female_prebooking: {
      collection: 'prebooking',
      note: 'this is a workaround until waterline supports conditional joins see balderdashy/waterline#988 and balderdashy/waterline#645',
      via: 'female_prebooking'
    },
    male_contingency: {
      collection: 'prebooking',
      note: 'this is a workaround until waterline supports conditional joins see balderdashy/waterline#988 and balderdashy/waterline#645',
      via: 'male_contingency'
    },
    female_contingency: {
      collection: 'prebooking',
      note: 'this is a workaround until waterline supports conditional joins see balderdashy/waterline#988 and balderdashy/waterline#645',
      via: 'female_contingency'
    },
    events: {
      collection: 'event',
      via: 'centre'
    },
    detainees: {
      collection: 'detainee',
      via: 'centre'
    },
    movements: {
      collection: 'movement',
      via: 'centre'
    },
    toJSON: function () {
      const response = {
        type: 'centre',
        id: this.id.toString(),
        attributes: {
          cidReceivedDate: this.cid_received_date ? this.cid_received_date.toString() : null,
          updated: this.updatedAt,
          heartbeatReceived: this.heartbeat_received ? this.heartbeat_received.toString() : null,
          prebookingReceived: this.prebooking_received ? this.prebooking_received.toString() : null,
          name: this.name
        },
        links: this.modelLinks('centres', reverseRouteService)
      };
      ['male', 'female'].forEach((gender) => {
        response.attributes[gender + 'Capacity'] = this[gender + '_capacity'];
        response.attributes[gender + 'InUse'] = this[gender + '_in_use'];
        response.attributes[gender + 'OutOfCommissionTotal'] = this[gender + '_out_of_commission'];
        response.attributes[gender + 'OutOfCommissionDetail'] = this.outOfCommission ? this.outOfCommission[gender] : null;
        response.attributes[gender + 'Prebooking'] = this[gender + '_prebooking'].length;
        response.attributes[gender + 'Contingency'] = this[gender + '_contingency'].length;
        response.attributes[gender + 'Availability'] = response.attributes[gender + 'Capacity'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'InUse'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'OutOfCommissionTotal'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'Prebooking'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'Contingency'];
        if (this.reconciled) {
          response.attributes[gender + 'UnexpectedIn'] = unreconciledEventReducer(this.unreconciledEvents, gender, ['check in']);
          response.attributes[gender + 'ExpectedIn'] = unreconciledMovementReducer(this.unreconciledMovements, gender, 'in');
          response.attributes[gender + 'ExpectedOut'] = unreconciledMovementReducer(this.unreconciledMovements, gender, 'out');
          response.attributes[gender + 'Availability'] -= response.attributes[gender + 'ExpectedIn'].length;
        }
      });
      return response;
    }
  },
  getGenderAndCentreByCIDLocation: function (location) {
    return this.find().then(centres =>
      _.compact(_.map(centres, centre => {
        if (_.includes(centre.male_cid_name, location)) {
          return {
            centre: centre.id,
            gender: 'male'
          };
        }
        if (_.includes(centre.female_cid_name, location)) {
          return {
            centre: centre.id,
            gender: 'female'
          };
        }
      }))[0]
    );
  },
{'fraction_non_alphanumeric': 0.12926702477906776, 'fraction_numerical': 0.005978166695546699, 'mean_word_length': 2.9544364508393284, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, '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': '2058087', 'n_tokens_mistral': 3535, 'n_tokens_neox': 3405, 'n_words': 694}