Executando verificação de segurança...
2

Podem ajudar com essa lógica!?

Tenho um array com 60 posições, e a cada vez que ele é utilizado preciso passar por 6 vezes, e marcar os numeros passado na posição active como true. O problema é que a cada vez que eu passo por ele, ele reseta o array, marcando somente o ultimo numero passado como true.

Code: https://github.com/heudersena/game-mega-sena/blob/development-02062023/src/cron/CronJobGamer.ts

Podem me da uma força nessa questão?

    // Código
    function retornaNumerosSorteados(numbers: number) {
      const numberArray = Array.from({ length: 60 }, (_, i) => ({ value: i, active: false }))
                const newArray = numberArray.map(item => {
                    return {
                        ...item,
                        active: item.value == numbers
                    }
                })
                console.log(newArray);                
                return newArray
            }

 retornaNumerosSorteados(10)
 retornaNumerosSorteados(14)

Saída:
[
  { value: 0, active: false },
  { value: 1, active: false },
  { value: 2, active: false },
  { value: 3, active: false },
  { value: 4, active: false },
  { value: 5, active: false },
  { value: 6, active: false },
  { value: 7, active: false },
  { value: 8, active: false },
  { value: 9, active: false },
  { value: 10, active: false },
  { value: 11, active: false },
  { value: 12, active: false },
  { value: 13, active: false },
  { value: 14, active: true },
  { value: 15, active: false },
  { value: 16, active: false },
  { value: 17, active: false },
  { value: 18, active: false },
  { value: 19, active: false },
  { value: 20, active: false },
  { value: 21, active: false },
  { value: 22, active: false },
  { value: 23, active: false },
  { value: 24, active: false },
  { value: 25, active: false },
  { value: 26, active: false },
  { value: 27, active: false },
  { value: 28, active: false },
  { value: 29, active: false },
  { value: 30, active: false },
  { value: 31, active: false },
  { value: 32, active: false },
  { value: 33, active: false },
  { value: 34, active: false },
  { value: 35, active: false },
  { value: 36, active: false },
  { value: 37, active: false },
  { value: 38, active: false },
  { value: 39, active: false },
  { value: 40, active: false },
  { value: 41, active: false },
  { value: 42, active: false },
  { value: 43, active: false },
  { value: 44, active: false },
  { value: 45, active: false },
  { value: 46, active: false },
  { value: 47, active: false },
  { value: 48, active: false },
  { value: 49, active: false },
  { value: 50, active: false },
  { value: 51, active: false },
  { value: 52, active: false },
  { value: 53, active: false },
  { value: 54, active: false },
  { value: 55, active: false },
  { value: 56, active: false },
  { value: 57, active: false },
  { value: 58, active: false },
  { value: 59, active: false }
]

Carregando publicação patrocinada...
1

Você apenas não está salvando essa Array :). Então cada vez que a função roda ela gera uma nova array e faz apenas uma alteração.

Para resolver isso você pode ter uma abordagem muito simples, que seria passar a array como parâmetro da função, ou para manter funcionando da mesma forma, utilizar uma closure ou classe para salvar o estado da array.

1
1

Primeira solução:

const numberArray = Array.from({ length: 60 }, (_, i) => ({ value: i, active: false }))

