gcba-normalizador-typescript
Version:
Normalizador de direcciones para el AMBA
3 lines (2 loc) • 16.2 kB
JavaScript
;var t=require("@usig-gcba/usig-core"),e=require("urijs"),r=require("@usig-gcba/callejero");const a={CALLE_ALTURA:"DIRECCION_CALLE_ALTURA",CALLE_Y_CALLE:"DIRECCION_CALLE_Y_CALLE",INVALIDO:"INVALIDO"},s={CALLE:"CALLE",DIRECCION:"DIRECCION"},l="EXCEPCION_CALLE_INVALIDA",i="EXCEPCION_CARGA_CALLEJERO",o="EXCEPCION_ALTURA_INVALIDA",n="EXCEPCION_CALLE_SIN_ALTURAS",c="EXCEPCION_CRUCE_INEXISTENTE",h={CALLE_INEXISTENTE:"No pudo hallarse ninguna calle existente que coincidiera con su búsqueda. Por favor, revise el nombre ingresado y vuelva a intentarlo.",CALLES_SIN_CARGAR:"El callejero no se encuentra cargado aún o se produjo un error al intentar cargarlo",ALTURA_INVALIDA:"La altura indicada no es válida para la calle ingresada.",CALLE_SIN_ALTURAS:"La calle {calle} no posee alturas oficiales. Utilice intersecciones para hallar direcciones válidas sobre esta calle o escriba S/N en lugar de la altura.",CRUCE_INEXISTENTE:"El cruce de calles indicado no existe"},u=/^POINT *\((-?[0-9]+\.[0-9]+) (-?[0-9]+\.[0-9]+)\)$/;class C{static construirDireccion(t,e){const r=t.tipo===s.CALLE?t:null;if(!r)throw new Error("La primera calle debe ser de tipo CALLE");let l;if("number"!=typeof e&&isNaN(Number(e))){if(e.tipo!==s.CALLE)throw new Error("El segundo parámetro debe ser una altura o una calle");l={calle:r,calleCruce:e,tipoDireccion:a.CALLE_Y_CALLE,tipo:s.DIRECCION,nombre:""}}else{l={calle:r,altura:"number"==typeof e?e:Number(e),tipoDireccion:a.CALLE_ALTURA,tipo:s.DIRECCION,nombre:""}}return l.nombre=(t=>{const{calle:e,tipoDireccion:r}=t;let s="";if(r===a.CALLE_ALTURA){const r=t.altura;s=`${e.nombre} ${r>0?r:"S/N"}`}else{const{calleCruce:r}=t,a=r.nombre.match(/^(I|Hi|HI).*/)?" e ":" y ";s=`${e.nombre}${a}${r.nombre}`}return e.partido&&(s+=`, ${e.localidad}`),s})(l),l}static isEqual(t,e){if(t.tipo!==s.DIRECCION||e.tipo!==s.DIRECCION)return!1;if(t.tipoDireccion!==e.tipoDireccion)return!1;if(t.tipoDireccion===a.CALLE_ALTURA){const r=t,a=e;return r.calle.codigo===a.calle.codigo&&r.altura===a.altura}const r=t,l=e;return r.calle.codigo===l.calle.codigo&&r.calleCruce.codigo===l.calleCruce.codigo||r.calle.codigo===l.calleCruce.codigo&&r.calleCruce.codigo===l.calle.codigo}static fromObj(t){const e=t.nombre_calle??t.nombre;if(!e)throw new Error("El nombre de la calle es requerido");let r;if(void 0!==t.tipo&&t.calle?.codigo)r=this.construirDireccion(t.calle,t.tipo===a.CALLE_ALTURA?t.altura:t.calle_cruce);else{const a={codigo:t.cod_calle,nombre:e,partido:t.nombre_partido,localidad:t.nombre_localidad,tipo:s.CALLE,alturas:[]};if(t.cod_calle2||t.cod_calle_cruce){const e={codigo:t.cod_calle2||t.cod_calle_cruce,nombre:t.calle2||t.nombre_calle_cruce,partido:t.nombre_partido,localidad:t.nombre_localidad,tipo:s.CALLE,alturas:[]};r=this.construirDireccion(a,e)}else r=this.construirDireccion(a,t.altura);t.nombre_partido&&(r.descripcion=`${t.nombre_localidad}, ${t.nombre_partido}`)}return void 0!==t.smp&&null!==t.smp&&(r.smp=t.smp),void 0!==t.coordenadas&&null!==t.coordenadas&&(r.coordenadas="string"==typeof t.coordenadas?(t=>{const e=t.match(u);if(e)return{x:parseFloat(e[1]),y:parseFloat(e[2])}})(t.coordenadas):t.coordenadas),r}}class p{constructor(t,e){if(this.tipo=-1,this.strCalles=[],this.strAltura="",this.strInput=t.replace(/"/g,"").replace(/[\.,\(\)']/g," ").toUpperCase().trim(),this.esAlturaSN=t=>/[sS][/\\][nN]/.test(t),this.aceptarCallesSinAlturas=e,this.strInput.length>0){let t=this.strInput.split(" Y ");if(t.length>=2){t=this.fixCallesConY(this.strInput).split(" Y "),t.length>=2&&(this.tipo=2,this.strCalles=[t[0].replace(" & "," Y "),t[1].replace(" & "," Y ")])}t=this.strInput.split(" E "),t.length>=2&&(isNaN(parseInt(t[t.length-1]))||parseInt(t[t.length-1]).toString()!==t[t.length-1])&&(this.tipo=2,this.strCalles=t),-1===this.tipo&&this.setearCalleAltura()}else this.tipo=-1}esTipoAltura(e,r){return t.isDigit(e)||r&&this.esAlturaSN(e)}setearCalleAltura(){let t=this.strInput.split(" ");this.maxWordLen=function(t,e,r){for(let a=0;a<t.length;a++)e=r(e,t[a],a);return e}(t,0,(function(t,e){return Math.max(e.trim().length,t)}));let e=t.length;e>1&&this.esTipoAltura(t[e-1],this.aceptarCallesSinAlturas)?(this.tipo=1,this.strCalles=[t.slice(0,-1).join(" ")],this.strAltura=t[e-1]):(this.tipo=0,this.strCalles=[this.strInput])}fixCallesConY(e){return t.translate(e,["GELLY Y OBES","MENENDEZ Y PELAYO","OLAGUER Y FELIU","ORTEGA Y GASSET","PAULA Y RODRIGUEZ","PAZ Y FIGUEROA","PI Y MARGALL","RAMON Y CAJAL","TORRES Y TENORIO","TREINTA Y TRES"],["GELLY & OBES","MENENDEZ & PELAYO","OLAGUER & FELIU","ORTEGA & GASSET","PAULA & RODRIGUEZ","PAZ & FIGUEROA","PI & MARGALL","RAMON & CAJAL","TORRES & TENORIO","TREINTA & TRES"])}quitarAvsCalle(){let e=["AV","AVDA","AVENIDA"];1===this.tipo?this.strCalles=t.removeWords(this.strCalles,e):2===this.tipo&&(this.strCalles[0]=t.removeWords(this.strCalles[0],e))}quitarAvsCalleCruce(){let e=["AV","AVDA","AVENIDA"];2===this.tipo&&(this.strCalles[1]=t.removeWords(this.strCalles[1],e))}quitarPasajes(){let e=["PJE","PSJE","PASAJE"];1===this.tipo?this.strCalles=t.removeWords(this.strCalles,e):2===this.tipo&&(this.strCalles[0]=t.removeWords(this.strCalles[0],e),this.strCalles[1]=t.removeWords(this.strCalles[1],e))}esAlturaSN(t){return/^s\/n$|^sn$/i.test(t)}}const A={debug:!1,exclude:"caba",server:"https://servicios.usig.buenosaires.gob.ar/normalizar",maxSuggestions:10,serverTimeout:5e3,maxRetries:3,afterAbort:()=>{},afterRetry:()=>{},afterServerRequest:()=>{},afterServerResponse:()=>{}};class g{constructor(t={}){this.lastRequest=null,this.retryCount=0,this.options={...A,...t}}static getInstance(t){return g.instance||(g.instance=new g(t)),g.instance}init(t){return this.options={...this.options,...t},this}async buscar(t,e,r,a){const s=a??this.options.maxSuggestions,l={...this.options,maxOptions:s,direccion:t};try{this.lastRequest=this.makeRequest(l);const t=await this.lastRequest,r=this.processResults(t,s);"function"==typeof e&&e(r)}catch(s){this.retryCount<this.options.maxRetries?(this.retryCount++,this.options.afterRetry(this.retryCount),await this.buscar(t,e,r,a)):(this.retryCount=0,"function"==typeof r&&r(s))}}async makeRequest(t){const r=e(this.options.server).search(t).toString();this.options.afterServerRequest(r);const a=new AbortController,s=setTimeout((()=>{a.abort(),this.options.afterAbort(new Error("Timeout"))}),this.options.serverTimeout);try{const t=await fetch(r,{signal:a.signal,headers:{Accept:"application/json"}});if(clearTimeout(s),!t.ok)throw new Error(`HTTP error! status: ${t.status}`);const e=await t.json();return this.options.afterServerResponse(e),e}catch(t){throw clearTimeout(s),t}}processResults(t,e){const r=[];if(!t.direccionesNormalizadas)return r;const a=Math.min(t.direccionesNormalizadas.length,e);for(let e=0;e<a;e++){const a=t.direccionesNormalizadas[e];let l;l="calle"===a.tipo?{codigo:a.cod_calle,nombre:a.nombre_calle,tipo:s.CALLE,partido:a.nombre_partido,descripcion:`${a.nombre_localidad}, ${a.nombre_partido}`,alturas:[]}:C.fromObj(a),r.push(l)}return r}}var m=g.getInstance();class d{constructor(t){this.patterns={cruceCalles:/\s+y\s+/gi,calleAltura:{},calle:{}};for(let e=1;e<=t;e++)this.patterns.calleAltura[e]=new RegExp(`(\\d+(\\s+(\\w|\\d|á|é|í|ó|ú|ü|ñ|'|\`|,|\\.)+){${e}})`,"gi"),this.patterns.calle[e]=new RegExp(`(\\w|\\d|á|é|í|ó|ú|ü|ñ|'|\`|,|\\.)+(\\s+(\\w|\\d|á|é|í|ó|ú|ü|ñ|'|\`|,|\\.)+){${e-1}}`,"gi")}static getInstance(t){return d.instance||(d.instance=new d(t)),d.instance}get cruceCalles(){return this.patterns.cruceCalles}getCalleAlturaPattern(t){return this.patterns.calleAltura[t]}getCallePattern(t){return this.patterns.calle[t]}}class E{static sinAcentos(t){const e={"Á":"A","É":"E","Í":"I","Ó":"O","Ú":"U","Ü":"U","á":"a","é":"e","í":"i","ó":"o","ú":"u","ü":"u"};return t.replace(/[ÁÉÍÓÚÜáéíóúü]/g,(t=>e[t]||t))}static esPermutacion(t,e){const r=t=>E.sinAcentos(t).replace(/"/g,"").toUpperCase().trim().split(" "),a=r(t),s=r(e);if(a.length!==s.length)return!1;const l=a.filter((t=>s.includes(t)));return a.length===l.length}static verificarBusquedaDireccion(t,e){const r=E.sinAcentos(e.toUpperCase()).split(" "),a=E.sinAcentos(t.toUpperCase()).replace(/[,.]/g,"").split(" ");for(let t=0;t<r.length-1;t++)for(let e=0;e<a.length-1;e++)if(r[t]===a[e]&&r[t].length>3)return!0;return!1}}class L{constructor(t,e){this.name=this.constructor.name,this.id=t,this.message=e,Object.setPrototypeOf(this,new.target.prototype)}toString(){return this.message}}class I extends L{constructor(t){super(l,`Calle inexistente: ${t}`),this.nombreCalle=t}getNombreCalle(){return this.nombreCalle}getError(){return{type:"CALLE_INEXISTENTE",message:h.CALLE_INEXISTENTE}}}class b extends L{constructor(t,e,r){super(o,`La calle ${t} no existe a la altura ${r}`),this.calle=t,this.matchings=e,this.altura=r}getCalle(){return this.calle}getMatchings(){return this.matchings}getAltura(){return this.altura}getError(){const t=this.matchings.flatMap((t=>t.alturas.map((e=>({calle:t.nombre,inicio:e.inicio,fin:e.fin})))));return{type:"ALTURA_INVALIDA",message:h.ALTURA_INVALIDA,matchings:t}}}class f extends L{constructor(t){super(n,h.CALLE_SIN_ALTURAS.replace("{calle}",t)),this.nombreCalle=t}getNombreCalle(){return this.nombreCalle}getError(){return{type:"CALLE_SIN_ALTURAS",streetName:this.nombreCalle,message:this.message}}}class N extends L{constructor(t,e,r,a){super(c,`Cruce inexistente: ${t} y ${r}`),this.calle1=t,this.matchingsCalle1=e,this.calle2=r,this.matchingsCalle2=a}getCalle1(){return this.calle1}getCalle2(){return this.calle2}getMatchingsCalle1(){return this.matchingsCalle1}getMatchingsCalle2(){return this.matchingsCalle2}getError(){return{type:"CRUCE_INEXISTENTE",message:h.CRUCE_INEXISTENTE,matchings1:this.matchingsCalle1,matchings2:this.matchingsCalle2}}}var _=Object.freeze({__proto__:null,ErrorCalleInexistente:I,ErrorCalleInexistenteAEsaAltura:b,ErrorCalleSinAlturas:f,ErrorCruceInexistente:N,ErrorEnCargaDelCallejero:class extends L{constructor(){super(i,"Callejero no disponible.")}getError(){return{type:"CALLES_SIN_CARGAR",message:h.CALLES_SIN_CARGAR}}}});const R={lazyDataLoad:!1,loadFullDatabase:!0,aceptarCallesSinAlturas:!1,callesEnMinusculas:!1,maxPalabras:7};class S{constructor(t={}){this.initialized=!1,this.callejeroPromise=null,this.options={...R,...t},this.regexPatterns=d.getInstance(this.options.maxPalabras)}static getInstance(t){return S.instance||(S.instance=new S(t)),S.instance}async init(t){return this.initialized?this:(this.callejeroPromise||(this.callejeroPromise=r.init({lazyDataLoad:this.options.lazyDataLoad,loadFullDatabase:this.options.loadFullDatabase,callesEnMinusculas:this.options.callesEnMinusculas,callejero:this.options.callejero}).then((t=>(this.callejero=t,this.initialized=!0,this)))),this.callejeroPromise)}setOptions(t){this.options={...this.options,...t}}listo(){return this.callejero?.listo()??!1}inicializado(){return this.initialized}async normalizarCalleAltura(t,e,r){let a=this.callejero.matcheaCalle(t.strCalles),s=[];try{s=await this.validarAlturas(t,a,e)}catch(r){if(0===s.length&&a.length>0){t.quitarAvsCalle(),a=this.callejero.matcheaCalle(t.strCalles);try{s=await this.validarAlturas(t,a,e)}catch(e){if(s=this.filtrarCallesQueNoSonAv(s),0===s.length)throw new b(t.strCalles,a,t.strAltura)}}else if(0===s.length&&0===a.length){t.quitarPasajes(),a=this.callejero.matcheaCalle(t.strCalles);try{s=await this.validarAlturas(t,a,e)}catch(t){throw t}}}return r&&s.length>1&&(s=s.filter((e=>E.esPermutacion(t.strCalles,e.calle.nombre)))),s}async validarAlturas(t,e,r){const a=[];let s=0;for(const l of e){try{this.callejero.alturaValida(l,t.strAltura)&&a.push(C.construirDireccion(l,t.strAltura))}catch(e){e instanceof Error&&3===e.id&&this.options.aceptarCallesSinAlturas&&t.esAlturaSN.test(t.strAltura)&&a.push(C.construirDireccion(l,0)),s++}if(r&&a.length>=r)break}if(e.length===s&&0===a.length)throw new f(e[0].nombre);return a}filtrarCallesQueNoSonAv(t){return t.filter((t=>this.callejero.tieneTramosComoAv(t.calle.codigo)))}async normalizarCalleYCalle(t,e){const r=this.callejero.matcheaCalle(t.strCalles[0]),a=this.callejero.matcheaCalle(t.strCalles[1]),s=new Set,l=[],i=(t,e)=>`${Math.min(Number(t.codigo),Number(e.codigo))}${Math.max(Number(t.codigo),Number(e.codigo))}`;for(const t of r)for(const r of a)if(t.codigo!==r.codigo&&!s.has(i(t,r))&&this.callejero.seCruzaCon(t,r)&&this.callejero.seCruzaCon(r,t)&&(l.push(C.construirDireccion(t,r)),s.add(i(t,r)),e&&l.length>=e))return l;if(0===l.length&&r.length>0&&a.length>0){const s=t.strCalles[0].split(" "),l=t.strCalles[1].split(" "),i=["AV","AVDA","AVENIDA"];if(i.some((t=>s.includes(t)))){const s={...t};s.quitarAvsCalle();try{const t=await this.normalizarCalleYCalle(s,e);return this.filtrarCallesQueNoSonAv(t)}catch(e){throw new N(t.strCalles[0],r,t.strCalles[1],a)}}if(i.some((t=>l.includes(t)))){const s={...t};s.quitarAvsCalleCruce();try{const t=await this.normalizarCalleYCalle(s,e);return this.filtrarCallesQueNoSonAv(t)}catch(e){throw new N(t.strCalles[0],r,t.strCalles[1],a)}}}if(0===l.length&&r.length>0&&a.length>0)throw new N(t.strCalles[0],r,t.strCalles[1],a);return l}async normalizar(t,e,r=!1){const a=new p(t,this.options.aceptarCallesSinAlturas??!1);let s=[];switch(a.tipo){case 0:s=this.callejero.matcheaCalle(a.strCalles,e);break;case 1:s=await this.normalizarCalleAltura(a,e??0,r);break;case 2:s=await this.normalizarCalleYCalle(a,e??0),0===s.length&&(a.setearCalleAltura(),s=await this.normalizarCalleAltura(a,e??0,r));break;case-1:s=[]}if(Array.isArray(s)){if(s.length>0)return s;throw new I(t)}return s}async buscarDireccion(t){const e=await this.buscarDirecciones(t,1);return!!e&&e[0]}async buscarDirecciones(t,e){const r=[],a=/((\s+y\s+)|(\s+\d+))/gi;let s;for(;s=a.exec(t);){let a;if(a=s[0].match(this.regexPatterns.cruceCalles)?await this.buscarCruceCalles(t,s.index,s[0].length):await this.buscarCalleAltura(t.substring(0,s.index+s[0].length)),a)if(r.length>0){const t=r[r.length-1];a.pos===t.pos&&a.match.toString()===t.match.toString()?a.len>t.len&&(r.pop(),r.push(a)):r.push(a)}else r.push(a);if(e&&r.length>=e)return r}return r.length>0&&r}async buscarCruceCalles(t,e,r){const a=t.substring(0,e).split("").reverse().join(""),s=t.substr(e+r),l=t.substr(e,r);let i="",o="",n=[],c=[];try{for(let t=1;t<this.options.maxPalabras;++t){const e=s.match(this.regexPatterns.getCallePattern(t));if(!e||0!==s.search(this.regexPatterns.getCallePattern(t)))throw new Error("Direccion no valida");o=e[0],c=await this.normalizar(o,2,!1)}}catch(t){const e=s.match(this.regexPatterns.getCallePattern(this.options.maxPalabras-1));e&&(o=e[0])}try{for(let t=1;t<this.options.maxPalabras;++t){const e=a.match(this.regexPatterns.getCallePattern(t));if(!e||0!==a.search(this.regexPatterns.getCallePattern(t)))throw new Error("Direccion no valida");i=e[0].split("").reverse().join(""),n=await this.normalizar(i,2,!1)}}catch(t){const e=a.match(this.regexPatterns.getCallePattern(this.options.maxPalabras-1));e&&(i=e[0].split("").reverse().join(""))}try{const e=await this.normalizar(i+l+o,2,!1);if(1===e.length&&E.verificarBusquedaDireccion(e[0].toString(),i+l+o))return{match:e[0],pos:t.search(i),len:i.length+l.length+o.length}}catch(t){return!1}return!1}async buscarCalleAltura(t){const e=t.split("").reverse().join("");let r="",a=[];try{for(let t=1;t<this.options.maxPalabras;++t){const s=e.match(this.regexPatterns.getCalleAlturaPattern(t));if(!s||0!==e.search(this.regexPatterns.getCalleAlturaPattern(t)))throw new Error("Direccion no valida");r=s[0].split("").reverse().join(""),a=await this.normalizar(r,2,!1)}}catch(t){const s=e.match(this.regexPatterns.getCalleAlturaPattern(this.options.maxPalabras-1));s&&(r=s[0].split("").reverse().join(""),a=await this.normalizar(r,2,!1))}return!!(a.length>0&&E.verificarBusquedaDireccion(a[0].toString(),r))&&{match:a[0],pos:t.search(r),len:r.length}}}const w=S.getInstance();var x=Object.freeze({__proto__:null,Direccion:C,Normalizador:w,NormalizadorAMBA:m,NormalizadorDirecciones:S});exports.Direccion=C,exports.Normalizador=x,exports.NormalizadorAMBA=m,exports.RegexPatterns=d,exports.StringDireccion=p,exports.TIPOS_DIRECCION=a,exports.TIPOS_OBJETO=s,exports.TextUtils=E,exports.exceptions=_;
//# sourceMappingURL=index.js.map