diff --git a/lib/modems.js b/lib/modems.js index 8f3ebc8..4a0c68a 100644 --- a/lib/modems.js +++ b/lib/modems.js @@ -25,6 +25,52 @@ exports.outgoingModems = (arrayOfModem) => { return modems.filter((modem) => modem.outgoing); }; +exports.OUTGOING_MODEMS = this.outgoingModems(); + +exports.prefixes = (arrayOfModem) => { + const prefixModemsObject = {}; + const prefixModemsArray = []; + + const modems = this.outgoingModems(arrayOfModem); + modems.forEach((modem) => { + const modemPrefixes = modem.prefix || []; + modemPrefixes.forEach((prefix) => { + const normalizedPrefix = prefix.trim().replace(/^0/, '62'); + + if (!prefixModemsObject[normalizedPrefix]) { + prefixModemsObject[normalizedPrefix] = [modem.name]; + } else { + prefixModemsObject[normalizedPrefix].push(modem.name); + } + }); + }); + + // eslint-disable-next-line no-restricted-syntax + for (const [prefix, value] of Object.entries(prefixModemsObject)) { + prefixModemsArray.push({ prefix, modems: value }); + } + + const retval = prefixModemsArray.sort((a, b) => { + if (a.prefix.length < b.prefix.length) return 1; + if (a.prefix.length > b.prefix.length) return -1; + + if (a < b) return -1; + if (a > b) return 1; + return 0; + }); + + retval.forEach((item) => { + // eslint-disable-next-line no-param-reassign + item.modems = item.modems.sort((a, b) => { + if (a < b) return -1; + if (a > b) return 1; + return 0; + }); + }); + + return retval; +}; + exports.randomModem = (arrayOfModem) => { const modems = this.outgoingModems(arrayOfModem); @@ -40,3 +86,29 @@ exports.randomModem = (arrayOfModem) => { const idx = Math.floor(Math.random() * modemCount); return modems[idx]; }; + +exports.findPrefixForNumber = (number, prefixes) => prefixes.find( + (item) => number.replace(/^0/, '62').indexOf(item.prefix) === 0, +); + +exports.isFreePrefixModem = (modem) => !modem.prefix || !modem.prefix.length; + +exports.randomModemByPrefix = (number, arrayOfModem) => { + const modems = this.outgoingModems(arrayOfModem); + const prefixes = this.prefixes(arrayOfModem); + const prefix = this.findPrefixForNumber(number, prefixes); + const modemNamesForPrefix = (prefix || {}).modems; + + if (modemNamesForPrefix && modemNamesForPrefix.length) { + const count = modemNamesForPrefix.length; + const idx = Math.floor(Math.random() * count); + const modemName = modemNamesForPrefix[idx]; + + return modems.find((modem) => modem.name === modemName); + } + + const freeModems = modems.filter((modem) => this.isFreePrefixModem(modem)); + const count = freeModems.length; + const idx = Math.floor(Math.random() * count); + return freeModems[idx]; +}; diff --git a/test/modems.js b/test/modems.js index 9a4eeb3..5a25866 100644 --- a/test/modems.js +++ b/test/modems.js @@ -1,20 +1,211 @@ +/* eslint-disable no-console */ /* global describe it */ const modems = require('../lib/modems'); -require('should'); +const should = require('should'); describe('#modems', () => { describe('#enabledModems', () => { - const test1 = modems.enabledModems([ + it('should return correctly', () => { + const test1 = modems.enabledModems([ + { + name: 'SENDER-AS13', + disabled: false, + outgoing: true, + imsi: null, + prefix: [], + }, + ]); + + test1.should.ok(); + }); + }); + + describe('#prefixes', () => { + it('should return correctly', () => { + const config = [ + { + name: 'XL1', + outgoing: true, + prefix: ['0818', '081'], + }, + { + name: 'TSEL1', + outgoing: true, + prefix: ['0812', '0811'], + }, + { + name: 'TSEL2', + outgoing: true, + prefix: ['0812', '0811'], + }, + { + name: 'ISAT1', + outgoing: true, + prefix: ['0815', '0816'], + }, + ]; + + const prefixes = modems.prefixes(config); + + prefixes[0].prefix.should.equal('62811'); + prefixes[1].prefix.should.equal('62812'); + prefixes[2].prefix.should.equal('62815'); + prefixes[3].prefix.should.equal('62816'); + prefixes[4].prefix.should.equal('62818'); + prefixes[5].prefix.should.equal('6281'); + + prefixes[0].modems[0].should.equal('TSEL1'); + prefixes[0].modems[1].should.equal('TSEL2'); + prefixes[1].modems[0].should.equal('TSEL1'); + prefixes[1].modems[1].should.equal('TSEL2'); + prefixes[2].modems[0].should.equal('ISAT1'); + prefixes[3].modems[0].should.equal('ISAT1'); + prefixes[4].modems[0].should.equal('XL1'); + prefixes[5].modems[0].should.equal('XL1'); + }); + }); + + describe('#findPrefixForNumber', () => { + it('should return correct prefix', () => { + const config = [ + { + name: 'XL1', + outgoing: true, + prefix: ['0818', '081'], + }, + { + name: 'TSEL1', + outgoing: true, + prefix: ['0812', '0811'], + }, + { + name: 'TSEL2', + outgoing: true, + prefix: ['0812', '0811'], + }, + { + name: 'ISAT1', + outgoing: true, + prefix: ['0815', '0816'], + }, + { + name: 'FREE1', + outgoing: true, + prefix: [], + }, + { + name: 'FREE2', + outgoing: true, + prefix: [], + }, + ]; + + const prefixes = modems.prefixes(config); + modems.findPrefixForNumber('628188188', prefixes).prefix.should.equal('62818'); + modems.findPrefixForNumber('08188188', prefixes).prefix.should.equal('62818'); + modems.findPrefixForNumber('62812812', prefixes).prefix.should.equal('62812'); + modems.findPrefixForNumber('62810810', prefixes).prefix.should.equal('6281'); + should.not.exists(modems.findPrefixForNumber('6221212121', prefixes)); + }); + }); + + describe('#randomModemByPrefix', () => { + const config = [ + { + name: 'XL1', + outgoing: true, + prefix: ['0818', '081'], + }, + { + name: 'TSEL1', + outgoing: true, + prefix: ['0812', '0811'], + }, { - name: 'SENDER-AS13', - disabled: false, + name: 'TSEL2', + outgoing: true, + prefix: ['0812', '0811'], + }, + { + name: 'ISAT1', + outgoing: true, + prefix: ['0815', '0816'], + }, + { + name: 'FREE1', + outgoing: true, + prefix: [], + }, + { + name: 'FREE2', outgoing: true, - imsi: null, prefix: [], }, - ]); + ]; + + const loopCount = 100; + + it('should return correctly for XL', () => { + for (let i = 0; i < loopCount; i += 1) { + modems.randomModemByPrefix('6281881818', config).name.should.equal('XL1'); + } + }); + + it('should return correctly for TSEL', () => { + for (let i = 0; i < loopCount; i += 1) { + modems.randomModemByPrefix('62812812', config).name.should.equalOneOf('TSEL1', 'TSEL2'); + } + }); + + it('should return correctly for INDOSAT', () => { + for (let i = 0; i < loopCount; i += 1) { + modems.randomModemByPrefix('62815815', config).name.should.equal('ISAT1'); + } + }); + + it('should return correctly for UNKNOWN PREFIX', () => { + for (let i = 0; i < loopCount; i += 1) { + modems.randomModemByPrefix('628888888', config).name.should.equalOneOf('FREE1', 'FREE2'); + } + }); + + it('should handle UNKNOWN PREFIX without free modem', () => { + // eslint-disable-next-line no-shadow + const config = [ + { + name: 'XL1', + outgoing: true, + prefix: ['0818', '081'], + }, + { + name: 'TSEL1', + outgoing: true, + prefix: ['0812', '0811'], + }, + { + name: 'TSEL2', + outgoing: true, + prefix: ['0812', '0811'], + }, + { + name: 'ISAT1', + outgoing: true, + prefix: ['0815', '0816'], + }, + { + name: 'FREE1', + outgoing: false, + prefix: [], + }, + { + name: 'FREE2', + outgoing: false, + prefix: [], + }, + ]; - test1.should.ok(); + should.not.exists(modems.randomModemByPrefix('628888888', config)); + }); }); });