function retornaNumerosSorteados(array: number[], numbers: number) {
  return array.map(item => ({
      ...item,
      active: item.value == numbers
    })
}

retornaNumerosSorteados(numberArray, 10)
retornaNumerosSorteados(numberArray, 14)

Segunda solução (funciona quase igual a classes):

function sorteiaNumeros() {
  const numberArray = Array.from({ length: 60 }, (_, i) => ({ value: i, active: false }))
  
  return (numbers: number) => numberArray.map(item => ({ ...item, active: item.value === numbers }))
}

const retornaNumerosSorteados = sorteiaNumeros()

retornaNumerosSorteados(10)
retornaNumerosSorteados(14)
1

O irmão muito obrigado por disponibilizar do seu tempo e sabedoria.

Que linda essa segunda forma, eu não conhecia esse conceito <3!

Grato!

1
1

Claro, é um erro muito simples que eu não meu atentei.
Ao utilizar a função map nós não mexemos na array original, apenas retornamos uma nova com os novos valores. A abordagem correta é a seguinte:

function sorteiaNumeros() {
  const numberArray = Array.from({ length: 60 }, (_, i) => ({ value: i + 1, active: false }))
  
  return (numbers: number) => {
    numberArray.forEach(item => {
      item.active = item.active || item.value === numbers
    })
    
    return numberArray
  }
}

Basicamente com o forEach nós temos o comportamento contrário, não retornamos nada mas conseguimos alterar os valores da array original.

1
1

TS não é minha especialidade, mas consigo ver erros nas respostas sugeridas.
A primeira solução está tipando array: number[] porém a 'array' seria do tipo '{}[]' ou seja, uma array de objetos.

A segunda solução tem 2 erros. Ambos ocorrem no seu código.
1 - A array de objetos está sendo inicializada dentro da função, logo, cada vez que você chamar a função, todos os números serão criados novamente de forma inativa, não há memória salvando os que foram ativados.
2 - Na ativação está sendo feito active: item.value === numbers, ou seja, mesmo se a função "decorasse" que o 10 já foi ativado, quando fosse a interação do 14, essa comparação retornaria FALSE, o que desativaria o 10 novamente.

O código abaixo eu fiz num editor online e funcionou:

function sorteiaNumero(numberArray: {value: number, active: boolean}[], numbers: number) {
            const newArray = numberArray.map(item => {
                return {
                    ...item,
                    active: item.active? true : item.value === numbers
                }
            })
            console.log(newArray);                
            return newArray
        }
        let numberArray = Array.from({ length: 60 }, (_, i) => ({ value: i, active: false }))


numberArray = sorteiaNumero(numberArray, 10)
numberArray = sorteiaNumero(numberArray, 14)

Repare que eu crio o 'numberArray' fora do escopo da função, e cada vez que eu chamo a função eu reatribuo os valores da 'numberArray', dessa forma, fica memorizado o número que foi ativado anteriormente.

Provavelmente dá pra refatorar, eu fiz "na pressa", mas acho que te atende por hora.

1

Obrigado pela explicação irmão, com certeza irei estudar suas dicas!

Fico agradecido por disponibilizar do seu tempo em ajudar o próximo!

Que Deus te abençoe!

1

Como já disseram, o problema é que dentro da função vc está recriando o array novamente. Então o certo é criar o array fora e passá-lo como argumento da função.

Mas tem outros detalhes para se pensar. Por exemplo, map sempre retorna um novo array, então só seria interessante criar outro array se vc precisasse preservar o original. Vc precisa manter o array original, ou só precisa do resultado final, com os números setados com active: true?

Se não precisa preservar o array original, é desnecessário usar map e ficar criando um novo array a cada número setado. Neste caso, a função poderia simplesmente alterar o array:

function sorteiaNumero(numberArray: {value: number, active: boolean}[], activeNumber: number) {
    for (const item of numberArray) {
        if (item.value === activeNumber) {
            item.active = true;
            break;
        }
    }
}

// outra forma de criar o array
let numberArray = [];
for (let i = 1; i <= 60; i++) {
    numberArray.push({ value: i, active: false });
}

sorteiaNumero(numberArray, 10);
sorteiaNumero(numberArray, 14);
console.log(numberArray); // 10 e 14 setados

Vi no GitHub que vc está criando um array com os números de 1 a 60 (que é diferente do exemplo que vc colocou acima, que coloca de 0 a 59). Enfim, sugeri acima uma outra forma de criá-lo, usando um for simples.

E como os números do array não se repetem, só preciso seguir no loop até encontrar o número. Depois, posso interromper o for usando um break (se os números se repetissem, aí teria que tirar o break).

Também mudei o nome do parâmetro: em vez de numbers, usei activeNumber. Pode parecer um detalhe besta, mas dar nomes melhores ajuda na hora de programar. O nome numbers está no plural, e passa a ideia - neste caso, errada - de são vários números. Mas pelo que entendi, é um só, então mudei para um nome no singular e que tenha mais a ver com o que ele representa.


Um detalhe: neste caso específico vc sabe que o array tem números de 1 a 60 em ordem. Ou seja, o número 1 está na posição 0, o número 2 está na posição 1 e assim por diante. Então a função poderia ser apenas:

function sorteiaNumero(numberArray: {value: number, active: boolean}[], activeNumber: number) {
    numberArray[activeNumber - 1].active = true;
}

Mas como eu já disse, é apenas para este caso específico, e só se vc garantir que sempre vai chamar a função passando um número entre 1 e 60. Para os casos mais genéricos, um loop é o mais indicado.


Complementando, dei uma olhada rápida pelo código do GitHub, e talvez essa complicação toda seja desnecessária. Nem tudo precisa de async/await. Por exemplo, sua função generateUniqueNumbers, não faz o menor sentido ela retornar uma Promise, já que não faz nenhuma operação assíncrona que necessita de espera. Bastaria que ela retornasse o array diretamente:

function generateUniqueNumbers(): Number[] {
    const numeros: Number[] = [];
    for (let i = 1; i <= 60; i++) {
        numeros.push(i);
    }
    // Embaralha os números
    for (let i = numeros.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [numeros[i], numeros[j]] = [numeros[j], numeros[i]];
    }
    // Retorna os primeiros 5 números do array
    // não precisa de variáveis intermediárias, pode retornar direto
    return numeros.slice(0, 6).sort((a: number, b: number) => a - b);
}

Vi que na função FN_GET_NUMBER_GAME() vc transforma o array em string, só para passá-lo para insertValueTableGame. Mas depois vc transforma esta string novamente em array, usando split. Esse trabalho todo é desnecessário.

O que eu faria: remova essa função FN_GET_NUMBER_GAME(), e use diretamente a que gera os números. E vc converte para string somente na hora de salvar:

const NEW_NAMBER_GAME = generateUniqueNumbers(); // nada de async/await, é desnecessário
...
const GAMER = await insertValueTableGame(NEW_NAMBER_GAME.toString(), LAST_NAMBER_INSERTED_TABLE_GAME);

E claro, arrume esses nomes. NAMBER está errado (é "U" em vez de "A"), mas acho que o nome atual também não é bom, pois não passa a ideia de que é o array de números. Poderia ser UNIQUE_NUMBERS ou algo assim. Na verdade, não sei porque adotou esse padrão de tudo em maiúsculas, mas enfim. Agora que esta variável contém o array, pode usá-la no restante do programa, no lugar de TRANSFORME_STRING_TO_ARRAY (outro péssimo nome, aliás).

Enfim, não parei pra ver todo o código, mas não entendi porque sorteiaNumeros precisa retornar outra função. Parece que tem várias complicações desnecessárias aí.