Django Wars [Parte 26]: Procurando alvos para atacar

O Django Wars foi idealizado e desenvolvido no Django 1.4. Algumas funcionalidades aqui descritas podem não funcionar ou funcionar de forma diferente em outras versões do Django

A melhor parte do jogo é destruir os outros jogadores e tentar se tornar o melhor do melhor do mundo!
Para atacar alguém primeiro temos que ter uma lista de alvos, e é isso que vamos fazer agora.

Vamos começar criando a view.
Para isso, vou criar um novo arquivo na pasta views chamado luta.py, com a view que faz a listagem de possíveis alvos.

# Create your views here.
from django.shortcuts import render_to_response # funcoes de renderizacao dos templates
from django.shortcuts import redirect # Funcao para executar um http-redirect

from djangowars.players.models import Player # precisamos para listar os alvos





# pagina que lista os possiveis alvos
def alvos(request):
    if not request.user.is_authenticated():
        return redirect('pagina_de_login')
    
    #da um refrash no hp, energia e raiva do player
    jogador = request.user.get_profile()
    jogador.refresh()
    jogador.save()
    
    
    #pega os alvos
    # jogadores que estejam no range entre 60% e 140% da xp do jogador
    # nao pode ser o nosso jogador
    # nao pode ser um jogador com 0 de experiencia
    # nao pode ser um jogador morto. hp = 0
    # pega apenas 10
    # quem me deu a dica de como aninhar varios filtros de forma elegante, de acordo com a PEP-8 foi o Renato Oliveira <http://www.labcodes.com.br/>
    alvos = Player.objects.filter(
        experiencia__gte = (jogador.experiencia * 0.6)
    ).filter(
        experiencia__lte = (jogador.experiencia * 1.4)
    ).exclude(
        id = jogador.id
    ).exclude(
        experiencia = 0
    ).exclude(
        hp = 0
    ).exclude[:10]
    
    
    
    return render_to_response("alvos.html", {"player": jogador,
                                             "vida": jogador.vida * 10,
                                             "alvos": alvos})

Acho que essa deve ser a view mais complicada que fizemos desde comecei com a idéia do Django-Wars.
E olha que essa já é a postagem de número 26 do projeto.

O que fazemos aqui é o seguinte: operações básicas do usuário de verificar se ele está logado e de dar o refresh nele, e depois fazemos uma listagem de alvos.
O que queremos é pegar usuários que tenham entre 60% e 140% do XP do usuário.
Assim criamos um “range” de jogadores que não sejam nem muito fortes e nem muito fracos em relação ao jogador logado.

Parar filtra, precisamos nos “conectar” a listagem de objetos do tipo Player, que definimos no models há um bom tempo atrás.
Para isso, Player.objects.
Se você digitar Player.objects.all() você estará pegando todos os jogadores.
Mas queremos filtrar e, para filtrar utilizamos filter e exclude.
No primeiro filtro, desejo informar que a experiência necessária deve ser maior-igual, nesse caso “greater-than-equal” (abreviado como gte), a 60% da experiência do nosso jogador.
Note que para falar de um filtro utilizamo o campo__comparação.
Esse primeiro filtro, em um SQL seria algo assim:

SELECT * FROM player WHERE experiencia >= 'valor_passado'

Mas, só isso não basta.
Além de pegar os jogadores cuja experiência seja maior-igual que 60% da experiência do nosso jogador, queremos que essa também seja menor que 140% da experiência do nosso jogador.
Se fossemos fazer um SQL teriamos algo nessa ideia:

SELECT * FROM player WHERE experiencia >= 'valor_passado' AND experiencia <= 'valor_qualquer'

A forma mais fácil de fazer esse AND é simplesmente empurrar outro filter() formando uma cadeia de filtros.
Assim, depois do primeiro .filter, podemos colocar outro .filter, e depois outro e outro, até que nossas condições estejam satisfeitas.
Não sendo o bastante, também podemos colocar chamadas como .exclude ou .oder_by.

Depois de utilizarmos nossos .filter, utilizei .exclude.
Deu pra entender o que eles fazem?
ISSO MESMO SNOOPY, eles excluem o que a gente não quer.
No caso, temos dois excludes diferentes, um para excluir o caso em que o id do jogador pesquisado no banco de dados seja o mesmo id que o jogador que está fazendo a caça, e o outro exclude é para remover da listagem jogadores que tenham experiência igual a 0.

Por fim, limitamos a nossa busca.
Não queremos listar tudo, queremos apenas 10.
Para limitar a busca no Django utilizamos a operação de cortar uma lista.

Em um primeiro momento é um pouco esquisito, mas é tudo tão simples que assusta.

Por fim, para terminarmos precisamos colocar esta view no arquivo urls.py e criar um template para ela.

URLS.PY

import djangowars.views.luta
url(r'^alvos/$', djangowars.views.luta.alvos, name='pagina_de_alvos'),

ALVOS.HTML

<div class="container">
    <p>
        Informações do usuário:
        Nível {{  player.nivel }}
        |
        Energia {{  player.energia_atual }}/{{ player.energia }}
        |
        Raiva {{ player.raiva_atual }}/{{ player.raiva }}
        HP: {{ player.hp }}/{{ vida }}
        |
        Carteira {{ player.carteira }}
    </p>

    <!--lista de alvos-->
    {% for alvo in alvos %}
        <p>{{ alvo.user.username }} - Level {{ alvo.nivel }} - <a href="atacar/{{ alvo.id }}">ATACAR!!!</a></p>
    {% endfor %}

</div> <!-- /container -->

Tá quase acabando.
QUE GLÓRIA!
😀

Estou ouvindo o acústico do Ultraje a Rigor.
DA HORA!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *