Source code for vitollino.main

#! /usr/bin/env python
# -*- coding: UTF8 -*-
# Este arquivo é parte do programa Vittolino
# Copyright 2011-2017 Carlo Oliveira <carlo@nce.ufrj.br>,
# `Labase <http://labase.selfip.org/>`__, `GPL <http://is.gd/3Udt>`__.
#
# Vittolino é um software livre, você pode redistribuí-lo e/ou
# modificá-lo dentro dos termos da Licença Pública Geral GNU como
# publicada pela Fundação do Software Livre (FSF), na versão 2 da
# Licença.
#
# Este programa é distribuído na esperança de que possa ser útil,
# mas SEM NENHUMA GARANTIA, sem uma garantia implícita de ADEQUAÇÃO
# a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR. Veja a
# Licença Pública Geral GNU para maiores detalhes.
#
# Você deve ter recebido uma cópia da Licença Pública Geral GNU
# junto com este programa, se não, veja em <http://www.gnu.org/licenses/>
"""

Gerador de labirintos e jogos tipo *'novel'*.
=============================================

.. module:: Vitollino
   :platform: Web
   :synopsis: Gerador de labirintos e jogos tipo *'novel'*.

.. moduleauthor:: Carlo Oliveira <carlo@ufrj.br>


Gerador de labirintos e jogos tipo *'novel'*.

.. seealso::

`Vitollino em Github <https://github.com/carlotolla/vitollino>`_

"""
import json
from browser import document, html, timer
from browser import window as win
from browser import ajax
import uuid

try:
   SUPERPYTHON = win.__SUPERPYTHON__
except Exception as _:
   SUPERPYTHON = None

CURSOR_STYLE = 'width: {}px, height: {}px, min-height: {}px, border-radius: 30px,' \
               ' left:{}px, top: {}px, position: absolute'
CURSOR_ELEMENT = 'left={}, top={}, width={}, height={}'
ABOXED = 9398
NOSCORE = dict(ponto=0, valor=0, carta=None, casa=None, move=None)
NOSC = {}
SZ = dict(W=300, H=300)
DOC_PYDIV = document["pydiv"]
ppcss = 'https://codepen.io/imprakash/pen/GgNMXO'
STYLE = {'position': "absolute", 'width': SZ['W'], 'left': 0, 'top': 0}
PSTYLE = {'position': "absolute", 'width': SZ['W'], 'left': 0, 'bottom': 0}
LIMBOSTYLE = {'position': "absolute", 'width': SZ['W'], 'left': 10000, 'bottom': 0, 'background': "white"}
ISTYLE = {'opacity': "inherited", 'height': 30, 'left': 0, 'top': 0, 'background': "white"}
ESTYLE = {'opacity': "inherited", 'width': 30, 'height': "30px", 'min-height': '30px', 'float': 'left',
          'position': 'unset'}
EIMGSTY = {"max-width": "100%", "max-height": "100%", "width": "100%", "height": "100%"}
STYLE["min-height"] = "300px"
IMAGEM = ""
NSTYLE = {'position': "absolute", 'width': "60%", 'left': "20%", 'top': 0, 'margin': "0%",
          "min-height": "20%", "cursor": "n-resize"}
SSTYLE = {'position': "absolute", 'width': "60%", 'left': "20%", 'bottom': 0, 'margin': "0%",
          "min-height": "10%", "cursor": "s-resize"}
LSTYLE = {'position': "absolute", 'width': "10%", 'left': "90%", 'top': "20%", 'margin': "0%",
          "min-height": "60%", "cursor": "e-resize"}
OSTYLE = {'position': "absolute", 'width': "10%", 'left': 0, 'top': "20%", 'margin': "0%",
          "min-height": "60%", "cursor": "w-resize"}
ZSTYLE = {'position': "absolute", 'width': "10%", 'margin': "0%",
          "min-height": "10%", "cursor": "zoom-in"}
