tcc-ifpr-armarios / armarios-ifpr-electron

Base aplication with authentication on SUAP ( Unified Public Administration System )
1 stars 0 forks source link

DOCS: A distância de Levenshtein #14

Closed OAllanFernando closed 1 month ago

OAllanFernando commented 1 month ago
const buscaCursoOuCriaCurso = async (curso) => {
  try {
    const cursoExistente = await Curso.findOne({ where: { nome: curso } });
    console.log(cursoExistente + "Nenhum curso com nomes identico aos no banco de dados");
    if (cursoExistente) {
      return cursoExistente;
    } else {
      const cursoAproximado = levenshteinMath(curso);
      console.log(cursoAproximado + "returnwu de kev");
      if (cursoAproximado) {
        return cursoAproximado;
      }
    }
    const novoCurso = await Curso.create({ nome: curso, ativo: true });
    return novoCurso;
  } catch (error) {
    console.log(error);
  }
};
const levenshteinMath = async (curso) => {
  // precisamos de uma busca com tolerancia de erro Acredito que 50% ou 60% de coopatibilidade é o suficiente
  // ENGENHARIA DE SOFTWARE = 22 letras
  // LICENCIATURA EM QUIMICA = 23 letras
  // ENTRADA = ENG DE SOFTWARE
  // vamos atribuir 0.6 de tolerancia e inserir no banco o a cursos que tenham 60% de compatibilidade no nome
  //const cursoSimilar = await Curso.findAll({ where: { nome: { [Op.like]: %${curso}% } } }); Assim comparariamos strings completas
  console.log("Curso a ser comparado:", curso);
  const tolerancia = process.env.TOLERANCIA_A_CURSOS;
  let cursos = await Curso.findAll();
  console.log("Cursos encontrados no banco: ", cursos.length, " cursos");
  let cursoEncontrado = null;
  let maiorSimilaridade = 0;
  cursos.forEach(cursoBanco => {
    let nomeBanco = cursoBanco.nome;
    let distancia = levenshtein.get(curso, nomeBanco);
    let maxTamanho = Math.max(curso.length, nomeBanco.length);
    let similaridade = 1 - (distancia / maxTamanho);
    console.log(Comparando '${curso}' com '${nomeBanco}' - Similaridade: ${ similaridade } a uma tolerancia de ${ tolerancia });
    if (similaridade > maiorSimilaridade) {
      maiorSimilaridade = similaridade;
      cursoEncontrado = cursoBanco;
    }
  });
  if (maiorSimilaridade >= tolerancia) {
    console.log("O curso encontrado que satisfaz a tolerancia de 60% foi: ", cursoEncontrado);
    return cursoEncontrado;
  } else {
    console.log("vish: ");
    return null;
  }
};
RETORNO:
Executing (default): SELECT "id", "nome", "ativo", "createdAt", "updatedAt" FROM "Cursos" AS "Curso" WHERE "Curso"."nome" = 'ENG DE SOFTWARE';
Nenhum curso com nomes identico aos no banco de dados 
Curso a ser comparado: ENG DE SOFTWARE
Executing (default): SELECT "id", "nome", "ativo", "createdAt", "updatedAt" FROM "Cursos" AS "Curso";
Cursos encontrados no banco:  1  cursos
Comparando 'ENG DE SOFTWARE' com 'ENGENHARIA DE SOFTWARE' - Similaridade: 0.6818181818181819 a uma tolerancia de 0.6
O curso encontrado que satisfaz a tolerancia de 60% foi:  Curso {
  dataValues: {
    id: 1,
    nome: 'ENGENHARIA DE SOFTWARE',
    ativo: true,
    createdAt: 2024-08-03T14:27:33.900Z,
    updatedAt: 2024-08-03T14:27:33.900Z
  },
  _previousDataValues: {
    id: 1,
    nome: 'ENGENHARIA DE SOFTWARE',
    ativo: true,
    createdAt: 2024-08-03T14:27:33.900Z,
    updatedAt: 2024-08-03T14:27:33.900Z
  },
  uniqno: 1,
  _changed: Set(0) {},
  _options: {
    isNewRecord: false,
    _schema: null,
    _schemaDelimiter: '',
    raw: true,
    attributes: [ 'id', 'nome', 'ativo', 'createdAt', 'updatedAt' ]
  },
  isNewRecord: false
}

Método de integração que calcula a diferença entre os cursos já disponíveis ao curso na api que à alimenta. O código é baseado na distância de Levenshtein, matematico russo .........

A impementação utiliza dos conceitos dessa distancia, comparando os cursos cadastrados por usuários adimministradores com os vindo de integrações, por regra não comparamos entradas de usuário, mas poderia ser utilizado como técnica de teste para obtenção de dados estatísticos, permitido aos cientistas dados relevantes na analise e estrutura de dados. Os benefícios de Levenshtein: O conceito pode reduzir a persistência entrada de dados comuns em usuários e ainda facilitar a integração de sistemas como demonstrado.

Distância de Levenshtein

Se os seguintes valores forem considerados:

Sub(a,a) = 0 para α ∈ Σ 0 para substituições de um caractere por ele mesmo;

Sub(a,b) = 1 para α, b ∈ Σ e α != b 1 para substituições de um caractere por outro diferente;

Del(a) = Ins(a) = 1 para α, ∈ Σ para deleções e inserções de um caractere.

Então, T[m-1,n-1] representa a distância de Levenshtein entre x e y.

Exemplo: x = YHCQPGK e y = LAHYQQKPGKA

Image

Isso resulta nos seguintes seis alinhamentos:

Image

que correspondem aos seis caminhos de custo mínimo entre (-1,-1) e (6,10):

Image

Cada alinhamento mostra a correspondência de caracteres entre as duas strings, considerando substituições, deleções e inserções para calcular a distância de Levenshtein.

https://www-igm.univ-mlv.fr/~lecroq/seqcomp/node2.html