Issue #1

A busca avançada do Gatherer parece quebrada, e tem por um tempo (eu adivinharia pelo menos seis meses). Eu não consegui encontrar ninguém falando sobre isso através do Google. Isso me fez pensar se eu estava fazendo algo errado, ou se ninguém mais notou, ou se eu simplesmente não estava procurando bem o suficiente para encontrar discussões anteriores. Eu decidi fazer alguma investigação.

Os dois principais problemas para o Gatherer como eu os vejo.

  1. Fazer uma pesquisa avançada com dois ou mais critérios (por exemplo, uma pesquisa por todos os cartões Azul, Preto e Vermelho. Depois, clique em x ao lado de um desses critérios na página de resultados da pesquisa. O critério desaparece da lista, mas o resultado do cartão não atualiza.
  2. Faça uma busca avançada com um ou mais critérios (por exemplo, Cor: DOES contém Azul). Em seguida, clique em “Refinar busca”. Os parâmetros anteriores não aparecem na caixa de critérios de busca avançada.

Pareçe que me lembro de ter atingido um terceiro problema no passado, algo relacionado a preencher o critério na página de pesquisa avançada, mas agora não me lembro do que era.

Testei isto em vários navegadores (Google Chrome, Mozilla Firefox, e Microsoft Edge). Eu testei isto em múltiplos dispositivos (um laptop, dois desktops, e um telefone). Eu testei isso em vários sistemas operacionais (Windows 10, Ubuntu 16.04, Ubuntu 18.04, Android 8, Android 9).

O melhor que posso dizer olhando apenas para o código do lado do cliente, acredito que isso é um problema com a forma como a resposta do servidor é tratada pela IU do Gatherer (e possivelmente um problema com a forma como o servidor responde, também).

Em AdvancedSearch.js::AdvSearchConditionCallback, linha 872, podemos ver como a IU do Gatherer espera lidar com a resposta do servidor:

var results = eval("(" + transport.responseText + ")");

A resposta que o servidor está a enviar aqui é JSON. Por exemplo, se eu fizer uma busca por todos os cartões Azul, Preto e Vermelho, e depois clicar em x para remover o critério “DOES contain Red”, a resposta que eu recebo é:

{ "LCID": 0, "CommandName": null, "CommandListPath": null, "SearchTerms": null, "SubQueryDelimiter": "Union", "SearchTermDelimiter": "And", "EscapeInputDelimiters": true, "EncodedSerializedQuery": "YwBvAGwAbwByAD0AKwBbAFUAXQArAFsAQgBdAA==", "ExtraSafeKeys": , "IncludeSpecial": false, "Filters": { "color": { "Identifier": "fe329dcb-d64a-4939-bfd6-7af5c102d655", "LogicalOperator": "Intersect", "From": "color", "Terms": ", "LogicalOperator": "And", "State": "+" }, { "Identifier": "b622e49d-87de-439f-ac75-0e99ffee07c6", "FormatString": "color", "Value": "", "LogicalOperator": "And", "State": "+" } ], "State": null, "FormatString": "color", "Value": ", "LogicalOperator": "And", "State": "+" }, { "Identifier": "b622e49d-87de-439f-ac75-0e99ffee07c6", "FormatString": "color", "Value": "", "LogicalOperator": "And", "State": "+" } ] } }, "State": "color=++"} 

Nota o JSON não parece ter nenhuma informação sobre quais cartões devem ser exibidos, e eu não vejo nenhum código em AdvancedSearch.js que lidaria com uma lista de cartões.

Então, chamando eval("(" + transport.responseText + ")") nisto funciona bem, convertendo a string JSON em um objeto JSON. AdvancedSearch.js então usa esse objeto JSON para atualizar a exibição da caixa de critérios de pesquisa. Entretanto, ele não atualiza a URL atual, (para ir de “?action=advanced&color=+++” para “?action=adanced&color=++”, por exemplo).

Agora, o Prototype.js está configurado de tal forma que ele também tentará avaliar a resposta. Mas, Prototype.js não é escrito para assumir que a resposta é JSON. Então, em Prototype.js::respondToReadyState (linha 1498), Prototype.js tenta eval esta string JSON como JavaScript (em evalResponse (linha 1533)), e como a string JSON não está entre parênteses, a avaliação falha:

SyntaxError: Unexpected token : at klass.evalResponse (Prototype.js:1533) at klass.respondToReadyState (Prototype.js:1501) at klass.onStateChange (Prototype.js:1436) at XMLHttpRequest.<anonymous> (Prototype.js:291)

Vale notar, no entanto, que mesmo que você modifique Prototype.js para incluir a string entre parênteses, ele apenas converte a string em um objeto JSON e depois não faz nada com ele. Além disso, se você modificar AdvancedSearch.js para configurar Prototype.js para não avaliar a resposta, ele simplesmente segue em frente e o resultado final é o mesmo.

Então, até onde posso dizer, há dois possíveis problemas:

  1. A UI do Gatherer (e AdvancedSearch.js em particular) deve alterar a URL atual, navegando para os novos resultados da busca.
  2. A UI do Gatherer é suposto consultar a URL retornada em segundo plano (ou talvez o servidor seja suposto incluir todas as cartas na resposta), e depois actualizar dinamicamente a lista de cartas.

