associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

SorteadorDeElemento

Receita: Sorteador de Elementos

Na empresa onde trabalho temos o hábito de promover sorteios para a distribuição de brindes que ganhamos em feiras, congressos e coisas do tipo. Recentemente ganhei um convite do Gmail e resolvi sortear entre o pessoal aqui da empresa. Para isso fiz o programinha abaixo... Sintam-se à vontade para melhorar ele :)

Código

   1 #!/usr/bin/env python
   2 # -*- coding: ISO-8859-1 -*-
   3 
   4 
   5 from inscritos import inscritos
   6 
   7 from Tkinter import *
   8 from Dialog import Dialog
   9 import time
  10 import random
  11 
  12 class MainFrame(Frame):
  13     def __init__(self, parent=None):
  14         Frame.__init__(self, parent)
  15         self.master.title("Sorteia")
  16         self.text = StringVar()
  17         self.nome = StringVar()
  18         self.createWidgets()
  19         self.pack(padx=10, pady=10)
  20 
  21 
  22     def createWidgets(self):
  23         panel1 = Frame(self)
  24         nomeL = Label(panel1, text="Nome:")
  25         nomeL.pack(side=LEFT)
  26         self.nomeE = Entry(panel1, \
  27             textvariable=self.nome, width=50)
  28         self.nomeE.pack(side=LEFT)
  29         self.nomeE.bind("<Return>", self.addEnter)
  30         addB = Button(panel1, text="  +  ", \
  31                       command=self.adicionar)
  32         addB.pack(side=LEFT)
  33         subB = Button(panel1, text="  -  ", \
  34                       command=self.remover)
  35         subB.pack(side=LEFT)
  36         panel1.pack(side=TOP)
  37 
  38         panel2 = Frame(self)
  39 
  40         scrollbar = Scrollbar(panel2, orient=VERTICAL)
  41         self.listbox = Listbox(panel2, \
  42                        yscrollcommand=scrollbar.set, \
  43                        font=("Tahoma", 10, "bold"))
  44         self.listbox.pack(side=LEFT, fill=BOTH, expand=1)
  45         scrollbar.config(command=self.listbox.yview)
  46         scrollbar.pack(side=RIGHT, fill=Y)
  47 
  48         panel2.pack(side=TOP, fill=BOTH, \
  49                               expand=Y, pady=10)
  50 
  51         panel3 = Frame(self)
  52 
  53         sorteiaB = Button(panel3, text="Sorteia",\
  54                           font=("Tahoma", 10, "bold"), \
  55                           command=self.sorteia)
  56 
  57         sorteiaB.pack(side=TOP, fill=BOTH, expand=Y)
  58 
  59         nomeSorteadoT = Label(panel3, \
  60                              textvariable=self.text, \
  61                              font=("Tahoma", 20, "bold"))
  62         nomeSorteadoT.pack(side=TOP, fill=BOTH, \
  63                              expand=Y, pady=20)
  64 
  65         self.nomeSorteadoT = nomeSorteadoT
  66 
  67         panel3.pack(side=TOP, fill=BOTH, expand=Y)
  68         random.shuffle(inscritos)
  69         for nome in inscritos:
  70                 self.listbox.insert(END, nome)
  71 
  72 
  73     def sorteia(self):
  74         listaSorteia = self._getLista()
  75         random.shuffle(listaSorteia)
  76         self.nomeSorteadoT['fg'] = 'black'
  77         if not listaSorteia:
  78             return
  79 
  80         t = 0
  81 
  82         while len(listaSorteia) > 1:
  83             nome = random.choice(listaSorteia)
  84             self.after(t, self.text.set, nome)
  85             t += 1000 / len(listaSorteia)
  86             listaSorteia.remove(nome)
  87 
  88         sorteado = listaSorteia.pop()
  89         self.after(t, self.fimSorteio, sorteado)
  90 
  91     def fimSorteio(self, sorteado):
  92         self.text.set(sorteado)
  93         self.nomeSorteadoT['fg'] = 'red'
  94         self.bell()
  95 
  96     def _getLista(self):
  97         listbox = self.listbox
  98 
  99         lista = [listbox.get(i) for i in range(listbox.size())]
 100         return lista
 101 
 102     def adicionar(self):
 103         nome = self.nome.get()
 104         if not len(nome):
 105             Dialog(self, title="Erro!", \
 106                          text="Nome inválido", \
 107                          bitmap='error', \
 108                          default=0, \
 109                          strings=('OK',))
 110             return
 111 
 112         if nome in self._getLista():
 113             Dialog(self, title="Erro!", \
 114                          text="Já cadastrado", \
 115                          bitmap='error', \
 116                          default=0, \
 117                          strings=('OK',))
 118             return
 119 
 120         self.listbox.insert(END, nome)
 121         self.limpaCampos()
 122 
 123     def addEnter(self, ev):
 124         self.adicionar()
 125 
 126     def remover(self):
 127         self.listbox.delete(ANCHOR)
 128 
 129     def limpaCampos(self):
 130         self.nome.set("")
 131         self.nomeE.focus()
 132 
 133 
 134 
 135 def main():
 136     frm = MainFrame()
 137     frm.mainloop()
 138 
 139 if __name__ == '__main__':
 140     main()

Arquivo: *inscritos.py*

inscritos = ["Charles Babbage",
             "Alan Turing",
             "Ada Lovelace"]

Uma das coisas que tentei fazer e não consegui é um 'efeito visual' que faça com que os nomes fiquem passando antes de parar no nome realmente sorteado. Eu fiz mudar mas a tela não atualizava. Alguém sabe como fazer isso? -- OsvaldoSantanaNeto

Bom... passatempo pra manhã de domingo. :) Ele embaralha a lista de nomes, expõe eles na Label por um tempo igual a 1s / comprimento da lista (assim dá um efeito de "desaceleração" quando o sorteio ocorre). A cada vez que faz isso, retira um dos nomes da lista, embaralha e começa tudo de novo. Quando restar só um nome (o sorteado) ele exibe o nome na Label, muda a cor pra vermelho e emite um sinal (só pra ter certeza). -- PedroWerneck

Página atualizada para representar as modificações feitas para o sorteio da II PyConBrasil. Retiramos o shuffle (que tornava a aplicação muito lenta) e utilizamos o choice para sortear cada um dos nomes da lista. -- EricoAndrei

Versão utilizada para os sorteios na PyConBrasil[3]. Foi feito o embaralhamento, com shuffle, da lista de nomes em dois momentos: Na alimentação do listbox e antes de qualquer sorteio. Foi demandado que o sorteador retire da listbox os nomes já sorteados, a fim de evitar que um mesmo nome seja sorteado duas vezes em uma mesma execução do programa. -- EricoAndrei

Volta para CookBook.


OsvaldoSantanaNeto