def __init__(self): ## VER SI NECESITO CONSTRUCTOR self.bloques_memoria = [] ##arreglo que posee el numero de archivo i ## si el bloque esta ocupado por el archivo i y 0 si no self.espacios_libres = 20 #al principiio todos los espacios estaran vacios self.cantidad_archivos = 0 self.nombres_archivos = [] self.nombres_archivos.append(None) ## LOS NOMBRES VAN DEL INDICE 1 EN ADELANTE self.Inodos = [] self.disc = Disco() for x in xrange(0,20): self.bloques_memoria.append([0, 0])
def run(self): #Populate probe id's probeCon = ProbeDataConsumer( self.asnFilters, self.countryFilters, self.proximityFilters, self.startTime, self.endTime ) probeCon.attach(self) probeCon.start() logging.warning('Loaded data for {} probes'.format(len(self.probeData))) Disco( threshold=self.threshold,startTime=self.startTime,endTime=self.endTime,timeWindow=self.timeWindow, probeData=self.probeData, topicIn=self.topicIn, topicOut=self.topicOut, slideStep=self.slideStep ).start()
# -*- coding: utf-8 -*- from memoria import Memoria from processo import Processo from disco import Disco from menu import menu if __name__ == "__main__": menu() mem = Memoria() disco = Disco() processo = Processo(escrita=True) processo2 = Processo(escrita=True) processo3 = Processo(escrita=True) processo4 = Processo(escrita=False) mem.init_Mem() disco.init_Disco() if mem.mapear_processo(processo): print("[+] O processo 1 foi mapeado para a memória") if mem.mapear_processo(processo2): print("[+] O processo 2 foi mapeado para a memória") if mem.unmmap_processo(processo, disco): print("[+] O processo 1 foi desmapeado da memória") if mem.mapear_processo(processo3): print("[+] O processo 3 foi mapeado para a memória")
import tserver, sys, random, time from disco import Disco def data_gen(path): return "badger\n" * 100 def fun_map(e, params): msg(e) return [] tserver.run_server(data_gen) inputs = tserver.makeurl([1]) job = Disco(sys.argv[1]).new_job(name = "test_ratelimit", input = inputs, map = fun_map) time.sleep(5) if job.jobinfo()['active'] == "dead": print "ok" job.clean(name) else: raise Exception("Rate limit failed")
def fun_reduce(iter, out, params): s = {} for k, v in iter: if k in s: s[k] += int(v) else: s[k] = int(v) for k, v in s.iteritems(): out.add(k, v) tserver.run_server(data_gen) job = Disco(sys.argv[1]).new_job(\ name = "test_profile",\ input = tserver.makeurl([""] * int(100)),\ map = really_unique_function_name,\ reduce = fun_reduce,\ nr_reduces = 30,\ sort = False,\ profile = True) ANS = {"gutta": int(1e4), "cavat": int(2e4), "capidem": int(1e4)} i = 0 for key, value in result_iterator(job.wait()): i += 1 if ANS[key] == int(value): print "Correct: %s %s" % (key, value) else: raise "Results don't match (%s): Got %d expected %d" %\ (key, int(value), ANS[key]) if i != 3: raise "Too few results"
def fun_reduce(iter, out, params): for k, v in iter: out.add("red_" + k, "red_" + v) tserver.run_server(data_gen) inputs = ["ape", "cat", "dog"] params = {"test1": "1,2,3",\ "one two three": "dim\ndam\n",\ "dummy": "value"} job = Disco(sys.argv[1]).new_job( name = "test_external", input = tserver.makeurl(inputs), map = external(["ext_test"]), reduce = fun_reduce, ext_params = params, nr_reduces = 1, sort = False) results = sorted([(v, k) for k, v in result_iterator(job.wait())]) for i, e in enumerate(results): v, k = e if k != "red_dkey" or v != "red_test_%s" % inputs[i / 3]: raise Exception("Invalid answer: %s, %s" % (k, v)) if len(results) != 9: raise Exception("Wrong number of results: %u vs. 9" % len(results)) job.purge()
else: raise Exception("Rate limit failed") def data_gen(path): return "badger\n" * 1000000 def fun_map(e, params): msg(e) return [] def fun_map2(e, params): return [] tserver.run_server(data_gen) inputs = tserver.makeurl([1]) job = Disco(sys.argv[1]).new_job(name = "test_ratelimit", input = inputs, map = fun_map) time.sleep(5) check_dead(job) job = Disco(sys.argv[1]).new_job(name = "test_ratelimit2", input = inputs, map = fun_map2, status_interval = 1) time.sleep(5) check_dead(job) job = Disco(sys.argv[1]).new_job(name = "test_ratelimit3", input = inputs, map = fun_map2, status_interval = 0) job.wait() job.purge()
for k, v in iter: s += int(v) out.add(k, s) tserver.run_server(data_gen) N = 100 results = {} inputs = [] for i in range(N): a = [i] * 10 b = range(i, i + 10) inputs += ["%d:%d" % x for x in zip(a, b)] results[str(i)] = str(sum(b)) disco = Disco(sys.argv[1]) job = disco.new_job(\ name = "test_chunked", input = tserver.makeurl(inputs), map = fun_map, partition = fun_partition, reduce = fun_reduce, chunked = False, nr_reduces = N, sort = False) for k, v in result_iterator(job.wait()): if results[k] != v: raise "Invalid result, got %s, expected %s" %\ (v, results[k]) del results[k]
import tserver, sys, random, time from disco import Disco def data_gen(path): return "badger\n" * 100 def fun_map(e, params): msg(e) return [] tserver.run_server(data_gen) inputs = tserver.makeurl([1]) job = Disco(sys.argv[1]).new_job(name = "test_ratelimit", input = inputs, map = fun_map) time.sleep(5) if job.jobinfo()['active'] == "dead": print "ok" job.purge() else: raise Exception("Rate limit failed")
import sys from disco import Disco OK_STATUS = ['job_ready', 'job_died'] disco = Disco(sys.argv[1]) def op_show(n, s): print n def op_kill(n, s): if s == "job_active": print "Killing", n disco.kill(n) def op_clean(n, s): print "Cleaning", n disco.clean(n) def op_purge(n, s): print "Purging", n disco.purge(n) for t, s, name in disco.joblist(): if sys.argv[3] in name: globals()["op_" + sys.argv[2]](name, s)
"\n" + str(pid) + ";" + name + ";" + str(quantum) + ";" + str(priority) + ";" + str(size), False) else: disco.escreverProcessoDisco( str(pid) + ";" + name + ";" + str(quantum) + ";" + str(priority) + ";" + str(size), False) tabelaDisco.delete(*tabelaDisco.get_children()) for item in disco.getDisco(): tabelaDisco.insert('', 'end', values=item) janela = tk.Tk() janela.title("Projeto Kernel") tamanhoMemoria = 4 memoriaVirtual = MemoriaVirtual(tamanhoMemoria) disco = Disco("arquivo.txt") # Memória Virtual ---------------------------------------------------- mVlabel = tk.Label(janela, text="Memória Virtual:") mVlabel.place(x=20, y=10) dataColsVirtual = ('BITR', 'TIME', 'INDEX', 'PID') tabelaVirtual = ttk.Treeview(janela, columns=dataColsVirtual, show='headings', height=tamanhoMemoria) tabelaVirtual.column(column='BITR', width='40') tabelaVirtual.column(column='TIME', width='40') tabelaVirtual.column(column='INDEX', width='40') tabelaVirtual.column(column='PID', width='40')
class ram(): def __init__(self): ## VER SI NECESITO CONSTRUCTOR self.bloques_memoria = [] ##arreglo que posee el numero de archivo i ## si el bloque esta ocupado por el archivo i y 0 si no self.espacios_libres = 20 #al principiio todos los espacios estaran vacios self.cantidad_archivos = 0 self.nombres_archivos = [] self.nombres_archivos.append(None) ## LOS NOMBRES VAN DEL INDICE 1 EN ADELANTE self.Inodos = [] self.disc = Disco() for x in xrange(0,20): self.bloques_memoria.append([0, 0]) def imprime_archivos(self): for i in range(len(self.nombres_archivos)): print self.nombres_archivos[i] print " en bloque " + str(i) + " de RAM" def agregar_archivo(self,cant_bloques, nombre_archivo): ## recibo la cantidad de bloques que utilizare de la ram y el archivo que deseo guardar bloques = [] ## variable que guardara cada bloque de 1024 bytes (a excepcion del ultimo) self.nombres_archivos.append(nombre_archivo) self.cantidad_archivos += 1 posicion_bloques_en_RAM = [] f = open(nombre_archivo) # abrimos para leer el archivo falta poner DIRECCION for x in xrange(0, cant_bloques): if x < cant_bloques - 1: bloques.insert(x, f.read(1024)) else: bloques.insert(x, f.read(os.path.getsize(nombre_archivo) - 1024*(cant_bloques-1))) ## verificar que la resta sea la correcta ## leo y guardo en los bloques contador_bloques = 0 ## contador que me indica que pedazo de archivo cortado voy copiando indice_archivo = self.cantidad_archivos inode = Inodo(nombre_archivo,indice_archivo) ##ACA deberia obtener el indice_actual de la clase disco y segun los bloques que necesito ## poner las direcciones en posicion actual + cant de bloques posicion_cabezal_directo = self.disc.getPosActual() for k in range(4,4+cant_bloques): inode.estructura.insert(k,posicion_cabezal_directo) posicion_cabezal_directo += 1 self.Inodos.append(inode) bloques_copiados = 0 #cantidad de pedazos del archivo que ya he copiado if self.espacios_libres < cant_bloques: ##aca va el metodo donde pido espacios y me devuelve un arreglo con los espacios que debo sacar reemplazados = reemplazar(self.bloques_memoria,cant_bloques-self.espacios_libres) ##obtengo los id de los bloques que reemplazare for i in range(0,20): if self.bloques_memoria[i][0] in reemplazados: self.bloques_memoria.insert(i ,[0, 0]) #reemplazo por vacio los bloques con indices devueltos for j in range(0,20): archivos_editados = [] #Arreglo que retorno a la clase disco if self.bloques_memoria[j][0] == 0 and bloques_copiados < cant_bloques: self.bloques_memoria.insert(j , [indice_archivo, contador_bloques]) #guardo indice, y offset de pedazo de archivo posicion_bloques_en_RAM.append(i) bloque_abierto_ram = open("ram/"+str(j)+".txt","w") #abro el archivo que quiero bloque_abierto_ram.write(bloques[contador_bloques]) ##escribo el pedazo de archivo que quiero escribir bloques_copiados += 1 bloque_abierto_ram.close() archivos_editados.append(j) #agrego el numero del archivo de la RAM que abri contador_bloques += 1 self.espacios_libres -= 1 elif bloques_copiados >= cant_bloques: #si ya copie todo, salgo del for #Si ya he copiado todo, entrego el arreglo al disco self.disc.Agregar_Bloques(archivos_editados) break else: for x in range(0,20): archivos_editados = [] #Arreglo que retorno a la clase disco if self.bloques_memoria[x][0] == 0 and bloques_copiados < cant_bloques: self.bloques_memoria.insert(x , [indice_archivo, contador_bloques]) #guardo indice, y offset de pedazo de archivo posicion_bloques_en_RAM.append(x) bloque_abierto_ram = open("ram/"+str(x)+".txt","w") #abro el archivo que quiero bloque_abierto_ram.write(bloques[contador_bloques]) ##escribo el pedazo de archivo que quiero escribir bloques_copiados += 1 bloque_abierto_ram.close() archivos_editados.append(x) #agrego el numero del archivo de la RAM que abri contador_bloques += 1 self.espacios_libres -= 1 elif bloques_copiados >= cant_bloques: #Si ya he copiado todo, entrego el arreglo al disco self.disc.Agregar_Bloques(archivos_editados) break f.close() return posicion_bloques_en_RAM def leer_archivo(self,name_archivo): if name_archivo in self.nombres_archivos: posicion = self.nombres_archivos.index(name_archivo) #obtenemos el id que representa a ese archivo #AHORA debo verificar que el archivo este en la RAM, sino lo iremos a buscar encontrado = False for x in xrange(0,20): if posicion == self.bloques_memoria[x][0]: #si esta dentro de la memoria RAM, sino, busco el disco y copio a RAM encontrado = True if encontrado == True: ##aca debo obtener todos los bloques tales que bloques_memoria[x,0] == posicion. partes = [] for i in range(0,20): if self.bloques_memoria[i][0] == posicion: partes.append([i,self.bloques_memoria[i][1]]) #Guardo el archivo que debo leer y el offset ##Al obtener todos los bloques, debo ordenarlos segun el segundo parametros de bloques_memoria partes = sorted(partes, key = lambda student: student[1]) ##metodo para ordenar # es decir segun bloques_memoria[x,1]... luego los imprimo en consola y los muestro ## Ahora simplemente leo los archivo de nombre (i).txt de partes y los imprimo for j in range(0,len(partes)): f = open("ram/"+str(partes[j][0])+".txt") dato = f.read() print dato f.close() else: #si no lo encuentro, el disco los debe copiar en la RAM y luego debo leerlos ##FALTA METODO DE DISCO DURO pos_inicial = 0 largo_archivo = 0 indice_archivo = 0 posicion_bloques_en_RAM = [] for x in xrange(0,len(self.Inodos)): if self.Inodos[x].estructura[0] == name_archivo: pos_inicial = self.Inodos[x].estructura[4] ##primero bloque dentro del disco que corresponde al archivo largo_archivo = self.Inodos[x].estructura[1] indice_archivo = self.Inodos[x].estructura[3] datos_retornados = self.disc.Leer_Bloques(int(pos_inicial), int(largo_archivo)) ##Obtengo los datos que quiero leer desde el disco bloques_copiados = 0 #cantidad de pedazos del archivo que ya he copiado contador_bloques = 0 if self.espacios_libres < len(datos_retornados): ##aca va el metodo donde pido espacios y me devuelve un arreglo con los espacios que debo sacar reemplazados = reemplazar(self.bloques_memoria,len(datos_retornados)-self.espacios_libres) ##obtengo los id de los bloques que reemplazare for i in range(0,20): if self.bloques_memoria[i][0] in reemplazados: self.bloques_memoria.insert(i ,[0, 0]) #reemplazo por vacio los bloques con indices devueltos for j in range(0,20): if self.bloques_memoria[j][0] == 0 and bloques_copiados < len(datos_retornados): self.bloques_memoria.insert(j , [indice_archivo, contador_bloques]) #guardo indice, y offset de pedazo de archivo posicion_bloques_en_RAM.append(i) bloque_abierto_ram = open("ram/"+str(j)+".txt","w") #abro el archivo que quiero bloque_abierto_ram.write(datos_retornados[contador_bloques]) ##escribo el pedazo de archivo que quiero escribir print datos_retornados[contador_bloques] #Imprimo en consola lo que quiero leer bloques_copiados += 1 bloque_abierto_ram.close() contador_bloques += 1 self.espacios_libres -= 1 elif bloques_copiados >= len(datos_retornados): #si ya lei todo, salgo del for break else: for x in range(0,20): if self.bloques_memoria[x][0] == 0 and bloques_copiados < len(datos_retornados): self.bloques_memoria.insert(x , [indice_archivo, contador_bloques]) #guardo indice, y offset de pedazo de archivo posicion_bloques_en_RAM.append(x) bloque_abierto_ram = open("ram/"+str(x)+".txt","w") #abro el archivo que quiero bloque_abierto_ram.write(datos_retornados[contador_bloques]) ##escribo el pedazo de archivo quiero quiero escribir print datos_retornados[contador_bloques] #Imprimo en consola lo que quiero leer bloques_copiados += 1 bloque_abierto_ram.close() contador_bloques += 1 self.espacios_libres -= 1 elif bloques_copiados >= cant_bloques: #Si ya he leido todo, entrego el arreglo al disco break
s = 1 for k, v in iter: if k != "=" + v: raise Exception("Corrupted key") s *= int(v) out.add("result", s) tserver.run_server(data_gen) inputs = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31] job = Disco(sys.argv[1]).new_job( name = "test_writers", input = tserver.makeurl(inputs), map = fun_map, map_writer = fun_map_writer, reduce = fun_reduce, reduce_reader = fun_reduce_reader, reduce_writer = fun_reduce_writer, nr_reduces = 1, sort = False) res = list(result_iterator(job.wait(), reader = result_reader)) if res != [ANS]: raise Exception("Invalid answer: %s" % res) job.purge() print "ok"
def fun_map(e, params): return [({"PI": math.pi}, time.strptime(e, "%d/%m/%Y"))] def fun_reduce(iter, out, params): for k, v in iter: out.add({"PI2": k["PI"]}, datetime.datetime(*v[0:6])) tserver.run_server(data_gen) inputs = ["01/11/1965", "14/03/1983", "12/12/2002"] job = Disco(sys.argv[1]).new_job(name = "test_objectrw", input = tserver.makeurl(inputs), map = fun_map, map_writer = func.object_writer, reduce = fun_reduce, reduce_reader = func.object_reader, reduce_writer = func.object_writer, required_modules = ["math", "datetime", "time"], nr_reduces = 1, sort = False) i = 0 for k, v in result_iterator(job.wait(), reader = func.object_reader): if k["PI2"] != math.pi: raise "Invalid key: %s" % k if v.strftime("%d/%m/%Y") not in inputs: raise "Invalid value: %s" % v i += 1 if i != 30: raise "Wrong number of results, got %d, expected 30" % i
def fun_map(e, params): if type(e) == tuple: return [(e[0] + params["suffix"], int(e[1]) + 1)] else: return [(e + params["suffix"], 0)] def fun_reduce(iter, out, params): for k, v in iter: out.add(k + "-", v) tserver.run_server(data_gen) disco = Disco(sys.argv[1]) results = disco.new_job( name="test_chain_0", input=tserver.makeurl([""] * 100), map=fun_map, reduce=fun_reduce, nr_reduces=4, sort=False, clean=True, params={"suffix": "0"}, ).wait() i = 1 while i < 10: nresults = disco.new_job(
raise "Invalid value for key (%s): "\ "got (%s) expected (%s)" % (k, x, v) x = "reduce:%d" % this_partition() put(x, "value:" + x) out.add("all", "ok") def fun_map2(e, params): x = get(e, params.job) if x != "value:" + e: raise "Invalid value for key %s: %s" % (e, x) return [("good", "")] tserver.run_server(data_gen) inputs = list(string.ascii_lowercase) disco = Disco(sys.argv[1]) job1 = disco.new_job(name = "test_oob1", input = tserver.makeurl(inputs), map = fun_map, reduce = fun_reduce, nr_reduces = 10) res = list(result_iterator(job1.wait())) if [("all", "ok")] * 10 != res: raise "Invalid result: %s" % res keys = ["reduce:%d" % i for i in range(10)] + inputs lst = job1.oob_list() if len(lst) != len(keys):
return 0 def data_gen(path): return "\n".join([path[1:]] * 10) def fun_map(e, params): return [(e, params.f1(int(e), params.x))] def fun_reduce(iter, out, params): for k, v in iter: out.add(k, params.f2(int(v))) tserver.run_server(data_gen) inputs = range(10) job = Disco(sys.argv[1]).new_job(name = "test_params", input = tserver.makeurl(inputs), map = fun_map, params = Params(x = 5, f1 = fun1, f2 = fun2), reduce = fun_reduce, nr_reduces = 1, sort = False) for x, y in result_iterator(job.wait()): if fun2(int(x) + 5) != int(y): raise "Invalid result: %s and %s" % (x, y) job.purge() print "ok"
from disco import Disco from memoriaSwapping import Memoria from memoriaVirtual import MemoriaVirtual import time import threading import sys memoriaVirtual = MemoriaVirtual(5) disco = Disco('arquivo.txt') def controlaTempo(): while (True): if (t2.isAlive()): disco.decrementarTempoRestante() memoriaVirtual.decrementaTempoExecutando() memoriaVirtual.controleTempoBitR() time.sleep(1) else: sys.exit(0) #finalizar programa def controlaRetidadaDisco(): while (True): if (disco.existeProcessoPronto()): dados = disco.retirarMaisUrgente() if (dados == ""): continue else: processosRetirados = memoriaVirtual.organizarProcesso(dados) for processo in processosRetirados:
from libro import Libro from disco import Disco from revista import Revista from librero import Librero from comic import Comic from manga import Manga miLibrero = Librero() miLibrero.agregaLibro(Libro(autor="korth", titulo="bases", editorial="Pearson")) # Disco miLibrero.agregaDisco( Disco(interprete="Ricardo Montaner", titulo="Vuelve Conmigo", album="Ida y Vuelta Edición Especial", anio=2017)) miLibrero.agregaDisco( Disco(interprete="Michael Jackson", titulo="Bllie Jean", album="Thriller", anio=1983)) miLibrero.agregaDisco( Disco(interprete="Zara Larsson", titulo="Lush Life", album="So Good", anio=2017)) miLibrero.agregaDisco( Disco(interprete="Hailee Steinfeld", titulo="Love Myself", album="Haiz",
from coloredlogs import install from disco import Disco if __name__ == '__main__': install(level=20) Disco('Kotori').run()
def data_gen(path): return "\n".join([path[1:]] * 10) def fun_map(e, params): import time, random time.sleep(random.randint(1, 3)) return [(e, 0)] def fun_reduce(iter, out, params): for k, v in iter: out.add("[%s]" % k, v) tserver.run_server(data_gen) disco = Disco(sys.argv[1]) num = sum(x['max_workers'] for x in disco.nodeinfo()['available']) print >> sys.stderr, num, "slots available" inputs = tserver.makeurl(range(num * 10)) random.shuffle(inputs) jobs = [] for i in range(5): jobs.append(disco.new_job(name = "test_async_%d" % i, input = inputs[i * (num * 2):(i + 1) * (num * 2)], map = fun_map, reduce = fun_reduce, nr_reduces = 11, sort = False)) time.sleep(1) all = dict(("[%s]" % i, 0) for i in range(num * 10)) for job in jobs:
def data_gen(path): return "\n".join(ani) def fun_map(e, params): if type(e) == tuple: return [(e[0] + params['suffix'], int(e[1]) + 1)] else: return [(e + params['suffix'], 0)] def fun_reduce(iter, out, params): for k, v in iter: out.add(k + "-", v) tserver.run_server(data_gen) disco = Disco(sys.argv[1]) results = disco.new_job(name = "test_chain_0", input = tserver.makeurl([""] * 100), map = fun_map, reduce = fun_reduce, nr_reduces = 4, sort = False, clean = True, params = {'suffix': '0'}).wait() i = 1 while i < 10: results = disco.new_job(name = "test_chain_%d" % i, input = results, map = fun_map, reduce = fun_reduce, nr_reduces = 4, map_reader = chain_reader, sort = False, clean = True, params = {'suffix': str(i)}).wait() i += 1 for key, value in result_iterator(results): if key[:5] not in ani or key[5:] != "0-1-2-3-4-5-6-7-8-9-":
import tserver, sys, md5, math from disco import Disco, result_iterator def data_gen(path): return path[1:] + "\n" def fun_map(e, params): k = str(int(math.ceil(float(e))) ** 2) return [(md5.new(k).hexdigest(), "")] tserver.run_server(data_gen) disco = Disco(sys.argv[1]) inputs = [1, 485, 3245] job = disco.new_job(name = "test_reqmodules", nr_reduces = 1, input = tserver.makeurl(inputs), map = fun_map, required_modules = ["math", "md5"], sort = False) res = list(result_iterator(job.wait())) if len(res) != len(inputs): raise Exception("Too few results: Got: %d Should be %d" % (len(res), len(inputs))) cor = map(lambda x: md5.new(str(int(math.ceil(x)) ** 2)).hexdigest(), inputs) for k, v in res: if k not in cor:
import tserver, sys, time from disco import Disco def data_gen(path): return "1 2 3\n" def fun_map(e, params): import time time.sleep(100) return [] disco = Disco(sys.argv[1]) num = sum(x['max_workers'] for x in disco.nodeinfo()['available']) print >> sys.stderr, num, "slots available" tserver.run_server(data_gen) job = disco.new_job(name = "test_kill", input = tserver.makeurl([""] * num * 2), map = fun_map) time.sleep(10) print >> sys.stderr, "Killing", job.name job.kill() time.sleep(5) if job.jobinfo()['active'] == "dead": print "ok" job.purge() else: raise Exception("Killing failed")
import coloredlogs from dotenv import load_dotenv load_dotenv() from disco import Disco if __name__ == '__main__': coloredlogs.install(level=20) Disco().run()
balao1 = Balao(objectGroup) balao1.image = balao1.images[1] # balao Carol balao = Balao(objectGroup) # Balao Rodrigo balao2 = Balao(objectGroup) balao2.image = balao2.images[2] # Balao Nasci balao3 = Balao(objectGroup) balao3.image = balao3.images[3] rodrigo = Rodrigo(objectGroup, rodrigoGroup) disco = Disco(DelayGroup) def draw_text(text, font, color, surface, x, y): textobj = font.render(text, 1, color) textrect = textobj.get_rect() textrect.topleft = (x, y) surface.blit(textobj, textrect) menu = True introduction = True click = False gameover_end = False game_end = False