Se #1 for o caso, então toda a lógica para atualizar dinamicamente a lista de critérios de busca seria inútil; assim que o navegador navegar para a nova URL, ele irá carregar uma página totalmente nova, com a lista de critérios já preenchida e as novas cartas exibidas. Isso também tornaria a primeira consulta (e a resposta do servidor) inútil, pois a IU já tem a informação que o servidor retorna, e poderia simplesmente navegar diretamente para esse URL.

Se o #2 for o caso, acredito que é provável que o servidor tenha um problema onde é suposto retornar a lista de cartas resultante em primeiro lugar. Caso contrário, mais uma vez, esta primeira consulta parece inútil, pois a resposta não inclui nada que a IU já não tivesse. De qualquer forma, a IU tem um problema onde ela não tem (aparentemente) nenhum código para atualizar dinamicamente a lista de cartões, de qualquer forma.

Esta é ainda mais complicada, porque nem sempre acontece. Às vezes quando você clica em “Refine Search”, ele funciona corretamente. No entanto, na maioria das vezes, não funciona. Para aqueles que não estão na indústria de desenvolvimento de software, isto é provavelmente o que é conhecido como “Race Condition”: duas coisas estão acontecendo simultaneamente, e o resultado final depende da ordem em que elas terminam. (É como a pilha no Magic, onde a ordenação de dois efeitos pode ter resultados drasticamente diferentes).

Aqui está o que eu vejo como o cerne da questão.

Vamos usar o nosso exemplo acima novamente, de uma busca por todas as cartas Azul, Preto e Vermelho. Se você inspecionar o botão “Refine Search”, você vai ver isto:

>

<a href="/Pages/Advanced.aspx?action=advanced&amp;color=+++" class="refineSearchLink">Refine Search</a>

Então, isto deve ser bastante simples. Navegue para a página de busca avançada com o mesmo critério de busca. O problema é o que realmente acontece com isso. Se você for para a página ligada, se você clicar no botão “Refine Search”, ou este link adicionado neste post, ou copiar-colar a URL na barra de endereço, isto (geralmente) não funciona; a página volta sem critérios de pesquisa preenchidos. O que é interessante para mim é que, novamente, parece ser um problema tanto com o servidor quanto com a IU (possivelmente ambos).

Se você for para a guia Rede nas ferramentas dos desenvolvedores do seu navegador e navegar até essa página, a primeira entrada que aparece na lista de atividades é a solicitação para “Pages/Advanced.aspx?action=advanced&color=+++”. Se você clicar para ver a Resposta, você verá o HTML completo da página como ela apareceu quando retornou pela primeira vez. Onde os Critérios de Pesquisa devem ser preenchidos, você encontra

<div class="filters" ><span style="display: none;">None yet.</span>

Acima disso está uma chamada para um script que parece ser destinado a preencher essa lista:

<script type="text/javascript">RetrieveCurrentSearchConditions();</script>

Localizando em RetrieveCurrentSearchConditions em AdvancedSearch.js, está tentando fazer um pedido Ajax, com os seguintes parâmetros (linha 406):

parameters: { cacheBust: new Date().getTime(), encodedSerializedPrevious: $(ClientIDs.encodedSerializedParameters).value }

O problema é que, se você quebrar esta linha (ou apenas ler através da resposta HTML bruta do servidor), o elemento ao qual encodedSerializedParameters se refere não tem um valor nesta resposta. Então, nós então fazemos este pedido com encodedSerializedParameters: "", e nós, previsivelmente, obtemos de volta filtros de pesquisa vazios. Então porque é que isto está a acontecer? Bem, se você voltar aos resultados da busca, e visualizar a fonte, você verá que encodedSerializedParameters tem um valor: YwBvAGwAbwByAD0AKwBbAFUAXQArAFsAQgBdACsAWwBSAF0A (codificação base 64 para “color=++++”).

Então, parece que este código está escrito esperando ser chamado enquanto ainda na página de resultados da busca, mas então ele não é realmente chamado até que o navegador já tenha navegado de volta para a página de busca avançada.

Então, parece que o servidor deve estar respondendo com o campo value do elemento encodedSerializedParameters já populado, mas não está. Ou, a IU é suposto de alguma forma recolher esse valor antes de navegar, e passá-lo através da navegação a ser usada na página seguinte. Ou, possivelmente, a IU deve ter uma função para retirar essa informação de pesquisa da URL (onde a informação da consulta é preenchida), e adicioná-la à caixa de critérios de pesquisa.

Eu sei que tudo isso funcionou em algum momento, então eu não tenho idéia de como esse código quebrado foi liberado, e como ele permaneceu quebrado por tanto tempo. Logo antes de publicar isto, decidi fazer uma pesquisa especificamente no r/magicTCG, e encontrei posts que podem estar referenciando esses mesmos problemas (por exemplo, o critério de pesquisa ‘Advanced Search’ do Gatherer repõe semi-randomly. Ajuda?, Problemas com a Pesquisa Avançada do Gatherer), e fiquei surpreso ao ver que eles são tão antigos (1 ano, 3 anos respectivamente para os exemplos acima). Portanto, se eles estão se referindo aos mesmos problemas, eles estão fora há muito tempo.

Então, a questão é, Será que os Feiticeiros da Costa acabaram de abandonar o Gatherer? (Ou pelo menos a sua pesquisa avançada?)

Leave a Reply