PKEYS = ['False', 'None', 'True', ' and ', ' as ', 'assert', 'break', 'class ', 'continue', 'def ',
         'del', 'elif', 'else', 'except', 'finally', 'for ', 'from ', 'global ', 'if ', 'import ',
         ' in ', ' is ', 'lambda', 'nonlocal', ' not ', ' or ', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
NDCT = {}
FIX_COUNT = {}


class _PATTERN:
    NOOP = {k.strip(): v for k, v in (tp.split(":") for tp in """""".replace("\n", "").split(";") if tp)}
    STARRY = {k.strip(): v for k, v in (tp.split(":") for tp in """background-color:black; opacity:0.4;
    background-image:
    radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 40px),
    radial-gradient(white, rgba(255,255,255,.15) 1px, transparent 30px),
    radial-gradient(white, rgba(255,255,255,.1) 2px, transparent 40px),
    radial-gradient(rgba(255,255,255,.4), rgba(255,255,255,.1) 2px, transparent 30px);
    background-size: 550px 550px, 350px 350px, 250px 250px, 150px 150px; 
    background-position: 0 0, 40px 60px, 130px 270px, 70px 100px;""".replace("\n", "").split(";") if tp)}

    NCROSS = {k.strip(): v for k, v in (tp.split(": ") for tp in """opacity: 0.7;
    background: 
    radial-gradient(circle, transparent 20%, slategray 20%, slategray 80%, transparent 80%, transparent),
    radial-gradient(circle, transparent 20%, slategray 20%, slategray 80%, transparent 80%, transparent) 30px 30px,
    linear-gradient(#A8B1BB 8px, transparent 8px) 0 -4px,
    linear-gradient(90deg, #A8B1BB 8px, transparent 8px) -4px 0;
    background-color: slategray;
    background-size: 60px 60px, 60px 60px, 30px 30px, 30px 30px;""".replace("\n", "").split(";") if tp)}

    OCROSS = {k.strip(): v for k, v in (tp.split(": ") for tp in """opacity: 0.7;
    background: 
    radial-gradient(circle, transparent 20%, slategray 20%, slategray 80%, transparent 80%, transparent),
    radial-gradient(circle, transparent 20%, slategray 20%, slategray 80%, transparent 80%, transparent) 50px 50px,
    linear-gradient(#A8B1BB 8px, transparent 8px) 0 -4px,
    linear-gradient(90deg, #A8B1BB 8px, transparent 8px) -4px 0;
    background-color: slategray;
    background-size: 100px 100px, 100px 100px, 50px 50px, 50px 50px;""".replace("\n", "").split(";") if tp)}

    BCROSS = {k.strip(): v for k, v in (tp.split(": ") for tp in """opacity: 0.7;
    background-color: slategray;
    background: 
    radial-gradient(slategray 9px, transparent 10px),        
    repeating-radial-gradient(slategray 0, slategray 4px, transparent 5px, transparent 15px,
    slategray 16px, slategray 20px, transparent 21px, transparent 30px);    
    background-size: 30px 30px, 90px 90px; 
    background-position: 0 0;""".replace("\n", "").split(";") if tp)}

    SHIPPO = {k.strip(): v for k, v in (tp.split(": ") for tp in """opacity: 0.5;background-color: #def;
    background-image: radial-gradient(closest-side, transparent 98%, rgba(0,0,0,.3) 99%),
    radial-gradient(closest-side, transparent 98%, rgba(0,0,0,.3) 99%);
    background-size: 80px 80px;
    background-position: 0 0, 40px 40px;""".replace("\n", "").split(";") if tp)}
    RADGRAD = ", ".join(["rgba({a},{a},{a},{b}) {c}%".format(
        a=200 if c % 2 else 20, b=0.6, c=c * 10) for c in range(0, 11)])

    BOKEH = {k.strip(): v for k, v in (tp.split(": ") for tp in """opacity: 0.5;
    background-size: 60px 60px, 60px 60px, 30px 30px, 30px 30px, 100% 100%;background: 
    radial-gradient({}) 0 0;""".replace("\n", "").format(RADGRAD).split(";") if tp)}


# INVENTARIO = None

from functools import WRAPPER_ASSIGNMENTS


[docs]def parametrized(dec): def layer(*args, **kwargs): def repl(f): return dec(f, *args, **kwargs) return repl return layer
[docs]def wraps_class_to_mimic_wrapped(original_cls): """ Empacota uma classe decoradora para que apareça corretamente nos documentos. .. doctest :: >>> @wraps_class_to_mimic_wrapped ... class Exemplo: ... ... ... >>> print(Exemplo.__doc__) Atualiza wrapper_cls para se assemelhar à classe original_cls. <BLANKLINE> :param original_cls: A Classe a ser empacotada :return: O empacotador da classe """ def wrapper(wrapper_cls): """Atualiza wrapper_cls para se assemelhar à classe original_cls. """ _ = [setattr(wrapper_cls, attr, getattr(original_cls, attr)) for attr in WRAPPER_ASSIGNMENTS if hasattr(original_cls, attr)] return wrapper_cls return wrapper
[docs]def singleton(cls_to_decorate): """ Decora um classe para ser um singleton e retornar sempre a mesma instância. >>> @singleton ... class Mono: ... def __init__(self): ... self.x = 0 ... >>> Mono().x, Mono().x = 1, 2 >>> print(Mono().x == Mono().x, Mono().x) True 2 :param cls_to_decorate: A classe para ser definida como singleton :return: O decorador de singleton """ instance = cls_to_decorate() @wraps_class_to_mimic_wrapped(cls_to_decorate) class Singletoner(cls_to_decorate): def __init__(self): super().__init__() self.wrapped = cls_to_decorate Singletoner.__doc__ = cls_to_decorate.__doc__ Singletoner.__repr__ = cls_to_decorate.__repr__ def __new__(cls, *args, **kwargs): return instance def __call__(self, *args, **kwargs): return instance def __repr__(self): return repr(cls_to_decorate) return Singletoner
[docs]@singleton class NoEv: """ Representa um evento vazio. .. doctest:: >>> print(ev.x, ev.y) -100 -100 """ x = -100 y = -100 def __repr__(self): return "<NoEvent>" def __init__(self): self.x = -100 self.y = -100 def stopPropagation(self): pass
[docs]@singleton class SalaCenaNula: """ Define uma Sala ou uma Cena vazia. .. doctest:: >>> cena = Cena(SalaCenaNula()) # A próxima cena >>> uma_cena = Cena(SalaCenaNula(), cena) # Cena nula à esquerda, proxima no meio >>> uma_cena.vai_esquerda() # tenta navegar para a cena à esquerda >>> # não vai, pois a cena é nula e não deixa que se navegue para ela >>> print(INVENTARIO.cena == cena) True Deve ser usado quando um parâmetro requer uma cena mas não deve ter uma cena válida ali. """ def __init__(self): self.esquerda, self.direita = [None] * 2 self.salas = [None] * 5 self.cenas = [self] * 4 self.img = "_NO_IMG_" self.nome = "_NO_NAME_" self.init = self.init self.centro, self.norte, self.leste, self.sul, self.oeste = self.salas def __repr__(self): return "<CenaNula>" def init(self): self.init = lambda _=0, s=self: self self.esquerda, self.direita = [SalaCenaNula()] * 2 self.salas = [SalaCenaNula()] * 5 self.cenas = [SalaCenaNula()] * 4 self.centro, self.norte, self.leste, self.sul, self.oeste = self.salas return self def vai(self): pass def portal(self, *_, **__): pass
NADA = SalaCenaNula().init() NS = {} NL = []
[docs]class Musica(object): def __init__(self, sound, loop=True, autoplay=True, sound_type="audio/mpeg"): self.sound = html.AUDIO(src=sound, autoplay=autoplay, loop=loop, type=sound_type) document.body <= self.sound
[docs]class Inventario: """ Os objetos que estão de posse do jogador. :param tela: Div do HTML onde o inventário será anexado """ """# Usado para definir um jogador no modo multiusuário""" GID = str(uuid.uuid4())[:8] # Usado para definir um jogador no modo multiusuário def __init__(self, tela=DOC_PYDIV): self.tela = tela self.cena = None self.nome = "__INVENTARIO__" self.inventario = {} self.item = {} self.opacity = 0 self.style = dict(**ISTYLE) self.style["min-height"] = "30px" self.elt = html.DIV(Id="__inv__", style=self.style) self.elt.onclick = self.mostra self.limbo = html.DIV(style=self.style) self.limbo.style.left = "4000px" self.mostra() tela <= self.elt def __repr__(self): return "Inventario" def __le__(self, other): if hasattr(other, 'elt'): self.elt <= other.elt else: self.elt <= other
[docs] def inicia(self): self.elt.html = "" self.inventario = {} self.cena = None self.opacity = 0 self.mostra()
[docs] def desmonta(self, _=0): self.limbo <= self.elt
[docs] def monta(self, _=0): self.tela <= self.elt
[docs] def mostra(self, _=0): self.opacity = abs(self.opacity - 0.5) self.elt.style.opacity = self.opacity
[docs] def bota(self, nome_item, item="", drag=False, acao=None): """ Os objetos que estão de posse do jogador. .. doctest:: >>> inv.bota("uma_coisa") >>> "uma_coisa" in inv.inventario True :param nome_item: uma string com o nome do item, ele será criado e colocado no inventário :param item: URL da imagem do item nomeado por nome_item :param drag: Se for True o objeto será arrastável :param acao: ação associada com o item nomeado quando ele é clicado """ if isinstance(nome_item, str): #item_img = html.IMG(Id=nome_item, src=item, width=30, height="30px", style=ESTYLE) nome_item = Elemento(item, tit=nome_item, w=30, height=30, drag=drag, style=ESTYLE) nome_item.entra(self) item_img = nome_item.elt item_img.style = ESTYLE nome = nome_item.tit or nome_item self.item[nome] = nome_item # Dropper(item_img) if acao: item_img.onclick = lambda *_: acao() else: acao = lambda *_: None self.inventario[nome_item] = acao
[docs] def tira(self, nome_item): item_img = document[nome_item] self.limbo <= item_img result = self.item.pop(nome_item) if nome_item in self.item else self.inventario.pop(nome_item, None) return result
[docs] def score(self, casa, carta, move, ponto, valor, _level=1): data = dict(doc_id=INVENTARIO.GID, carta=carta, casa=casa, move=move, ponto=ponto, valor=valor, _level=_level, tempo=win.Date.now()) SUPERPYTHON.scorer(data) if SUPERPYTHON else None
# print('store', data)
[docs] @staticmethod def send(operation, data, action=lambda t: None, method="POST"): def on_complete(request): if int(request.status) == 200 or request.status == 0: # print("req = ajax()== 200", request.text) action(request.text) else: print("error " + request.text) req = ajax() req.bind('complete', on_complete) # req.on_complete = on_complete url = "/record/" + operation req.open(method, url, True) # req.set_header('content-type', 'application/x-www-form-urlencoded') req.set_header("Content-Type", "application/json; charset=utf-8") print("def send", data) data = json.dumps(data) req.send(data)
INVENTARIO = Inventario()
[docs]class Elemento_: """ Um objeto de interação que é representado por uma imagem em uma cena. papel = Elemento( img="papel.png", tit="caderno de notas", vai=pega_papel, style=dict(left=350, top=550, width=60)) :param img: URL de uma imagem :param vai: função executada quando se clica no objeto :param style: dicionário com dimensões do objeto {"left": ..., "top": ..., width: ..., height: ...} :param tit: Texto que aparece quando se passa o mouse sobre o objeto :param alt: Texto para leitores de tela :param cena: cena alternativa onde o objeto vai ser colocado :param score: determina o score para este elemento :param kwargs: lista de parametros nome=URL que geram elementos com este nome e a dada imagem """ limbo = html.DIV(style=LSTYLE) def __init__(self, img="", vai=None, style=NS, tit="", alt="", cena=INVENTARIO, score=NOSC, drag=False, drop='', **kwargs): self._auto_score = self.score if score else self._auto_score self.img = img self.vai = vai if vai else lambda _=0: None self.cena = cena self.nome = tit self.opacity = 0 self.style = dict(**PSTYLE) # self.style["min-width"], self.style["min-height"] = w, h self.style.update(**style) self.elt = html.DIV(Id=tit, style=self.style) self.xy = (-111, -111) self.scorer = dict(ponto=1, valor=cena.nome, carta=tit or img, casa=self.xy, move=None) self.scorer.update(score) if img: self.img = html.IMG(src=img, title=tit, alt=alt, style=EIMGSTY) # width=self.style["width"]) self.elt <= self.img self.elt.onclick = self._click self.c(**kwargs) # _ = Dragger(self.elt) if drag else None # _ = Droppable(self.elt, drop, self.vai) if drop else None _ = self.entra(cena) if cena and (cena != INVENTARIO) else None def _auto_score(self, **kwargs): pass def __le__(self, other): if hasattr(other, 'elt'): self.elt <= other.elt else: self.elt <= other def _click(self, ev=NoEv()): self.xy = (ev.x, ev.y) ev.stopPropagation() return self.vai(ev)
[docs] def entra(self, cena, style=NOSC): styler = dict(self.style) styler.update(style) self.elt.style = styler self.cena = cena self.scorer.update(valor=cena.nome, move=self.xy, casa=(styler["left"], styler["top"] if "top" in styler else 0)) self._auto_score(**self.scorer) cena <= self
[docs] def score(self, **kwargs): score = {key: kwargs[key] if key in kwargs else value for key, value in self.scorer.items()} INVENTARIO.score(**score)
[docs] @classmethod def c(cls, **kwargs): return [setattr(cls, nome, Elemento(**img) if isinstance(img, dict) else Elemento(img=img)) for nome, img in kwargs.items()]
[docs]class Elemento(Elemento_): """ Um objeto de interação que é representado por uma imagem em uma cena. papel = Elemento( img="papel.png", tit="caderno de notas", vai=pega_papel, style=dict(left=350, top=550, width=60)) :param img: URL de uma imagem :param vai: função executada quando se clica no objeto :param style: dicionário com dimensões do objeto {"left": ..., "top": ..., width: ..., height: ...} :param tit: Texto que aparece quando se passa o mouse sobre o objeto :param alt: Texto para leitores de tela :param x: Posição x, na horizontal a partir da esquerda do elemento na cena :param y: Posição y, na vertical a partir do topo do elemento na cena :param w: Largura em pixels do elemento na cena :param h: Altura em pixels do elemento na cena :param texto: Se fornecido, este texto vai aparecer quando se clica no elemento :param cena: cena alternativa onde o objeto vai ser colocado :param score: determina o score para este elemento :param drag: Se o valor for True, o o elmento será arrastável, default Faslse :param drop: recebe um dicionário {"a": ator} onde ator é uma função def ator(ev, nome} chamada quando "a" é arrastado cá :param kwargs: lista de parametros nome=URL que geram elementos com este nome e a dada imagem """ _score = None def __init__(self, img="", vai=None, style=NDCT, tit="", alt="", x=0, y=0, w=100, h=100, o=1, texto='', cena=INVENTARIO, score=NDCT, drag=False, drop={}, tipo="100% 100%", **kwargs): self._auto_score = self.score if score else self._auto_score self.img, self.title, self.dropper, self.alt = img, tit, drop, alt self._drag = self._over = self._drop = self._dover = self.vai = lambda *_: None self.cena = cena self.nome = tit self.opacity = 0 self.texto = texto self.vai = Texto(cena, texto, foi=self.foi).vai if texto else vai if vai else self.vai # height = style["height"] if "height" in style else style["maxHeight"] if "maxHeigth" in style else 100 # height = height[:-2] if isinstance(height, str) and "px" in height else height self.style = dict(**PSTYLE) self.style.update(**{'position': 'absolute', 'overflow': 'hidden', 'o': 1, 'left': x, 'top': y, 'width': '{}px'.format(w), 'height': '{}px'.format(h), 'background-image': 'url({})'.format(img), 'background-position': '{} {}'.format(0, 0), #'background-size': '{}px {}px'.format(w, h) 'background-size': tipo, 'background-repeat': 'no-repeat' }) # self.style["min-width"], self.style["min-height"] = w, h self.style.update(**style) self.elt = html.DIV(Id=tit, title=tit, style=self.style) self.xy = (-111, -111) self.scorer = dict(ponto=1, valor=cena.nome, carta=tit or img, casa=self.xy, move=None) self.scorer.update(score) # if False: # self.img = html.IMG(Id="img_" + tit, src=img, title=tit, alt=alt, # style=EIMGSTY) # width=self.style["width"]) # self.elt <= self.img self.elt.onclick = self._click self.c(**kwargs) # _ = Dragger(self.elt) if drag else None # _ = Droppable(self.elt, drop, self.vai) if drop else None _ = self.entra(cena) if cena and (cena != INVENTARIO) else None self.elt.ondragstart = lambda ev: self._drag(ev) self.elt.onmouseover = lambda ev: self._over(ev) self.elt.ondrop = lambda ev: self._drop(ev) self.elt.ondragover = lambda ev: self._dover(ev) # self.img.onmousedown = self.img_prevent self.do_drag(drag) self.do_drop(drop) #Elemento._scorer_()
[docs] def do_score(self, tit): if tit not in FIX_SCORE: FIX_SCORE[tit] = int(Elemento._score.score_.html) + 1 Elemento._score.score_.html = FIX_SCORE[tit]
@classmethod def _scorer_(cls): Elemento._scorer_ = lambda *_ : None Elemento._score = scr = Elemento(SCORE) scr.score_ = html.H2("0") scr.elt <= scr.score_ scr.entra(INVENTARIO)
[docs] def foi(self): self._do_foi()
def _do_foi(self): style = {'opacity': "inherited", 'width': 30, 'height': "30px", 'min-height': '30px', 'float': 'left', 'position': 'unset', 'overflow': 'hidden', 'background-image': 'url({})'.format(self.img), 'background-position': '{} {}'.format(0, 0), 'background-size': '{}px {}px'.format(30, 20), } self.do_drag(False) # Texto(self.cena, "Finally,got my correct name: {}".format(self.tit)).vai() _texto = self.texto if self.tit == self.title else CORRECT.format(self.tit) self.vai = Texto(self.cena, _texto).vai clone_mic = Elemento(self.img, tit=self.title, drag=True, style=style, cena=INVENTARIO) clone_mic.entra(INVENTARIO) self._do_foi = lambda *_: None @property def o(self): return int(self.elt.style.opacity) @o.setter def o(self, value): self.elt.style.opacity = value @property def x(self): return int(self.elt.style.left[:-2]) @x.setter def x(self, value): self.elt.style.left = value @property def y(self): return int(self.elt.style.top[:-2]) @y.setter def y(self, value): self.elt.style.top = value @property def tit(self): return self.elt.title @tit.setter def tit(self, texto): self.elt.title = texto @property def style(self): return self.elt.style @style.setter def style_set(self, texto): self.elt.style = texto @property def drag(self): return self.elt.draggable @drag.setter def drag_set(self, condition): self.do_drag(condition) @property def drop(self): return self.dropper @drop.setter def drop_set(self, texto): self.dropper = texto
[docs] def img_prevent(self, ev): ev.preventDefault() ev.stopPropagation() return False
[docs] def mouse_over(self, ev): # ev.preventDefault() ev.target.style.cursor = "pointer" return False
[docs] def img_drag_start(self, ev): # ev.preventDefault() ev.stopPropagation() return False
[docs] def drag_start(self, ev): # ev.preventDefault() ev.stopPropagation() ev.data['text'] = ev.target.id ev.data.effectAllowed = 'move' return False
[docs] def do_drag(self, drag=True): self.elt.draggable = drag if drag: self._drag = self.drag_start self._over = self.mouse_over else: self._drag = self._over = self.img_prevent
[docs] def do_drop(self, drop=""): if drop: self._drop = self.drop self._dover = self.drag_over else: self._drop = self._dover = self.img_prevent
[docs] def drag_over(self, ev): ev.data.dropEffect = 'move' ev.preventDefault() return False
[docs] def drop(self, ev): ev.preventDefault() ev.stopPropagation() src_id = ev.data['text'] tit = document[src_id].title self.dropper.setdefault(tit, lambda *_: None)(ev, tit)
[docs]class Codigo(Elemento): """ Um objeto de interação que é representado por uma trecho de código em uma cena. exemplo = Codigo( codigo="from anna import main", topo="Importando um módulo", vai=testa_codigo, style=dict(left=350, top=550, width=60)) :param codigo: O código de programa :param vai: função executada quando se clica no objeto :param style: dicionário com dimensões do objeto {"left": ..., "top": ..., width: ..., height: ...} :param topo: Texto que aparece no topo do bloco :param cena: cena onde o objeto vai ser colocado """ def __init__(self, codigo="", topo="", cena=INVENTARIO, img="", vai=None, style=NS): self.img = img self.vai = vai if vai else lambda _=0: None self.cena = cena self.opacity = 0 self.style = dict(**PSTYLE) # self.style["min-width"], self.style["min-height"] = w, h self.style.update(backgroundColor='rgba(210, 220, 220, 0.85)', **style) self.elt = html.DIV(style=self.style) self.xy = (-111, -111) istyle = dict(EIMGSTY) istyle.update(opacity=0.3) if img: self.img = html.IMG(src=img, style=istyle) self.elt <= self.img if topo: self.topo = html.DIV(color="black", style=dict(padding="15px")) self.topo.html = topo self.elt <= self.topo self.elt.onclick = self._click self.scorer = dict(ponto=1, valor=cena.nome, carta=img, casa=self.xy, move=None) self._code = html.CODE(codigo) self._area = html.PRE(self._code, Class="python", style=dict( position='relative', top=0, left=0, backgroundColor='transparent')) self.elt <= self._area codigo = win.hljs.highlight("python", codigo) def rp(cod, keys=PKEYS[:], mark='<span class="hljs-keyword">{}</span>'): key = keys.pop() cod = cod.replace(key, mark.format(key)) return rp(cod, keys, mark) if keys else cod # codigo = rp(codigo) self._code.html = codigo.value _ = self.entra(cena) if cena and (cena != INVENTARIO) else None
[docs]class Portal: N = NSTYLE L = LSTYLE S = SSTYLE O = OSTYLE Z = ZSTYLE PORTAIS = dict(N=NSTYLE, L=LSTYLE, S=SSTYLE, O=OSTYLE, Z=ZSTYLE) def __init__(self, cena=None, debug_=False, **kwargs): self.portal, self.kwargs, self.debug = None, kwargs, debug_ self.style = ZSTYLE if cena: self.cena = cena self.p(**kwargs) def __call__(self, cena): class CenaDecorada(cena): def __init__(self, *args, __portal=self, **kargs): style = ZSTYLE super(CenaDecorada, self).__init__(*args, **kargs) __portal.cena = self [__portal.__setup__(acena, portal, style) for portal, acena in __portal.kwargs.items()] return CenaDecorada def __setup__(self, cena, portal, style=NS): class Portico: def __init__(self, origem, destino, portal_, style_, debug=False): self.origem, self.destino, self.portal_, self.style_ = origem, destino, portal_, style_ self.elt = html.DIV(style=self.style_) self.elt.onclick = self._onclick Droppable(self.elt, cursor="not-allowed") if isinstance(self.origem, Cena): self.origem.elt <= self.elt if debug: Cursor(self.elt, self.origem.elt) setattr(self.origem, portal, self) self._vai = self.do_vai def _onclick(self, *args): return self._vai(*args) def __call__(self, *args, **kwargs): return self._vai(*args, **kwargs) def fecha(self, *_): self._vai = lambda *_: None def abre(self, *_): self._vai = self.do_vai def do_vai(self, ev=NoEv()): print("vai", self.destino.nome) return self.destino.vai(ev) @property def vai(self): return self._vai @vai.setter def vai(self, value): self._vai = value @property def img(self): return self.destino.img """ @property def x(self, value): self.elt.left = value @property def y(self, value): self.elt.top = value @property def w(self, value): self.elt.width = value @property def h(self, value): self.elt.height = value """ def __eq__(self, other): return other == self.destino _ = style.update(**{"min-height": "%dpx" % style["height"]}) if "height" in style else None sty = Portal.PORTAIS.get(portal, ZSTYLE) self.style.update(sty) self.style.update(style) ptc = Portico(self.cena, cena, portal, self.style, debug=self.debug) self.elt = ptc.elt return ptc
[docs] def p(self, **kwargs): style = dict(NS) styl = kwargs.pop("style") if "style" in kwargs else {} style.update(**styl) self.portal = [self.__setup__(cena, portal, style=style) for portal, cena in kwargs.items() if (portal in "NSLO" and cena != NADA)] self.portal = self.portal[0] if self.portal else SalaCenaNula() return self.cena
[docs] def vai(self, *_): self.portal.vai()
ROSA = list("NLSO") CART = [(-1, 0), (0, 1), (1, 0), (0, -1)] # [(i, j) for j, i in CART]
[docs]class Labirinto: def __init__(self, c=NADA, n=NADA, l=NADA, s=NADA, o=NADA): self.salas = [sala for sala in [c, n, l, s, o]] self.centro, self.norte, self.leste, self.sul, self.oeste = self.salas self.lb()
[docs] def lb(self): for indice, sala in enumerate(self.salas[1:]): self.centro.cenas[indice].portal(N=sala.cenas[indice]) if sala else None indice_oposto = (indice + 2) % 4 sala.cenas[indice_oposto].portal(N=self.centro.cenas[indice_oposto]) if sala else None
[docs] @staticmethod def m(cenas): def valid(cns, jj, ii, m, n): return 0 <= jj + m < len(cns) and 0 <= ii + n < len(cns[jj + m]) and cns[jj + m][ii + n] def vizinhos(jj, ii, cns=cenas): return [(kk, cns[jj + m][ii + n]) for kk, (m, n) in enumerate(CART) if valid(cns, jj, ii, m, n)] for j, linha in enumerate(cenas): if isinstance(linha, list): for i, centro in enumerate(linha): if not isinstance(centro, Sala): continue for k, sala in vizinhos(j, i): if not isinstance(sala, Sala): continue centro.cenas[k].meio = sala.cenas[k] indice_oposto = (k + 2) % 4 sala.cenas[indice_oposto].meio = centro.cenas[indice_oposto]
[docs] @staticmethod def n(cenas): def valid(cns, jj, ii, m, n): return 0 <= jj + m < len(cns) and 0 <= ii + n < len(cns[jj + m]) and cns[jj + m][ii + n] def vizinhos(jj, ii, cns=cenas): return [(kk, cns[jj + m][ii + n]) for kk, (m, n) in enumerate(CART) if valid(cns, jj, ii, m, n)] # return [(kk, cns[jj + m][ii + n]) for kk, (m, n) in enumerate(CART) # if 0 <= jj + m < len(cns) and 0 <= ii + n < len(cns[jj+m])and cns[jj + m][ii + n]] for j, linha in enumerate(cenas): if isinstance(linha, list): for i, centro in enumerate(linha): if not isinstance(centro, Sala): continue for k, sala in vizinhos(j, i): if not isinstance(sala, Sala): continue centro.cenas[k].portal(**{"N": sala.cenas[k]}) indice_oposto = (k + 2) % 4 sala.cenas[indice_oposto].portal(**{"N": centro.cenas[indice_oposto]})
[docs]class Sala: def __init__(self, n=NADA, l=NADA, s=NADA, o=NADA, nome='', **kwargs): self.cenas = [Cena(img) if isinstance(img, str) else img for img in [n, l, s, o]] self.nome = nome Sala.c(**kwargs) self.p() @property def norte(self): return self.cenas[0] @property def leste(self): return self.cenas[1] @property def sul(self): return self.cenas[2] @property def oeste(self): return self.cenas[3]
[docs] def p(self): for esquerda in range(4): cena_a_direita = (esquerda + 1) % 4 self.cenas[esquerda].direita = self.cenas[cena_a_direita] self.cenas[cena_a_direita].esquerda = self.cenas[esquerda]
[docs] @staticmethod def c(**cenas): for nome, cena in cenas.items(): setattr(Sala, nome, Sala(nome=nome, **cena))
[docs]class Salao(Sala):
[docs] def p(self): # [cena.sai(saida) for cena, saida in zip(self.cenas, saidasnlso)] for esquerda in range(4): cena_a_direita = (esquerda + 1) % 4 self.cenas[esquerda].portal(L=self.cenas[cena_a_direita]) self.cenas[cena_a_direita].portal(O=self.cenas[esquerda])
[docs] @staticmethod def c(**cenas): for nome, cena in cenas.items(): setattr(Salao, nome, Salao(nome=nome, **cena))
[docs]class Cena: """ Use para construir uma cena. :: from _spy.vitollino import Cena cena_esq = Cena(img="esq.jpg") cena_mei = Cena(img="mei.jpg", cena_esq) cena_mei.vai() :param str img: URL da imagem :param Cena esquerda: Cena que está à esquerda desta :param Cena direita: Cena que está à direita desta :param Cena meio: Cena que está à frente desta :param vai: Função a ser chamada no lugar da self.vai nativa """ def __init__(self, img=IMAGEM, esquerda=NADA, direita=NADA, meio=NADA, vai=None, nome='', xy=(0, 0), score=NOSC, **kwargs): width = STYLE["width"] self.scorer = dict(ponto=1, valor="__JOGO__", carta=nome, casa=xy, move=None) self.scorer.update(score) self._auto_score = self.score if score else self._auto_score self.ev = NoEv() self.xy = xy self.img = img self.nome = nome self.dentro = [] self.esquerda, self.direita, self.meio = esquerda or NADA, direita or NADA, meio or NADA self.N, self.O, self.L = [NADA] * 3 self.vai = vai or self.vai self.elt = html.DIV(style=STYLE) self.img = html.IMG(src=self.img, width=width, style=STYLE, title=nome) self.elt <= self.img Cena.c(**kwargs) self._cria_divs(width) def _cria_divs(self, width): self.divesq = divesq = html.DIV(style=STYLE) divesq.style.opacity = 0 divesq.style.width = width // 3 # 100 Droppable(divesq, cursor="not-allowed") divesq.onclick = self.vai_esquerda self.divmeio = divmeio = html.DIV(style=STYLE) divmeio.style.opacity = 0 divmeio.style.width = width // 3 # 100 divmeio.onclick = self.vai_meio Droppable(divmeio, cursor="not-allowed") divmeio.style.left = width // 3 # 100 self.divdir = divdir = html.DIV(style=STYLE) divdir.style.opacity = 0 divdir.style.width = width // 3 # 100 divdir.onclick = self.vai_direita Droppable(divdir, cursor="not-allowed") divdir.style.left = width * 2 // 3 # 100 self.elt <= self.divesq self.elt <= self.divmeio self.elt <= self.divdir def __call__(self): return self.vai() def __le__(self, other): if hasattr(other, 'elt'): self.elt <= other.elt else: self.elt <= other print(other)
[docs] def portal(self, esquerda=None, direita=None, meio=None, **kwargs): self.esquerda, self.direita, self.meio = esquerda or self.esquerda, direita or self.direita, meio or self.meio return Portal(self, **kwargs)
[docs] @staticmethod def c(**cenas): for nome, imagem in cenas.items(): imagem, kwargs = (imagem, {}) if isinstance(imagem, str) \ else (imagem["img"], (imagem.pop("img") and 0) or imagem) setattr(Cena, nome, Cena(imagem, nome=nome, **kwargs))
[docs] @staticmethod def q(n=NADA, l=NADA, s=NADA, o=NADA, nome="", **kwargs): return Sala(n, l, s, o, nome=nome, **kwargs)
[docs] @staticmethod def s(n=NADA, l=NADA, s=NADA, o=NADA, nome="", **kwargs): return Salao(n, l, s, o, nome=nome, **kwargs)
[docs] def vai_direita(self, _=0): if self.direita: self.direita.vai()
[docs] def vai_esquerda(self, _=0): if self.esquerda: self.esquerda.vai()
[docs] def vai_meio(self, _=0): if self.meio: self.meio.vai()
[docs] def sai(self, saida): self.meio = saida
[docs] def bota(self, nome_item): if isinstance(nome_item, str): item_img = html.IMG(Id=nome_item, src=nome_item, width=30, style=EIMGSTY) self.elt <= item_img else: nome_item.entra(self) self.dentro.append(nome_item)
# self <= item
[docs] def tira(self, item): self.dentro.pop(item)
[docs] def vai(self, ev=NoEv()): self.ev = ev INVENTARIO.cena = self INVENTARIO.desmonta() tela = DOC_PYDIV tela.html = "" tela <= self.elt INVENTARIO.monta() INVENTARIO.cena = self self._auto_score(move=(ev.x, ev.y)) return self
def _auto_score(self, **kwargs): pass
[docs] def score(self, **kwargs): score = {key: kwargs[key] if key in kwargs else value for key, value in self.scorer.items()} INVENTARIO.score(**score)
[docs]class Texto(Popup): def __init__(self, cena=NADA, tit="", txt="", foi=None, **kwargs): super().__init__(None, tit=tit, txt=txt, vai=None, **kwargs) self.cena = cena self.kwargs = kwargs self.esconde = foi if foi else self.esconde @property def foi(self): return self.esconde @foi.setter def foi(self, value): self.esconde = value
[docs] def esconde(self, ev=NoEv()): pass
[docs] def mostra(self, tit="", txt="", act=None, **kwargs): kwargs = kwargs if kwargs else self.kwargs act = act if act else lambda *_: None self.elt = Popup.POP.popup self.cena.elt <= self.elt Popup.POP.esconde = self.esconde Popup.POP.mostra(act, tit=tit, txt=txt, **kwargs)
[docs] def vai(self, ev=NoEv()): ev.stopPropagation() self.cena.elt <= Popup.POP.popup self.mostra(self.tit, self.txt, act=self.esconde) return False
[docs] @staticmethod def texto(tit="", txt="", **kwars): def _texto(class_): def decorate(*args, **kwargs): def decorate_vai(*_): class_instance.texto.vai() class_instance = class_(*args, **kwargs) decorated_vai, class_instance.portal.vai = class_instance.portal.vai, decorate_vai class_instance.texto = Texto(class_instance.cena, tit=tit, txt=txt, **kwars) class_instance.texto.esconde = lambda *_: decorated_vai() return class_instance return decorate return _texto
[docs]class Point(list): def __init__(self, x, y): super().__init__([x, y]) self.x, self.y = x, y self.__iadd__, self.__isub__ = self.__radd__, self.__rsub__ def __sub__(self, other): return Point(self.x - other.x, self.y - other.y) def __add__(self, other): return Point(self.x + other.x, self.y + other.y) def __radd__(self, other): print("__radd__(self, {other})".format(other=other)) self.x += other.x self.y += other.y return self def __rsub__(self, other): self.x -= other.x self.y -= other.y return self
[docs] def px(self): return ["{}px".format(ordin) for ordin in (self.x, self.y)]
def __iter__(self): return (ordin for ordin in (self.x, self.y)) def __setitem__(self, key, value): if key: self.y = value else: self.x = value
[docs]class Cursor: def __init__(self, alvo, cena=DOC_PYDIV): self.alvo, self.cena, self.ponto = alvo, cena, None outer = self class Noop: def __init__(self, outerer=self): self.outer = outerer def change(self, ev): pass @staticmethod def update_style(styler, new_style, delta=None): cur_style = dict(outer.style) point = Point(outer.alvo.style.left, outer.alvo.style.top) delta = delta if delta else Point(outer.alvo.style.width, outer.alvo.style.minHeight) print("delta.x, delta.y", outer.elt.style.left, outer.elt.style.top, delta.x, delta.y) cur_style.update(cursor=styler, left=point.x, top=point.y, width=delta.x, height=delta.y, **new_style) cur_style["min-height"] = "{}px".format(delta.y) return cur_style def next(self, ev): ev.target.style = self.update_style("move", _PATTERN.BCROSS) outer.current = outer.move def mouse_over(self, ev): ev.target.style.cursor = "default" def mouse_down(self, ev): outer.ponto = Point(ev.x, ev.y) outer.cursor = outer.current pass def mouse_move(self, ev): pass def mouse_up(self, _): outer.cursor = outer.noop st = self.outer.elt.style width_, height_, left_, top_ = st.width, st.minHeight, st.left, st.top self.outer.elt.title = CURSOR_ELEMENT.format(left_, top_, width_, height_) class Move(Noop): def mouse_move(self, ev): delta = Point(int(alvo.style.left.rstrip("px")), int(alvo.style.top.rstrip("px"))) \ + Point(ev.x, ev.y) - outer.ponto alvo.style.left, alvo.style.top = delta outer.elt.left, outer.elt.top = delta outer.ponto = Point(ev.x, ev.y) def mouse_over(self, ev): ev.target.style.cursor = "move" def next(self, ev): print("next resize") ev.target.style = self.update_style("grab", _PATTERN.BOKEH) outer.current = outer.resize class Resize(Noop): def mouse_move(self, ev): delta = Point(int(outer.elt.style.width.rstrip("px")), int(outer.elt.style.minHeight.rstrip("px"))) \ + Point(ev.x, ev.y) - outer.ponto outer.elt.style.width, outer.elt.style.minHeight = delta.px() alvo.style.width, alvo.style.minHeight = delta.px() outer.elt.style.height = alvo.style.height = delta.px()[1] # alvo.style = self.update_style("default", {}, delta) # outer.elt.style = self.update_style("default", PATTERN.BOKEH, delta) # print("mouse_move", alvo.style.minHeight, delta) outer.ponto = Point(ev.x, ev.y) def mouse_over(self, ev): ev.target.style.cursor = "grab" def next(self, ev): print("next noop") ev.target.style = self.update_style("default", _PATTERN.STARRY) outer.current = outer.noop def next_state(ev): # self.state.append(self.state.pop(0)) self.current.next(ev) def _mouse_down(ev): return self.cursor.mouse_down(ev) def _mouse_up(ev): return self.cursor.mouse_up(ev) def _mouse_move(ev): return self.cursor.mouse_move(ev) def _mouse_over(ev): return self.cursor.mouse_over(ev) def _strip_kind(dm): kinds = "px %".split() kind = [k for k in kinds if isinstance(dm, str) and (k in dm)] # dm = str(dm) if isinstance(dm, int) else dm if isinstance(dm, str) else "0" return int(dm.rstrip(kind[0])) if kind else int(dm) if dm else 0 self.noop, self.move, self.resize = self.state = [Noop(), Move(), Resize()] self.cursor = self.noop self.current = self.move style = dict(**ISTYLE) dims = [self.alvo.style.top, self.alvo.style.minHeight, self.alvo.style.left, self.alvo.style.width] print("dim left, top = ", dims) dims = [_strip_kind(dm) for dm in dims] top, height, left, width = dims # left, top = left + width//2 - 30, top + height//2 - 30 cstyle = CURSOR_STYLE cstyle = cstyle.format(width, height, height, left, top) print("cstyle = ", cstyle) cstyle = {k.strip(): v for k, v in (tp.split(":") for tp in cstyle.replace("\n", "").split(", ") if tp)} style.update(**cstyle) style.update(**_PATTERN.STARRY) self.style = style self.elt = html.DIV(Id="__cursor__", style=style, title="") self.cena <= self.elt self.elt.onclick = next_state self.elt.onmousedown = _mouse_down self.elt.onmouseup = _mouse_up self.elt.onmousemove = _mouse_move self.elt.onmouseover = _mouse_over
[docs]class Dragger: POINTER = "" ACTION = "" def __init__(self, dragger): self._mouse_over = self.pre_mouse_over self._mouse_down = self.pre_mouse_down self._mouse_up = self.pre_mouse_up self._mouse_move = self.pre_mouse_move def drag_start(ev): self.drag_start(ev) def mouse_over(ev): self._mouse_over(ev) def mouse_down(ev): self._mouse_down(ev) def mouse_move(ev): self._mouse_move(ev) def mouse_up(ev): self._mouse_up(ev) self.dragger = dragger dragger.draggable = True dragger.ondragstart = drag_start dragger.onmouseover = mouse_over dragger.onmousedown = mouse_down dragger.onmousemove = mouse_move dragger.onmouseup = mouse_up
[docs] def widen(self, dx): self.dragger.w = self.dragger.w + dx
[docs] def highten(self, dy): self.dragger.h = self.dragger.h + dy
[docs] @staticmethod def pre_mouse_over(ev): ev.target.style.cursor = "grab"
[docs] @staticmethod def mouse_over(ev): obj = ev.target dx, dy, x, y = obj.w, obj.h, ev.x - obj.offsetLeft, ev.y - obj.offsetTop quadrante = dy // y * 3 + dx // x ev.target.style.cursor = Dragger.POINTER[quadrante]
[docs] def drag_start(self, ev): ev.data['text'] = ev.target.id ev.data.effectAllowed = 'move' ev.preventDefault() return False
[docs] def mouse_down(self, ev): ev.target.style.cursor = "move" self._mouse_move = self.pre_mouse_move
[docs] def pre_mouse_down(self, ev): ev.target.style.cursor = "move" self._mouse_move = self.pre_mouse_move pass
[docs] def pre_mouse_up(self, _): self._mouse_over = self.mouse_over self._mouse_move = self.no_mouse_move self._mouse_down = self.mouse_down pass
def _mouse_up_(self, _): self._mouse_over = self.mouse_over self._mouse_down = self.mouse_down self._mouse_up = self.mouse_up
[docs] def mouse_up(self, _): self._mouse_over = self.pre_mouse_over self._mouse_down = self.pre_mouse_down self._mouse_up = self.pre_mouse_up pass
[docs] def no_mouse_move(self, ev): pass
[docs] def pre_mouse_move(self, ev): obj = ev.target dx, dy, x, y = obj.w, obj.h, ev.x - obj.offsetLeft, ev.y - obj.offsetTop self.dragger.x = ev.x - x self.dragger.y = ev.y - y pass
[docs]class Dropper: def __init__(self, dropper): dropper.draggable = True dropper.ondragstart = self.drag_start dropper.onmouseover = self.mouse_over
[docs] def mouse_over(self, ev): ev.target.style.cursor = "pointer"
[docs] def drag_start(self, ev): ev.data['text'] = ev.target.id ev.data.effectAllowed = 'move' ev.preventDefault() return False
[docs]class Droppable: def __init__(self, droppable, dropper_name="", action=None, cursor=None): # droppable.ondragover = self.drag_over # droppable.ondrop = self.drop droppable.bind("dragover", self.drag_over) droppable.bind("drop", self.drop) self.dropper_name = dropper_name self.cursor = cursor self.action = action if action else lambda *arg: None
[docs] def drag_over(self, ev): ev.data.dropEffect = 'move' # print('drop', ev.target.id) src_id = ev.data['text'] elt = document[src_id] elt.style.cursor = self.cursor or "auto" ev.preventDefault() return False
[docs] def drop(self, ev): ev.preventDefault() src_id = ev.data['text'] elt = document[src_id] elt.style.cursor = "auto" if self.dropper_name == src_id: self.action(elt, self) return False
[docs]class Folha: def __init__(self, texto, ht_ml, tela, left): style = {'position': "absolute", 'width': 80, 'height': 80, 'left': left, 'top': 10, 'background': "yellow"} fid = "folha%d" % left self.folha = ht_ml.DIV(texto, Id=fid, style=style, draggable=True) tela <= self.folha self.folha.ondragstart = self.drag_start self.folha.onmouseover = self.mouse_over
[docs] def mouse_over(self, ev): ev.target.style.cursor = "pointer"
[docs] def drag_start(self, ev): ev.data['text'] = ev.target.id ev.data.effectAllowed = 'move'
[docs]class Suporte: def __init__(self, bloco, ht_ml, tela, left, certa): style = {'position': "absolute", 'width': 80, 'height': 80, 'left': left, 'top': 100, 'background': "grey"} self.folha = ht_ml.DIV("............ ............", style=style) self.left = left self.certa = certa tela <= self.folha self.folha.ondragover = self.drag_over self.folha.ondrop = self.drop self.bloco = bloco
[docs] def drag_over(self, ev): ev.data.dropEffect = 'move' ev.preventDefault()
[docs] def drop(self, ev): ev.preventDefault() src_id = ev.data['text'] elt = document[src_id] elt.style.left = self.left elt.style.top = 100 elt.draggable = False # don't drag any more elt.style.cursor = "auto" certa = True if src_id != self.certa: elt.style.background = "red" certa = False self.bloco.conta_peça(certa)
[docs]class Bloco: def __init__(self): self.monta = lambda *_: None ordem = "10 410 310 210 110".split() texto = "" \ "Era uma vez|" \ "de nós três|" \ "por cima|" \ "deu um salto|" \ "um gato pedrêz|" \ "".split("|") tela = document["pydiv"] tela.html = "" self.pecas_colocadas = [] print(list(enumerate(ordem))) for pos, fl in enumerate(ordem): Suporte(self, html, tela, pos * 100 + 10, "folha" + fl) for pos, tx in enumerate(texto): Folha(tx, html, tela, pos * 100 + 10)
[docs] def inicia_de_novo(self): pass
[docs] def conta_pecas(self, valor_peca): self.pecas_colocadas += valor_peca if len(self.pecas_colocadas) == 4: if all(self.pecas_colocadas): input("O texto está certo.") else: vai = input("Tentar de novo?") if vai == "s": self.inicia_de_novo()
[docs] def nao_monta(self): pass
[docs] def vai(self): self.monta() self.monta = self.nao_monta
# self.centro.norte.vai()
[docs]class Jogo: def __init__(self): self.c = Cena self.d = self.codigo = Codigo self.q = Sala self.salao = self.s = Salao self.a = Elemento self.texto = self.t = Popup self.n = Texto self.labirinto = self.l = Labirinto self.inventario = self.i = INVENTARIO self.portal = self.p = Portal self.dropper = self.d = Dropper self.droppable = self.r = Droppable self.musica = self.m = Musica self.codigo = Codigo self.document = document self.html = html self.window = win self.timer = timer pass @property def cena(self): """ Acessa a classe Cena""" return Cena @property def quarto(self): """ Acessa a classe Sala""" return Sala @property def sala(self): """ Acessa a classe Salao""" return Salao @property def algo(self): """ Acessa a classe Elemento""" return Elemento @property def nota(self): """ Acessa a classe Texto""" return Texto
JOGO = Jogo()
[docs]def main(): # Bloco() # CenaPrincipal() return Bloco()
if "__main__" in __name__: print("runnin tests") import doctest doctest.testmod(globs=dict( inv=Inventario(), ev= NoEv(), Cena= Cena, SalaCenaNula= SalaCenaNula, INVENTARIO=INVENTARIO, wraps_class_to_mimic_wrapped=wraps_class_to_mimic_wrapped, singleton=singleton )) # main() CSS = ''' h1 { text-align: center; font-family: Tahoma, Arial, sans-serif; color: #06D85F; margin: 80px 0; } .box { width: 40%; margin: 0 auto; background: rgba(255,255,255,0.2); padding: 35px; border: 2px solid #fff; border-radius: 20px/50px; background-clip: padding-box; text-align: center; } .button { position: absolute; font-size: 1em; padding: 10px; color: #fff; border: 2px solid #FFF3; border-radius: 100px; text-decoration: none; cursor: pointer; transition: all 0.3s ease-out; left: 45%; top: 25%; } .button:hover { background: #777; } .overlay { position: absolute; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.7); transition: opacity 300ms; } .overlay:target { visibility: visible; opacity: 0.8; } .popup { top: 20%; margin: 70px auto; padding: 15px; background: #fff; border-radius: 10px; width: 85%; position: relative; transition: all 5s ease-in-out; } .popup h2 { margin-top: 0; color: #333; font-family: Tahoma, Arial, sans-serif; } .popup .close { position: absolute; top: 0px; right: 5px; transition: all 200ms; font-size: 30px; font-weight: bold; text-decoration: none; color: #333; } .popup .option { transition: all 200ms; font-size: 30px; font-weight: bold; text-decoration: none; color: #333; } .popup .close:hover { color: #06D85F; } .popup .option:hover { color: #06D85F; } .popup .content { max-height: 30%; overflow: auto; } ''' def __setup__(): document.head <= html.STYLE(CSS, type="text/css", media="screen") Popup(Cena()) __setup__()