Beispiel #1
0
class Game(Screen):
    joystick_x = GAME.get("joystick", {}).get("x", 0.8)
    joystick_y = GAME.get("joystick", {}).get("y", 0.2)
    joystick_size = GAME.get("joystick", {}).get("size", 150)

    is_colliding = kp.BooleanProperty(False)

    # turn:
    last_magnitude = kp.NumericProperty(0)
    is_turn = kp.BooleanProperty(False)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def update(self, dt):
        # print("update", self.joystick.angle)
        self.player.update(dt)

        delta_magnitude = self.joystick.magnitude - self.last_magnitude
        if abs(delta_magnitude) == 1:
            self.is_turn = 1
        else:
            self.is_turn = 0
        self.last_magnitude = self.joystick.magnitude
        # print("delta_magnitude", delta_magnitude)

        signal = -1 if abs(self.joystick.angle) > 90 else 1

        if self.is_turn:
            self.player.x += signal * self.player.agility / 5
        else:
            delta = self.player.agility * self.joystick.magnitude * dt
            self.player.x += signal * delta

        # Borders:
        self.player.right = min(self.player.right, Window.width)
        self.player.x = max(self.player.x, 0)

        # update cars:
        self.car.y -= self.player.speed * dt
        if self.car.top <= 0:
            self.car.y = Window.height
            self.car.center_x = random.randint(0, Window.width)

        # collisions:
        if self.player.collide_widget(self.car):
            if not self.is_colliding:
                print("collide")
                self.is_colliding = True
                self.player.hull -= self.player.speed / 50
                if self.player.hull <= 0:
                    print("GAME OVER")
                    self.player.new()
                    self.car.y = Window.height
                self.player.speed *= 0.5
        else:
            self.is_colliding = False
class TwitterConfig(Screen):

    colorInter = Properties.ListProperty([1, 1, 1, 1])
    activeInter = Properties.BooleanProperty(False)
    halign = Properties.StringProperty('left')

    def __init__(self, **kwargs):
        super(TwitterConfig, self).__init__(**kwargs)
        self.pos_hint = {'center_y': 0.5, 'center_x': 0.5}

    def changeHalign(self, halign):
        self.halign = halign

    def saveConfig(self):
        #guardar las configs
        print(self.activeInter)
        dbWrapper.saveTwitter(self.activeInter, self.colorInter, self.halign)

    def pressedBack(self, widget):
        anim = Animation(pos_hint={"center_x": .5, "y": -.03}, duration=.1)
        anim += Animation(pos_hint={"center_x": .5, "y": 0}, duration=.1)
        anim.bind(on_complete=partial(self.goToMenuScreen))
        anim.start(widget)

    def goToMenuScreen(self, widget, selected):
        self.saveConfig()
        App.get_running_app().root.transition = FadeTransition(duration=.3)
        App.get_running_app().root.current = "menu"
class ScatterColoredLabel(Scatter):
    background_color = Properties.ListProperty((0, 0, 0, 1))
    visible = Properties.BooleanProperty()
    saveOnDBEvent = Properties.ObjectProperty()
    noteId = Properties.NumericProperty()
    text = Properties.StringProperty()

    def on_pos(self, instance, value):
        try:
            self.saveOnDBEvent.cancel()
        except:
            logging.info('Notes: No previous event')
        self.saveOnDBEvent = Clock.schedule_once(self.saveOnDB, 5)

    def saveOnDB(self, dt):
        noteToSave = Notes(
            _id=self.noteId,
            pinned=self.visible,
            text=self.text,
            posX=self.pos[0],
            posY=self.pos[1],
            scale=self.scale,
            rotation=self.rotation,
            rgb=[
                self.background_color[0]*255,
                self.background_color[1]*255,
                self.background_color[2]*255,
                self.background_color[3],
            ],

        )
        noteToSave.save()

        logging.info('DB: Updated note with id: ' + str(self.noteId))
Beispiel #4
0
class InfoDayConfig(Screen):
    colorHora = Properties.ListProperty([1, 1, 1, 1])
    formatoHora = Properties.ListProperty(["24h", False])

    colorFecha = Properties.ListProperty([1, 1, 1, 1])
    formatoFecha = Properties.StringProperty("dd/mm")

    colorTemp = Properties.ListProperty([1, 1, 1, 1])
    formatoTemp = Properties.StringProperty("metric")

    formatoClima = Properties.NumericProperty(2)

    c_id = Properties.StringProperty('6361046')
    activeInter = Properties.BooleanProperty(True)

    colorInter = Properties.ListProperty([1, 1, 1, 1])

    def __init__(self, **kwargs):
        super(InfoDayConfig, self).__init__(**kwargs)
        self.pos_hint = {'center_y': 0.5, 'center_x': 0.5}
        self.getAllInter()

    def saveConfig(self):
        #guardar las configs
        if self.ids.textinput.text == "":
            self.c_id = self.ids.textinput.hint_text
        else:
            self.c_id = self.ids.textinput.text
        dbWrapper.saveHora("hora", self.formatoHora, self.colorHora)
        dbWrapper.saveFecha("fecha", self.formatoFecha, self.colorFecha)
        dbWrapper.saveTemp("temp", self.formatoTemp, self.colorTemp, self.c_id)
        dbWrapper.saveClima("weather", self.formatoClima, self.c_id)
        dbWrapper.saveInfoState(self.activeInter)
        dbWrapper.saveInternationalConfig("inter", self.colorInter)

    def getAllInter(self):
        datos = dbWrapper.getAllInterByMonth(str(strftime('%m')))

        for j in datos:
            layout = BoxLayout(orientation='horizontal',
                               size_hint_y=None,
                               height=20,
                               padding=[-40, 0, 0, 0])
            layout.add_widget(Texto(text=str(j.dia)))
            layout.add_widget(
                Texto(text=str(j.info if len(j.info) < 25 else '...' +
                               j.info[10:35] + '...')))
            self.ids.todos.add_widget(layout)

    def pressedBack(self, widget):
        anim = Animation(pos_hint={"center_x": .5, "y": -.03}, duration=.1)
        anim += Animation(pos_hint={"center_x": .5, "y": 0}, duration=.1)
        anim.bind(on_complete=partial(self.goToMenuScreen))
        anim.start(widget)

    def goToMenuScreen(self, widget, selected):
        self.saveConfig()
        App.get_running_app().root.transition = FadeTransition(duration=.3)
        App.get_running_app().root.current = "menu"
Beispiel #5
0
class Keybind(Button):
    """
    Stores keybindings and manages actually sending them out of
    TabletKeyApp and to the next window.
    """
    bound_keys = kp.ListProperty([])
    tab_back = kp.BooleanProperty(False)
    position = kp.ListProperty([0, 0])

    def output(self) -> dict:
        """

        :return: A dictionary containing the vital binding properties
            of the Keybind so that they can be saved.
        """
        return dict(
            position=self.pos,
            binding='+'.join(self.bound_keys),
            tab_back=self.tab_back
        )

    def setup(self, name: str, binding: str, position: (list, tuple) = None,
              tab_back: bool = False) -> None:
        """
        Sets a Keybind button up, or overwrites the existing properties
        if used on an existing Keybind object.

        :param name: A string, the user-supplied name of the keybinding
            to display on the button.
        :param binding: A string with each keyboard key separated by a
            plus (+) sign.
        :param position: A list or tuple, currently mostly a
            placeholder for when user-specified Keybind button
            placement is implemented.
        :param tab_back: A boolean, indicates whether, when this
            Keybind is pressed, the user wants to immediately tab back
            to the TabletKeyApp window.
        :return: None
        """
        self.bound_keys = binding.split('+')
        self.tab_back = tab_back
        self.position = position if position is not None else [0, 0]
        self.text = name

    def send(self) -> None:
        """
        Uses pyautogui to send the contents of the Keybind to the next
        window.

        :return: None
        """
        pg.hotkey('alt', 'tab')
        # A slight delay is necessary to successfully input the
        # keystroke into the other window.
        time.sleep(0.1)
        pg.hotkey(*self.bound_keys)
        if self.tab_back:
            time.sleep(0.1)
            pg.hotkey('alt', 'tab')
Beispiel #6
0
class HoverBehavior(object):

    hovered = prop.BooleanProperty(False)
    hover_on_children = prop.BooleanProperty(False)
    border_point = prop.ObjectProperty(None)
    """border_point contains the last relevant point received by the Hoverable.
    This can be used in on_enter or on_leave in order to know where was
    dispatched the event.
    """

    def __init__(self, **kwargs):
        self.register_event_type('on_enter')
        self.register_event_type('on_leave')
        window.Window.bind(mouse_pos=self.on_mouse_pos)
        super(HoverBehavior, self).__init__(**kwargs)

    def on_mouse_pos(self, *args):
        if not self.get_root_window():
            return # do proceed if I'm not displayed <=> If have no parent
        pos = args[1]
        # Next line to_widget allow to compensate for relative layout
        inside = self.collide_point(*self.to_widget(*pos))
        if self.hover_on_children:
            for w in self.children: #w in self.walk(restrict=True):
                inside |= w.collide_point(*w.to_widget(*pos))
        if self.hovered == inside:
            # We have already done what was needed
            return
        self.border_point = pos
        self.hovered = inside
        if inside:
            self.dispatch('on_enter')
        else:
            self.dispatch('on_leave')

    def activate_hover(self):
        window.Window.bind(mouse_pos=self.on_mouse_pos)

    def deactivate_hover(self):
        window.Window.unbind(mouse_pos=self.on_mouse_pos)

    def on_enter(self):
        pass

    def on_leave(self):
        pass
Beispiel #7
0
class AbstractMenuItemHoverable(object):
    hovered = kp.BooleanProperty(False)

    def _on_hovered(self, new_hovered):
        if new_hovered:
            spacer_height = self.parent.spacer.height if self.parent.spacer else 0
            self.show_submenu(self.width, self.height + spacer_height)
        else:
            self.hide_submenu()
Beispiel #8
0
class Sprite(Image):
    vel = kp.ObjectProperty(Vector(0, 0))
    acc = kp.ObjectProperty(Vector(0, 0))
    touch_the_ground = kp.BooleanProperty(True)
    last_moving = kp.StringProperty("right")
    have_the_key = kp.BooleanProperty(False)

    def __init__(self, game, source, **kwargs):
        super().__init__()
        self.source = source
        self.game = game
        self.width = kwargs.get("width", self.game.tile_size)
        self.height = kwargs.get("height", self.game.tile_size)
        self.x = kwargs.get("x", 0)
        self.y = kwargs.get("y", 0)
        index = kwargs.get("index", 1)
        self.game.add_widget(self, index=index)
        self._pos = Vector(*self.pos)
Beispiel #9
0
class MenuItem(widget.Widget):
    '''Background color, in the format (r, g, b, a).'''
    background_color_normal = prop.ListProperty([0.2, 0.2, 0.2, 1])
    background_color_down = prop.ListProperty([0.3, 0.3, 0.3, 1])
    background_color = prop.ListProperty([])
    separator_color = prop.ListProperty([0.8, 0.8, 0.8, 1])
    text_color_hovered = prop.ListProperty([1, 1, 1, 1])
    text_color_unhovered = prop.ListProperty([.7, .7, .7, 1])
    inside_group = prop.BooleanProperty(False)
    pass
Beispiel #10
0
class SmithyBox(BoxLayout):
    research = kp.BooleanProperty(False)

    def __init__(self, **kwargs):
        self.orientation = "vertical"
        super().__init__(**kwargs)
        Clock.schedule_once(self.update, 0)

    def update(self, *args):
        font_size = Window.width / 40
        self.remove_all_widgets()
        self.app = App.get_running_app()
        for building_name, building_level in self.unit.requirements.get(
                "UNLOCK"):
            building = getattr(self.app, building_name)
            if building.level < building_level:
                text = "Requirements:\n"
                for building_name, building_level in self.unit.requirements.get(
                        "UNLOCK"):
                    text += "%s (%s)\n" % (building_name, building_level)
                building.bind(level=self.update)
                label = DarkLabel(text=text, font_size=font_size)
                self.add_widget(label)
                break
        else:  # no break
            if self.research or "RESEARCH" not in self.unit.requirements:
                text = "Researched"
                label = DarkLabel(text=text, font_size=font_size)
                self.add_widget(label)
                self.image.source = "atlas://img/unit_big/unit_big/%s" % self.unit.name
            else:
                self.image.source = "atlas://img/unit_big/unit_big/%s_grey" % self.unit.name
                self.wood = self.unit.requirements.get("RESEARCH").get("WOOD")
                self.clay = self.unit.requirements.get("RESEARCH").get("CLAY")
                self.iron = self.unit.requirements.get("RESEARCH").get("IRON")
                text = "%s %s %s" % (self.wood, self.clay, self.iron)
                label = DarkLabel(text=text, font_size=font_size)
                self.add_widget(label)
                button = Button(text="Research")
                self.add_widget(button)
                button.bind(on_press=self.start_research)

    def start_research(self, *args):
        if self.wood < self.app.wood.current and self.clay < self.app.clay.current\
                and self.iron < self.app.iron.current:
            self.app.wood.current -= self.wood
            self.app.clay.current -= self.clay
            self.app.iron.current -= self.iron
            self.research = True
            self.update()

    def remove_all_widgets(self):
        for widget in self.children.copy():
            self.remove_widget(widget)
Beispiel #11
0
class GameApp(App):
    step_size = kp.NumericProperty(Window.height / N_OF_STEPS)
    debug = kp.BooleanProperty(DEBUG)

    def build(self):
        game = Game()
        game.frog = Player()
        game.new()
        game.add_widget(game.frog)
        Clock.schedule_interval(game.update, 1.0 / FPS)
        return game
class ColoredLabelConfig(GridLayout):
    editing = Properties.BooleanProperty(False)
    noteid = Properties.NumericProperty()
    pinned = Properties.BooleanProperty()
    bcolor = Properties.ListProperty((0, 0, 0, 1))
    texto = Properties.StringProperty()

    def pinNote(self, noteId, pinned):
        ColoredLabel.visible = pinned != True
        self.pinned = pinned != True
        note = dbWrapper.findNoteById(noteId)
        note.pinned = pinned != True
        note.save()

    def on_editing(self, instance, value):
        if (value == False):
            nuevoTexto = self.ids.textValue.text
            noteToUpdate = Notes(_id=self.noteid, pinned=self.pinned, rgb=[
                                 self.bcolor[0]*255, self.bcolor[1]*255, self.bcolor[2]*255, 1], text=nuevoTexto)
            noteToUpdate.save()

    def deleteNote(self):
        dbWrapper.deleteNoteById(self.noteid)
class GifConfig(ButtonBehavior, AsyncImage):
    imagenId = Properties.NumericProperty()
    pinned = Properties.BooleanProperty()
    delay = Properties.NumericProperty()

    def pinGif(self):

        self.pinned = not self.pinned

        gif = dbWrapper.findGifById(self.imagenId)
        gif.pinned = self.pinned
        gif.posX = 10
        gif.posY = 10
        gif.save()
class DraggableColoredLabel(DragBehavior, Label):
    background_color = Properties.ListProperty((0, 0, 0, 1))
    visible = Properties.BooleanProperty()
    saveOnDBEvent = Properties.ObjectProperty()
    noteId = Properties.NumericProperty()

    def on_pos(self, instance, value):
        try:
            self.bringToFront()
            self.saveOnDBEvent.cancel()
        except:
            logging.info('Notes: No previous event')

        self.saveOnDBEvent = Clock.schedule_once(self.saveOnDB, 5)

    def bringToFront(self):
        parent = self.parent
        children = parent.children
        childOnTop = children[0]

        if (self != childOnTop):
            parent.remove_widget(self)
            parent.add_widget(self)

    def saveOnDB(self, dt):
        noteToSave = Notes(
            _id=self.noteId,
            pinned=self.visible,
            text=self.text,
            posX=self.pos[0],
            posY=self.pos[1],
            sizeX=self.size_hint[0],
            sizeY=self.size_hint[1],
            rgb=[
                self.background_color[0]*255,
                self.background_color[1]*255,
                self.background_color[2]*255,
                self.background_color[3],
            ],

        )
        noteToSave.save()

        logging.info('DB: Updated note with id: ' + str(self.noteId))
Beispiel #15
0
class InternationalConfig(Screen):
    colorInter = Properties.ListProperty([1, 1, 1, 1])
    activeInter = Properties.BooleanProperty(True)

    def __init__(self, **kwargs):
        super(InternationalConfig, self).__init__(**kwargs)
        self.pos_hint = {'center_y': 0.5, 'center_x': 0.5}
        self.getAllInter()

    def printt(self, switch):
        print(switch.active)

    def saveConfig(self):
        # guardar las configs
        dbWrapper.saveInternationalConfig(
            "inter",
            self.colorInter if self.activeInter == False else [1, 1, 1, 0])

    def getAllInter(self):
        datos = dbWrapper.getAllInterByMonth(str(strftime('%m')))

        for j in datos:
            layout = BoxLayout(orientation='horizontal',
                               size_hint_y=None,
                               height=20,
                               padding=[-40, 0, 0, 0])
            layout.add_widget(Texto(text=str(j.dia)))
            layout.add_widget(
                Texto(text=str(j.info if len(j.info) < 25 else '...' +
                               j.info[10:35] + '...')))
            self.ids.todos.add_widget(layout)

    def pressedBack(self, widget):
        anim = Animation(pos_hint={"center_x": .5, "y": -.03}, duration=.1)
        anim += Animation(pos_hint={"center_x": .5, "y": 0}, duration=.1)
        anim.bind(on_complete=partial(self.goToMenuScreen))
        anim.start(widget)

    def goToMenuScreen(self, widget, selected):
        self.saveConfig()
        App.get_running_app().root.transition = FadeTransition(duration=.3)
        App.get_running_app().root.current = "menu"
class GifConfig2(BoxLayout):
    imagenId = Properties.NumericProperty()
    pinned = Properties.BooleanProperty()
    delay = Properties.NumericProperty()
    updateListFunction = Properties.ObjectProperty()
    source = Properties.StringProperty()

    def pinGif(self):

        self.pinned = not self.pinned

        gif = dbWrapper.findGifById(self.imagenId)
        gif.pinned = self.pinned
        gif.posX = 10
        gif.posY = 10
        gif.save()

    def deleteGif(self):
        dbWrapper.deleteGifById(self.imagenId)
        self.updateListFunction()
Beispiel #17
0
class ClockWidget(Image):
    text = Properties.StringProperty('')
    chosenColor = Properties.ListProperty()
    segundos = Properties.BooleanProperty()
    horas = Properties.StringProperty()

    def on_text(self, *_):
        # Just get large texture:z
        l = Label(text=self.text)
        l.font_size = '1000dp'  # something that'll give texture bigger than phone's screen size
        l.color = self.color
        l.texture_update()
        # Set it to image, it'll be scaled to image size automatically:
        self.texture = l.texture

    def __init__(self, **kwargs):
        super(ClockWidget, self).__init__(**kwargs)
        currentHora = getHora()
        self.chosenColor = currentHora.color
        self.segundos = currentHora.formato[1]
        self.horas = currentHora.formato[0]
        self.color = self.chosenColor
        self.text = datetime.now().strftime(
            self.update_secondsAndFormat(self.segundos, self.horas))
        Clock.schedule_interval(self.update_time, 1)

    def update_time(self, *args):
        self.text = datetime.now().strftime(
            self.update_secondsAndFormat(self.segundos, self.horas))
        self.color = self.chosenColor

    def update_secondsAndFormat(self, seconds, formato):
        if (seconds == True and formato == "24h"):
            return '%H:%M:%S'
        elif (seconds == True and formato == "12h"):
            return '%I:%M:%S %p'
        elif (seconds == False and formato == "24h"):
            return '%H:%M'
        else:
            return '%I:%M %p'
Beispiel #18
0
class Joystick(RelativeLayout):
    sticky = kp.BooleanProperty(False)  # When False, the joystick will snap back to center on_touch_up.
    angle = kp.NumericProperty()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.magnitude = 0

    # def on_touch_down(self, *args):
    #     # print("on_touch_down", args)

    def on_touch_move(self, *args):
        # print("on_touch_down", args)
        touch = args[0]
        # print(touch.pos, self.center)
        # self.stick.center = touch.pos

        center2touch = Vector(*touch.pos) - Vector(*self.center)
        # print("center2touch", center2touch)
        dist = center2touch.length()
        # print("dist", dist)
        self.angle = -Vector(1, 0).angle(center2touch)
        # print("angle", self.angle)
        pos2center = Vector(*self.center) - Vector(*self.pos)
        if dist > self.max_dist:
            dist = self.max_dist
            center2touch = center2touch.normalize() * self.max_dist
        self.stick.center = center2touch + pos2center
        self.magnitude = dist / self.max_dist

        # print("magnitude: %s" % (self.magnitude))

    
    def on_touch_up(self, *args):
        # print("on_touch_up", args)
        if self.sticky:
            return
        self.stick.center = self.width / 2, self.height / 2
        self.magnitude = 0
Beispiel #19
0
class MenuBar(box.BoxLayout):

    '''Background color, in the format (r, g, b, a).'''
    background_color = prop.ListProperty([0.2, 0.2, 0.2, 1])
    separator_color = prop.ListProperty([0.8, 0.8, 0.8, 1])
    selected = prop.BooleanProperty(False)

    def __init__(self, **kwargs):
        self.itemsList = []
        super(MenuBar, self).__init__(**kwargs)

    def add_widget(self, item, index=0):
        if not isinstance(item, MenuItem):
            raise TypeError("MenuBar accepts only MenuItem widgets")
        super(MenuBar, self).add_widget(item, index)
        if index == 0:
            index = len(self.itemsList)
        self.itemsList.insert(index, item)

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos) == False:
            self.selected = False
        else:
            self.selected = True
        super(MenuBar, self).on_touch_down(touch)

    def on_selected(self, instance, value):
        for w in self.children:
            if isinstance(w, MenuSubmenu):
                if value:
                    w.activate_hover()
                else:
                    w.deactivate_hover()

    def close_all_menus(self):
        for ch in self.children:
            if isinstance(ch, MenuSubmenu):
                ch.close()
Beispiel #20
0
class MapWidget(Widget):
    draw_color = properties.ListProperty([0, 0, 0])
    background = properties.ListProperty([1, 1, 1])
    point_color = properties.ListProperty([0, 0, 0])
    point_size = properties.ListProperty([10, 10])
    draw_from_text_file = properties.BooleanProperty(False)
    dragging_map = properties.BooleanProperty(False)
    translation = properties.ListProperty([0, 0])
    translation_last_point = properties.ListProperty([0, 0])

    # data_file_path = properties.StringProperty()

    def __init__(self, **kwargs):
        working_dir = Path.cwd()
        self.data_file_path = str(Path(str(working_dir) + "/" + DATA_FILE))
        self.objects = []  # Contains all objects that is drawn on the screen
        # Create empty file
        if not Path.exists(Path(self.data_file_path)):
            open(self.data_file_path, "w")
        super(MapWidget, self).__init__(**kwargs)
        self.bind(pos=self.resize, size=self.resize)

    def resize(self, *args):
        self.pos = self.pos
        self.size = self.size
        self.clear_canvas()

        if self.draw_from_text_file:
            self.draw_from_data_file()

    def on_touch_down(self, touch):
        if self.inside_widget(touch, "touch") and self.draw_from_text_file:
            self.dragging_map = True
            self.translation_last_point = [touch.x, touch.y]

    def on_touch_move(self, touch):
        # print("Touch: %f, %f" % (touch.x - self.center_x, touch.y - self.center_y))
        if self.dragging_map:
            self.translation[0] += -(self.translation_last_point[0] - touch.x
                                     )  # - self.center_x
            self.translation[1] += -(self.translation_last_point[1] - touch.y
                                     )  #- self.center_y
            self.translation_last_point = [touch.x, touch.y]
            self.clear_canvas()
            if self.draw_from_text_file:
                self.draw_from_data_file()

    def on_touch_up(self, touch):
        if self.inside_widget(touch, "touch"):
            if self.dragging_map:
                self.dragging_map = False
                self.translation[0] += -(self.translation_last_point[0] -
                                         touch.x)
                self.translation[1] += -(self.translation_last_point[1] -
                                         touch.y)

    def clear_canvas(self):
        for obj in self.objects:
            self.canvas.remove(obj)

        self.objects.clear()
        if not self.dragging_map:
            self.draw_from_text_file = False

    def inside_widget(self, touch, type):
        bottom_left_x = self.center_x - self.width / 2
        bottom_left_y = self.center_y - self.height / 2
        top_right_x = self.center_x + self.width / 2
        top_right_y = self.center_y + self.height / 2
        if type == "touch":
            x = touch.pos[0]
            y = touch.pos[1]
            return x >= bottom_left_x and x <= top_right_x and y >= bottom_left_y and y <= top_right_y
        elif type == "pos":
            x = touch[0]
            y = touch[1]
            return x >= bottom_left_x and x <= top_right_x and y >= bottom_left_y and y <= top_right_y

    def draw_from_data_file(self):
        if not self.draw_from_text_file:
            self.draw_from_text_file = True

        with open(self.data_file_path, "r") as input_file:
            for line in input_file:
                line = line.rstrip()
                line = line.split(",")
                position = [
                    self.center_x + int(line[0]) + self.translation[0],
                    self.center_y + int(line[1]) + self.translation[1]
                ]

                if self.inside_widget(position, "pos"):
                    self.obj = InstructionGroup()
                    self.obj.add(Color(*self.point_color))
                    self.obj.add(Ellipse(pos=position, size=self.point_size))
                    self.objects.append(self.obj)
                    self.canvas.add(self.obj)
Beispiel #21
0
class Snake(App):
    sprite_size = kp.NumericProperty(SPRITE_SIZE)

    head = kp.ListProperty([0, 0])
    snake = kp.ListProperty()
    length = kp.NumericProperty(LENGTH)

    fruit = kp.ListProperty([0, 0])
    fruit_sprite = kp.ObjectProperty(Fruit)

    direction = kp.StringProperty(RIGHT, options=(LEFT, UP, RIGHT, DOWN))
    buffer_direction = kp.StringProperty(RIGHT, options=(LEFT, UP, RIGHT, DOWN, ''))
    block_input = kp.BooleanProperty(False)

    alpha = kp.NumericProperty(0)

    def on_start(self):
        self.fruit_sprite = Fruit()
        self.fruit = self.new_fruit_location
        self.head = self.new_head_location
        Clock.schedule_interval(self.move, MOVESPEED)
        Window.bind(on_keyboard=self.key_handler)

    def on_fruit(self, *args):
        self.fruit_sprite.coord = self.fruit
        if not self.fruit_sprite.parent:
            self.root.add_widget(self.fruit_sprite)

    def key_handler(self, _, __, key, *____):
        try:
            self.try_change_direction(direction_keys[key])
        except KeyError:
            pass

    def try_change_direction(self, new_direction):
        if direction_group[new_direction] != direction_group[self.direction]:
            if self.block_input:
                self.buffer_direction = new_direction
            else:
                self.direction = new_direction
                self.block_input = True

    def on_head(self, *args):
        self.snake = self.snake[-self.length:]+[self.head]

    def on_snake(self, *args):
        for index, coord in enumerate(self.snake):
            sprite = SPRITES[index]
            sprite.coord = coord
            if not sprite.parent:
                self.root.add_widget(sprite)

    @property
    def new_head_location(self):
        return [randint(2, dim - 2)for dim in[COLS, ROWS]]

    @property
    def new_fruit_location(self):
        while True:
            fruit = [randint(2, dim)for dim in[COLS, ROWS]]
            if fruit not in self.snake and fruit != self.fruit:
                return fruit

    def move(self, *args):
        self.block_input = False
        new_head = [sum(x) for x in zip(self.head, direction_values[self.direction])]
        if not self.check_in_bounds(new_head) or new_head in self.snake:
            return self.die()
        if new_head == self.fruit:
            self.length += 1
            self.fruit = self.new_fruit_location
        if self.buffer_direction:
            self.try_change_direction(self.buffer_direction)
            self.buffer_direction = ''
        self.head = new_head

    def check_in_bounds(self, pos):
        return all(0 <= pos[x] < dim for x, dim in enumerate([COLS, ROWS]))

    def die(self):
        self.root.clear_widgets()
        self.alpha = ALPHA
        Animation(alpha=0, duration=MOVESPEED).start(self)

        self.snake.clear()
        self.length = LENGTH
        self.fruit = self.new_fruit_location
        self.head = self.new_head_location
Beispiel #22
0
class GlobalContainer(box.BoxLayout):

    graph_list = prop.ListProperty([])
    active_graph = prop.ObjectProperty(None)
    name_manager = NameManager.Instance()
    show_sidepanel = prop.BooleanProperty(True)
    modestr = prop.StringProperty('insert')
    itemstr = prop.StringProperty('atom')

    modes = {'insert': asp.Mode.INSERT, 'select': asp.Mode.SELECT}
    items = {
        'atom': asp.Item.ATOM,
        'ellipse': asp.Item.ELLIPSE,
        'rectangle': asp.Item.SQUARE
    }

    def __init__(self, **kwargs):
        super(GlobalContainer, self).__init__(**kwargs)
        self._keyboard = None
        self.request_keyboard()
        self.working_dir = './'
        self.tutorial = None
        self.popup_stack = []
        window.Window.bind(on_resize=self.on_resize)

        if DEBUG:
            self.tracker = ClassTracker()
            self.tracker.track_object(MenuButton)
            self.all_objects = muppy.get_objects()

    def request_keyboard(self):
        self._keyboard = window.Window.request_keyboard(
            self._keyboard_release, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_catch(self):
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_release(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        #self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 'escape':
            base.stopTouchApp()
        elif keycode[1] == 'd':
            self.set_mode('insert')
        elif keycode[1] == 's':
            self.set_mode('select')
        elif keycode[1] == 'w':
            self.set_item('atom')
        elif keycode[1] == 'e':
            self.set_item('ellipse')
        elif keycode[1] == 'r':
            self.set_item('rectangle')
        elif keycode[1] == 'p':
            self.active_graph.show_tree(0)
        elif keycode[1] == 'o':
            self.view_symbolic_formula()
        elif keycode[1] == 'n':
            self.show_gringo_query()
        elif keycode[1] == 'g':
            self.show_save()
        elif keycode[1] == 'l':
            self.show_load()
        elif keycode[1] == 'y':
            print self.name_manager.get_all()
            print asp.Line.get_all_lines()
        elif keycode[1] == 't':
            self.toggle_sidepanel()
        elif keycode[1] == 'tab':
            if not self.show_sidepanel:
                self.toggle_sidepanel()
            self.ids.atom_input.focus = True
        elif keycode[1] == '.':
            if DEBUG:
                rb = refbrowser.InteractiveBrowser(self)
                rb.main()

                # self.all_objects = muppy.get_objects()
                # sum1 = summary.summarize(self.all_objects)
                # summary.print_(sum1)

                # self.tracker.create_snapshot()
                # self.tracker.stats.print_summary()
        return True

    def _focus_name_list(self, value):
        if value and (asp.AtomWidget.active_atom is not None):
            previous_name = asp.AtomWidget.active_atom.name
            for button in self.ids.name_list.children:
                if (button.text == previous_name) and (button.state != 'down'):
                    button.trigger_action()
        elif value:
            if self.ids.name_list.children:
                self.ids.name_list.children[-1].trigger_action()
        else:
            for button in self.ids.name_list.children:
                if button.state == 'down':
                    button.trigger_action()

    def on_resize(self, window, width, height):
        if self.show_sidepanel:
            self.ids.sidepanel.width = self.width * .15
        self.active_graph.size = self.ids.stencilview.size

    def toggle_sidepanel(self):
        self.show_sidepanel = not self.show_sidepanel
        if self.show_sidepanel:
            width = self.width * .15
        else:
            width = 0
        anim.Animation(width=width, d=.15,
                       t='out_quart').start(self.ids.sidepanel)
        if not self.show_sidepanel:
            self.ids.sidepanel.focus = False
            # Also release keyboard
        #self.update_sourcecode()

    def update_atom_editor(self, name):
        editor = self.ids.atom_editor
        if name == '':
            editor.disabled = True
        else:
            if editor.disabled:
                editor.disabled = False
            atom = self.name_manager.get(name)
            editor.update(atom)

    def update_atom(self,
                    name,
                    new_name='',
                    new_hook_points=[],
                    is_constant=False):
        atom = self.name_manager.get(name)
        if new_name <> '':
            atom.name = new_name
        if len(new_hook_points) == 4:
            atom.hook_points = new_hook_points
            # print id(atom.hook_points)
        atom.is_constant = is_constant

    def register_atom(self,
                      name,
                      hooks=[False, False, False, False],
                      is_constant=False):
        if name == '':
            return
        children = self.ids.name_list.children
        new_button = None
        name_to_insert = name
        i = len(children) - 1

        # If the name doesn't exist, register atom
        if self.name_manager.get(name) is None:
            self.name_manager.register(name, asp.Atom(name, hooks,
                                                      is_constant))
            # print id(self.name_manager.get(name).hook_points)

        # Insert in name_list sorted by name
        while i >= 0:
            if children[i].text < name_to_insert:
                #print children[i].text, '<',  name_to_insert
                pass
            elif children[i].text == name_to_insert:
                # Already exists
                if children[i].state != 'down':
                    children[i].trigger_action()
                return
            elif children[i].text > name_to_insert:
                #print children[i].text, '>',  name_to_insert
                temp = children[i].text
                children[i].text = name_to_insert
                name_to_insert = temp
                if new_button == None:
                    new_button = children[i]
            i -= 1

        self.ids.name_list.add_widget(AtomSelectionButton(text=name_to_insert))
        if new_button == None:
            new_button = children[0]
        if new_button.state == 'down':
            asp.AtomWidget.active_atom = self.name_manager.get(name)
            self.update_atom_editor(name)
            self.set_item('atom')
        else:
            new_button.trigger_action()

    def rename_atom(self, new_name):
        old_name = ''
        for button in self.ids.name_list.children:
            if button.state == 'down':
                old_name = button.text
                selected_button = button
        if (old_name != '') and (new_name != ''):
            try:
                atom = self.name_manager.get(old_name)
                exists = self.name_manager.get(new_name)
                assert atom is not None
                assert exists is None
            except AssertionError:
                #self.show_error('Name already exists.')
                print 'Name already exists.'
                return
            selected_button.text = new_name
            atom.name = new_name
            self.name_manager.unregister(old_name)
            self.name_manager.register(new_name, atom)
            self.update_atom_editor(new_name)

    def delete_atom(self):
        for button in self.ids.name_list.children:
            if button.state == 'down':
                self.name_manager.unregister(button.text)
                self.active_graph.delete_atom(button.text)
                asp.AtomWidget.active_atom = None
                self.ids.name_list.remove_widget(button)
                self.update_atom_editor('')

    def clear_atoms(self):
        self.ids.name_list.clear_widgets()
        self.name_manager.clear()
        self.update_atom_editor('')
        asp.AtomWidget.active_atom = None

    def new_graph(self):
        # TODO: Migrate to tab system
        asp.Line.clear_lines()
        self.clear_atoms()
        if self.active_graph is None:
            g = asp.RootWidget()
            self.graph_list.append(g)
            self.active_graph = g
            self.ids.stencilview.add_widget(g)
        else:
            self.active_graph.delete_tree()

    def close_graph(self):
        if self.active_graph is not None:
            asp.Line.clear_lines()
            self.active_graph.delete_tree()
            self.active_graph.delete_root()
            self.clear_atoms()
            self.graph_list.pop()
            self.active_graph = None

    def set_mode(self, mode):
        try:
            prev_mode = self.active_graph.mode
            new_mode = self.modes[mode]
            if new_mode == asp.Mode.INSERT:
                self.active_graph.show_hooks()
            else:
                if prev_mode == asp.Mode.INSERT:
                    self.active_graph.hide_hooks()
            self.active_graph.mode = new_mode
            self.modestr = mode
        except KeyError as err:
            print 'ERROR: Invalid mode {0} requested.'.format(str(err))

    def set_item(self, item):
        try:
            self.active_graph.item = self.items[item]
            self.itemstr = item
        except KeyError as err:
            print 'ERROR: Invalid item {0} requested.'.format(str(err))
        except AttributeError:
            pass
        if item == 'atom':
            self._focus_name_list(True)
        else:
            self._focus_name_list(False)

    def push_popup(self, popup):
        self.popup_stack.append(popup)
        popup.open()

    def dismiss_popup(self):
        popup = self.popup_stack.pop()
        popup.dismiss()

    def show_rename_atom(self):
        content = TextInputDialog(caption="Enter new name",
                                  validate_callback=self.rename_atom,
                                  cancel=self.dismiss_popup)
        p = CustomPopup(self,
                        title="Rename atom",
                        content=content,
                        size_hint=(0.4, 0.25))
        self.push_popup(p)

    def show_load(self):
        content = LoadDialog(load=self.load, cancel=self.dismiss_popup)
        content.ids.filechooser.path = self.working_dir
        p = CustomPopup(self,
                        title="Load file",
                        content=content,
                        size_hint=(0.9, 0.9))
        self.push_popup(p)

    def show_save(self):
        content = SaveDialog(save=self.save, cancel=self.dismiss_popup)
        content.ids.filechooser.path = self.working_dir
        p = CustomPopup(self,
                        title="Save file",
                        content=content,
                        size_hint=(0.9, 0.9))
        self.push_popup(p)

    def show_export(self):
        content = ExportDialog(export=self.export, cancel=self.dismiss_popup)
        content.ids.filechooser.path = self.working_dir
        p = CustomPopup(self,
                        title="Export file",
                        content=content,
                        size_hint=(0.9, 0.9))
        self.push_popup(p)

    def show_gringo_query(self):
        caption = "Enter desired predicates separated by commas"
        content = TextInputDialog(caption=caption,
                                  validate_callback=self.gringo_query,
                                  dismiss_on_validate=False,
                                  focus=False,
                                  cancel=self.dismiss_popup)
        p = CustomPopup(self,
                        title="Output predicates",
                        content=content,
                        size_hint=(0.4, 0.25))
        self.push_popup(p)

    def show_stable_models(self, solver):
        models = solver.get_models()
        content = None
        if len(models) == 0:
            content = ErrorDialog('Unsatisfiable', cancel=self.dismiss_popup)
        else:
            solver.generate_graph(models[0])
            content = StableModelDialog(solver, cancel=self.dismiss_popup)
            content.ids.img.reload()
        p = CustomPopup(self,
                        catch_keyboard=False,
                        title="Stable Models",
                        content=content,
                        size_hint=(0.9, 0.9))
        self.push_popup(p)

    def show_error(self, err_str):
        content = ErrorDialog(err_str, cancel=self.dismiss_popup)
        p = CustomPopup(self,
                        catch_keyboard=False,
                        title="Error",
                        content=content,
                        size_hint=(0.4, 0.3))
        self.push_popup(p)

    def show_about(self):
        content = AboutDialog(cancel=self.dismiss_popup)
        p = CustomPopup(self,
                        catch_keyboard=False,
                        title="About " + __title__,
                        content=content,
                        size_hint=(0.5, 0.5))
        self.push_popup(p)

    def load(self, path, filename):
        self.close_graph()
        self.working_dir = path

        try:
            f = os.path.join(path, filename[0])
            # Temporal line storage. Its contents are arranged as follows:
            # { line_id: (graph, hook_list) , ... }
            lines = {}
            with open(f, 'r') as stream:
                for line in stream:
                    if line.startswith(NameParser.TOKENS['name']):
                        name, hooks, is_constant = NameParser.parse_name(line)
                        self.register_atom(name, hooks, is_constant)
                    if line.startswith(NameParser.TOKENS['line']):
                        line_id, graph = NameParser.parse_line(line)
                        lines[line_id] = (graph, [None] * len(graph))

            new_graph = lang.Builder.load_file(f)
            self.ids.stencilview.add_widget(new_graph)
            self.active_graph = new_graph
            #self.graph_list.pop()
            self.graph_list.append(new_graph)
            for w in self.active_graph.walk(restrict=True):
                if isinstance(w, asp.AtomWidget):
                    w._deferred_init()
                    for i in w.get_line_info():
                        line_id = i[0]
                        hook_index = i[1]
                        lines[line_id][1][hook_index] = i[2]
                elif isinstance(w, asp.NexusWidget):
                    for i in w.line_info:
                        line_id = i[0]
                        hook_index = i[1]
                        lines[line_id][1][hook_index] = w

            for line, info in lines.iteritems():
                print line, info
                asp.Line.build_from_graph(info[0], info[1])

            self.set_mode(self.modestr)
            self.set_item(self.itemstr)
            self.dismiss_popup()
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.dismiss_popup()
            self.close_graph()
            self.new_graph()
            self.show_error('Corrupted file.')

    def save(self, path, filename):
        self.working_dir = path
        with open(os.path.join(path, filename), 'w') as stream:
            stream.write('#:kivy 1.0.9\n\n')
            for (name, atom) in self.name_manager.get_all():
                stream.write(
                    NameParser.get_name_str(name, atom.hook_points,
                                            atom.is_constant))
            for line in asp.Line.get_all_lines():
                stream.write(
                    NameParser.get_line_str(line.line_id,
                                            line.get_full_graph()))
            stream.write('\n')
            stream.write(self.active_graph.get_tree(0))
        self.dismiss_popup()

    def export(self, path, filename):
        _, ext = os.path.splitext(filename)
        if ext == '.png':
            self.active_graph.export_to_png(os.path.join(path, filename))
        elif ext == '.lp':
            rpn = self.active_graph.get_formula_RPN()
            constants = self.active_graph.get_constants()
            solver = eg_solver.Solver()
            solver.set_formula(rpn, constants)
            rules = solver.generate_asp_rules()
            with open(os.path.join(path, filename), 'w') as stream:
                for r in rules:
                    stream.write(r)
                    stream.write('\n')
        else:
            error_str = 'File extension not supported.'
            print error_str
            self.show_error(error_str)
            return
        self.dismiss_popup()

    def highlight_variables(self):
        self.active_graph.highlight_variables()

    def view_symbolic_formula(self):
        print self.active_graph.get_formula()

    def gringo_query(self, show_predicates):
        def generate_show_statements(predicates):
            pred_list = predicates.split(',')
            pred_list = map(lambda s: s.strip(), pred_list)
            n_args = (lambda name: self.name_manager.get(name).hook_points.
                      count(True))
            pred_list = [p + '/' + str(n_args(p)) for p in pred_list]
            show_list = ['#show {0}.'.format(p) for p in pred_list]
            return show_list

        self.dismiss_popup()

        rpn = self.active_graph.get_formula_RPN()
        rpn = norm.LIT.TRUE if rpn == '' else rpn
        constants = self.active_graph.get_constants()
        print 80 * '-'
        print 'RPN formula:\n', rpn

        solver = eg_solver.Solver()
        result = ''
        try:
            show_statements = []
            if show_predicates:
                try:
                    show_statements = generate_show_statements(show_predicates)
                except Exception:
                    pass
            solver.set_formula(rpn, constants)
            result = solver.solve(show=show_statements)
        except norm.MalformedFormulaError:
            self.show_error('Malformed formula.')
            return
        except RuntimeError, e:
            print e
            self.show_error(str(e))
            return
        self.show_stable_models(solver)
Beispiel #23
0
class DataManagement(MDBoxLayout):
    """Object of text fields and buttons for managing data"""

    ## Place holders \/
    app = None ## Main APP reference
    item_data = prop.DictProperty() ## Dict of one row from database
    new_cls = prop.BooleanProperty() ## Bool for new item without parents
    view_only = prop.BooleanProperty() ## Enables/Disables text fields
    delete_dialog = prop.ObjectProperty() ## Delete Dialog popup object
    editing = prop.BooleanProperty(False) ## Enable/Disable editing mode

    def __init__(self,view_only=True,item_data=None,new_cls=False,**kwargs):
        super().__init__(**kwargs)
        self.app = MDApp.get_running_app() ## App object reference
        self.view_only = view_only
        self.item_data = item_data
        self.new_cls = new_cls
        self.set_fields() ## Set text field contents
        self.add_buttons() ## Add buttons to screen
    
    def set_fields(self):
        """Set rules for text fields content"""
        if self.view_only:
            ## populate fields with current database row
            self.populate_fields()
        else:
            ## if not view_only tests for new item 
            if self.new_cls:
                ## if new item, changes label icon and adds 'None' to parent node
                self.ids.label_icon.icon = 'folder-plus-outline'
                self.ids.cls_sub.text = '[ Fundo ]'
                self.app.pcd_tree.disabled = True ## Locks treeview
            else:
                ## if not new item, adds current item code as item parent
                self.ids.cls_sub.text = self.item_data['cls_codigo']

    def add_buttons(self):
        """Add buttons depending on view_only mode"""
        if self.view_only:
            buttons = ViewButtons(edit_code=str(self.item_data['cls_codigo']))
        else:
            buttons = EditButtons()
        self.ids.btn_frame.clear_widgets()
        self.ids.btn_frame.add_widget(buttons)

    def enable_edit(self):
        """Enables editing of text fields"""
        toast(f'Editando {self.item_data["cls_nome"][:40]}{" [...]" if len(self.item_data["cls_nome"]) > 40 else ""}',1)
        self.ids.add_label.text = f'[b]Editando[/b] {self.item_data["cls_nome"]}'
        self.editing = True ## Enables editing
        self.view_only = False ## Disables view_only mode
        self.app.pcd_tree.disabled = True ## Locks treeview
        self.add_buttons() ## Add new buttons

    def populate_fields(self):
        """Populates text fields with current item_data data"""
        self.ids.add_label.text = f'Visualizando [b]{self.item_data["cls_nome"]}[/b]'
        self.ids.cls_nome.text = str(self.item_data['cls_nome'])
        self.ids.cls_codigo.text = str(self.item_data['cls_codigo'])
        self.ids.cls_sub.text = str(self.item_data['cls_sub']) if self.item_data['cls_sub'] != '' else '[ Fundo ]'
        self.ids.reg_abertura.text = str(self.item_data['reg_abertura'])
        self.ids.reg_desativacao.text = str(self.item_data['reg_desativacao'])
        self.ids.reg_reativacao.text = str(self.item_data['reg_reativacao'])
        self.ids.reg_mudanca_nome.text = str(self.item_data['reg_mudanca_nome'])
        self.ids.reg_deslocamento.text = str(self.item_data['reg_deslocamento'])
        self.ids.reg_extincao.text = str(self.item_data['reg_extincao'])
        self.ids.ativa.state = 'down' if self.item_data['cls_indicador'] == 'Ativa' else 'normal'
        self.ids.inativa.state = 'normal' if self.item_data['cls_indicador'] == 'Ativa' else 'down'
        self.ids.fase_corrente.text = str(self.item_data['fase_corrente'])
        self.ids.evento_fase_corrente.text = str(self.item_data['evento_fase_corrente'])
        self.ids.fase_intermediaria.text = str(self.item_data['fase_intermediaria'])
        self.ids.evento_fase_inter.text = str(self.item_data['evento_fase_inter'])
        self.ids.preservacao.state = 'down' if self.item_data['dest_final'] == 'Preservação' else 'normal'
        self.ids.eliminacao.state = 'normal' if self.item_data['dest_final'] == 'Preservação' else 'down'
        self.ids.reg_alteracao.text = str(self.item_data['reg_alteracao'])
        self.ids.observacoes.text = str(self.item_data['observacoes'])

    def show_delete_dialog(self):
        """Create and open delete dialog popup"""
        btn_cancel = MDFlatButton(
            text = 'Cancelar',
            theme_text_color = 'Custom',
            text_color = self.app.theme_cls.primary_color,
            on_release = lambda x: self.delete_dialog.dismiss())
        btn_confirm = MDRaisedButton(
            text = 'Apagar',
            elevation = 11,
            on_release = lambda *x: (self.delete_item_from_db(), self.delete_dialog.dismiss()))

        self.delete_dialog = MDDialog(
            title = 'Deseja realmente apagar?',
            text = f'{self.item_data["cls_nome"]}',
            buttons = [btn_cancel,btn_confirm],
            auto_dismiss = False)
        self.delete_dialog.open()
    
    def delete_item_from_db(self):
        """Try deleting item from database, if successful, deletes item from treeview"""
        try:
            delete_row(self.item_data)
        except lib.utils.ItemHasChildren:
            toast('Classe possui dependentes! Impossível apagar.')
        else:
            toast(f'{self.item_data["cls_nome"][:40]}{" [...]" if len(self.item_data["cls_nome"]) > 40 else ""} apagado com sucesso!',1)
            self.app.root.ids.data_frame.clear_widgets() ## clear data management frame
            self.app.pcd_tree.delete_node_from_tree() ## delete item from treeview
    
    def text_fields_into_dict(self):
        """Gets data from text fields into dict
        :return: dict"""
        data = {
            'parentId': self.item_data['legacyId'] if not self.new_cls else 'zero',
            'cls_nome': self.ids.cls_nome.text.strip(),
            'cls_codigo': self.ids.cls_codigo.text.strip(),
            'cls_sub': self.ids.cls_sub.text.strip() if not self.new_cls else '',
            'reg_abertura': self.ids.reg_abertura.text.strip(),
            'reg_desativacao': self.ids.reg_desativacao.text.strip(),
            'reg_reativacao': self.ids.reg_reativacao.text.strip(),
            'reg_mudanca_nome': self.ids.reg_mudanca_nome.text.strip(),
            'reg_deslocamento': self.ids.reg_deslocamento.text.strip(),
            'reg_extincao': self.ids.reg_extincao.text.strip(),
            'cls_indicador': 'Ativa' if self.ids.ativa.state == 'down' else 'Inativa',
            'fase_corrente': self.ids.fase_corrente.text.strip(),
            'evento_fase_corrente': self.ids.evento_fase_corrente.text.strip(),
            'fase_intermediaria': self.ids.fase_intermediaria.text.strip(),
            'evento_fase_inter': self.ids.evento_fase_inter.text.strip(),
            'dest_final': 'Preservação' if self.ids.preservacao.state == 'down' else 'Eliminação',
            'reg_alteracao': self.ids.reg_alteracao.text.strip(),
            'observacoes': self.ids.observacoes.text.strip()}
        return data
    
    def insert_data_into_db(self):
        """Try to insert data into database,
        if successful regen treeview with new data"""
        data = self.text_fields_into_dict() ## Current item data dict
        parent = self.item_data if not self.new_cls else 'zero' ## set parent data if not new cls
        if self.ids.cls_nome.text.strip() and self.ids.cls_codigo.text.strip() != '':
            ## if required fields are not empty
            try:
                ## Instantiate data manager object \/
                to_insert = ManageData(item_data=data,parent_data=parent)
                if not self.editing:
                    to_insert.insert_into_db() ## inserts into database
                else:
                    to_insert.update_db() ## updates database
            except:
                toast('Algo deu errado! Impossível salvar a Classe.')
            else:
                toast('Classe salva com sucesso!',1)
                self.app.root.ids.data_frame.clear_widgets() ## clear data management frame 
                self.app.pcd_tree.regen_tree() ## Regenerates pcd treeview
                self.app.pcd_tree.switch_button(reset=True) ## switch toggle nodes button
                self.app.pcd_tree.disabled = False ## Unlocks treeview
        else:
            ## if required fields are empty
            toast('Campos obrigatórios estão em branco!')
            self.ids.cls_codigo.focus = True if self.ids.cls_codigo.text.strip() == '' else False
            self.ids.cls_nome.focus = True if self.ids.cls_nome.text.strip() == '' else False
class DraggableBaseWidget(ScatterLayout):
    dbName = Properties.StringProperty("base")
    do_rotation = False
    do_scale = False
    do_translation = False
    edit_mode = Properties.BooleanProperty(False)
    dbInstance = Properties.ObjectProperty()

    # FOR 2 SEC HOLDING
    heldForLongEnoughEvent = Properties.ObjectProperty()

    # TODO METER EL DEJAR PULSADO DOS SEGUNDOS
    # TODO QUE AL ENTRAR EN EDIT, SALGA UN MARQUITO Y EL ICONO DE DESPLAZAMIENTO (LAS FLECHAS EN CUATRO DIRECCIONES)
    # TODO QUE AL ESTAR EN EDIT, PULSAR FUERA DEL WIDGET LO GUARDE, EN VEZ DE ESPERAR POR UN DOUBLE CLICK DENTRO DEL WIDGET

    def __init__(self, **kwargs):
        super(DraggableBaseWidget, self).__init__(**kwargs)
        self.dbInstance = self.getInstanceFromDB()
        self.pos = (self.dbInstance.posX, self.dbInstance.posY)

    def on_edit_mode(self, instance, value):
        self.do_translation = (self.edit_mode, self.edit_mode)
        self.scale = 1
        self.do_translation = value
        if (value):
            # Edit Mode activado
            transitionName = "in_out_quad"
            anim = Animation(scale=1.05, duration=.5, t=transitionName)
            anim += Animation(scale=.95, duration=.5, t=transitionName)
            anim.repeat = True
            anim.start(self)
        else:
            # Edit Mode desactivado
            self.updateInstanceOnDB()
            transitionName = "in_out_sine"
            Animation.stop_all(self)
            anim = Animation(scale=1.1, duration=.25, t=transitionName)
            anim += Animation(scale=.9, duration=.25, t=transitionName)
            anim += Animation(scale=1, duration=.125, t=transitionName)
            anim.start(self)

    # FOR DOUBLE TAP EDIT
    # def on_touch_move(self, touch):
    #     if self.edit_mode:
    #         return super().on_touch_move(touch)

    # def on_touch_down(self, touch):
    #     if self.collide_point(touch.pos[0], touch.pos[1]) and touch.is_double_tap:
    #         self.edit_mode = not self.edit_mode
    #     else:
    #         return super().on_touch_down(touch)

    def on_touch_up(self, touch):
        if (self.collide_point(touch.pos[0], touch.pos[1])):
            try:
                self.heldForLongEnoughEvent.cancel()
            except:
                pass
        return super().on_touch_up(touch)

    def on_touch_down(self, touch):

        if self.edit_mode:
            if (not self.collide_point(touch.pos[0], touch.pos[1])):
                self.edit_mode = False
            return super().on_touch_down(touch)
        else:
            if (self.collide_point(touch.pos[0], touch.pos[1])):
                try:
                    self.heldForLongEnoughEvent.cancel()
                except:
                    pass

                self.heldForLongEnoughEvent = Clock.schedule_once(
                    self.heldForLongEnough, 1)
            else:
                return super().on_touch_down(touch)

    def heldForLongEnough(self, dt):
        self.edit_mode = True

    def updateInstanceOnDB(self):
        self.dbInstance.posX = self.pos[0]
        self.dbInstance.posY = self.pos[1]
        self.dbInstance.save()

    def getInstanceFromDB(self):
        try:
            instance = Draggable.objects.get(draggableName=self.dbName)
        except:
            instance = Draggable(draggableName=self.dbName,
                                 posX=self.pos[0], posY=self.pos[1])
            instance.save()
        return instance
class ColoredLabel(Label):
    background_color = Properties.ListProperty((0, 0, 0, 1))
    visible = Properties.BooleanProperty()
Beispiel #26
0
class Player(Widget):
    speedx = kp.NumericProperty(0)
    shield = kp.NumericProperty(100)
    alive = kp.BooleanProperty(True)
    lives = kp.NumericProperty(PLAYER_LIVES)
    hidden = kp.BooleanProperty(False)
    power = kp.NumericProperty(1)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.groups = ["all_sprites"]

        self.keys = set()
        Window.bind(on_key_down=self._on_keyboard_down)
        Window.bind(on_key_up=self._on_keyboard_up)

        self.path = convert_list2path(init_path=IMG_DIR, path_list=PLAYER_PATH)

        self.w_hint = PLAYER_WIDTH
        self.h_hint = PLAYER_HEIGHT
        self.width = self.w_hint * Window.width
        self.height = self.h_hint * Window.height

        self.diameter = min(self.width, self.height)
        self.radius = self.diameter / 2
        self.last_shot = time.time()

        with self.canvas:
            self.rect = Rectangle(pos=self.pos, size=self.size, source=self.path)
            Color(1, 1, 1, DEBUG_PLAYER_RADIUS * 0.5)
            self.ellipse = Ellipse(center=self.center, size=(self.diameter, self.diameter))
            Color(1, 1, 1, 1)
            Color(1, 1, 1, DEBUG_PLAYER_RECT_HIT * 0.5)
            self.rect_hit = Rectangle(pos=self.pos, size=self.size)
            Color(1, 1, 1, 1)
        self.bind(pos=self.update_rect)

        self.new()

    def update_rect(self, *args):
        # hit box:
        self.ellipse.pos = (self.center_x - self.radius, self.center_y - self.radius)
        self.rect_hit.pos = self.pos
        # rect:
        self.rect.pos = self.pos
        self.rect.size = self.size

    def new(self):
        # print("new player")
        self.center_x = Window.width * 0.5
        self.y = Window.height * PLAYER_Y
        self.speedx_hint = 0
        self.speedy_hint = 0
        self.shield = 100
        self.lives = PLAYER_LIVES

    def _on_keyboard_down(self, *args):
        key = CONVERT_CODE2KEY.get(args[2])
        self.keys.add(key)

    def _on_keyboard_up(self, *args):
        # print(keyboard, keycode)
        try:
            key = CONVERT_CODE2KEY.get(args[2])
            self.keys.remove(key)
        except:
            pass

    def update(self, dt):
        # print("update player", self.x)
        self.speedx_hint = 0
        if "right" in self.keys:
            self.speedx_hint = PLAYER_SPEED
        if "left" in self.keys:
            self.speedx_hint = -PLAYER_SPEED
        if "spacebar" in self.keys:
            self.shoot()

        self.x += self.speedx_hint * Window.width
        self.y += self.speedy_hint * Window.height

        if self.x < 0:
            self.x = 0
        if self.right > Window.width:
            self.right = Window.width

    def power_up(self):
        self.power += 1
        Clock.schedule_once(self.power_up_time_over, POWER_UP_TIME)

    def power_up_time_over(self, dt):
        self.power -= 1

    def shoot(self):
        now = time.time()
        if now - self.last_shot > SHOOT_DELAY:
            self.last_shot = now
            if self.power == 1:
                Bullet(self.parent, self.center_x, self.top)
            elif self.power > 1:
                Bullet(self.parent, self.x, self.center_y)
                Bullet(self.parent, self.right, self.center_y)

    def lose_1_life(self):
        # hide the player temporarily
        self.hidden = True
        self.y -= 1000
        # update player stats:
        self.lives -= 1
        self.shield = 100
        # check drawing lives:
        self.parent.remove_widget(self.parent.drawed_lives[-1])
        self.parent.drawed_lives.pop()
        Clock.schedule_once(self.unhide, PLAYER_TIME_TO_UNHIDE)

    def unhide(self, dt):
        self.hidden = False
        print("parent", self.parent)
        self.center_x = self.parent.center_x
        self.y += 1000

    def kill(self):
        for group_name in self.groups:
            group = getattr(self.parent, group_name)
            group.remove(self)
        self.parent.remove_widget(self)
        self.alive = False
Beispiel #27
0
class Game(Widget):
    paused = kp.BooleanProperty(False)
    score = kp.NumericProperty(0)
    explosion_over = kp.BooleanProperty(False)

    def __init__(self, **kwargs):
        self.player = Player()
        super().__init__(**kwargs)
        self.all_touchs = []

        self.new()

        self.dir = path.dirname(__file__)
        self.bg = convert_list2path(init_path=IMG_DIR, path_list=BG)

        with self.canvas.before:
            self.rect = Rectangle(pos=self.pos, size=Window.size, source=self.bg)

    def new(self):
        self.score = 0
        self.paused = False
        self.over = False
        self.all_sprites = []
        self.bullets = []
        self.mobs = []
        self.power_ups = []
        self.player.new()
        self.add_new_sprite(self.player)
        for _ in range(MOBS_N):
            Mob(self)
        # drawing init lives:
        self.drawed_lives = []
        drawed_live_size = Window.width * LIVES_WIDTH, Window.height * LIVES_HEIGHT
        drawed_live_source = convert_list2path(init_path=IMG_DIR, path_list=PLAYER_PATH)
        for i in range(PLAYER_LIVES):
            x = Window.width * (LIVES_X + (LIVES_WIDTH  + LIVES_MARGIN) * i)
            drawed_live_pos = x, Window.height * LIVES_Y
            self.drawed_lives.append(Life(*drawed_live_pos, *drawed_live_size, drawed_live_source))
            self.add_widget(self.drawed_lives[-1])


    def add_new_sprite(self, sprite):
        for group_name in sprite.groups:
            group = getattr(self, group_name)
            group.append(sprite)
        self.add_widget(sprite)

    def on_touch_down(self, touch):
        if self.paused:
            return
        print("on_touch_down")
        if len(self.all_touchs) > 0:
            self.player.keys.add("spacebar")
        self.all_touchs.append(touch)

    def on_touch_move(self, touch):
        if self.paused:
            return
        print(touch.dx)
        self.player.x += touch.dx

    def on_touch_up(self, touch):
        if self.paused:
            return
        print("on_touch_up")
        try:
            self.player.keys.remove("spacebar")
        except KeyError:
            pass
        try:
            self.all_touchs.remove(touch)
        except ValueError:
            pass

    def quit_game(self):
        # print("quit game")
        self.over = True
        for sprite in self.all_sprites.copy():
            sprite.kill()

    def update(self, dt):
        if self.over:
            return False
        if self.paused:
            return
        self.rect.size = Window.size
        for sprite in self.all_sprites:
            sprite.update(dt)
        # check to see if a bullet hit a mob:
        hits = self.groupcollide(self.mobs, self.bullets, True, True)
        for hit in hits:
            self.score += 100 / hit.radius
            explosion = Explosion(center=hit.center, size=hit.size, _type="mob")
            self.add_widget(explosion)
            Mob(self)
            if random.random() < POWER_UP_CHANCE:
                power_up = PowerUp(hit.center)
                self.add_new_sprite(power_up)

        # check to see if a mob hit the player:
        hits = self.spritecollide(self.player, self.mobs, destroy=True, func="circular")
        for hit in hits:
            self.player.shield -= hit.radius
            explosion = Explosion(center=hit.center, size=hit.size, _type="mob")
            self.add_widget(explosion)
            Mob(self)
            if self.player.shield <= 0:
                self.death_explosion =\
                  Explosion(center=self.player.center, size=self.player.size, _type="player")
                self.add_widget(self.death_explosion)
                self.player.lose_1_life()

        # check to see if a player hit a powerup:
        hits = self.spritecollide(self.player, self.power_ups, True)
        for hit in hits:
            if hit._type == "shield":
                self.player.shield += random.randrange(SHIELD_MIN, SHIELD_MAX)
                if self.player.shield > 100:
                    self.player.shield = 100
            if hit._type == "gun":
                self.player.power_up()

        # if the player died and the explosion has finished playing:
        if self.player.lives == 0 and self.explosion_over:
            self.paused = True

    def spritecollide(self, sprite, group, destroy=False, func=None):

        def append(sprites_that_collide, sprite_i, destroy):
            sprites_that_collide.append(sprite_i)
            if destroy:
                sprite_i.kill()

        sprites_that_collide = []
        for sprite_i in group:
            # print(sprite_i.pos, sprite_i.size)
            if sprite_i.collide_widget(sprite):
                # print("colide")
                if func == "circular":
                    dist = Vector(*sprite.center).distance(Vector(*sprite_i.center))
                    if dist < sprite.radius + sprite_i.radius:
                        append(sprites_that_collide, sprite_i, destroy)
                if not func:
                    append(sprites_that_collide, sprite_i, destroy)
        return sprites_that_collide

    def groupcollide(self, group1, group2, destroy1=False, destroy2=False):
        sprites_that_collide = {}
        for g1_sprite in group1.copy():
            for g2_sprite in group2.copy():

                if g1_sprite.collide_widget(g2_sprite):
                    if destroy1:
                        g1_sprite.kill()
                    if destroy2:
                        g2_sprite.kill()
                    try:
                        sprites_that_collide[g1_sprite].append(g2_sprite)
                    except:
                        sprites_that_collide[g1_sprite] = [g2_sprite]
        return sprites_that_collide
Beispiel #28
0
class PCDTree(MDBoxLayout):
    """Treeview widget + buttons and dialogs
    manipulations refered to data"""

    btn_icon = prop.ListProperty(['unfold-more-horizontal','unfold-less-horizontal'])
    btn_text = prop.ListProperty(['Expandir Árvore', 'Retrair Árvore'])

    app = prop.ObjectProperty() ## Main APP reference
    toggled = prop.BooleanProperty(False) ## State of nodes
    nodes_dict = prop.DictProperty() ## All nodes instances callable via id

    dialog = prop.ObjectProperty() ## Search dialog
    search_widget = prop.ObjectProperty() ## Search dialog content instance
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.app = MDApp.get_running_app()
        self.populate_all_nodes() ## add nodes to the treeview

        self.search_widget = SearchFrame(self) ## creates search widget
        self.create_search_dialog() ## creates search dialog with `self.search_widget`
    """
    Treeview methods
    """
    def regen_tree(self):
        """Regenerates treeview nodes"""
        self.ids.treeview.root.nodes = [] ## clear nodes list
        self.ids.treeview.clear_widgets() ## clear nodes widgets
        self.toggled = False ## reset toggled state
        self.populate_all_nodes() ## populate treeview

    def _fetch_data_into_dict(self):
        """Fetches data from database and converts into dict 
        returns a list with a dict for each row of the database
        :return: list"""
        query = 'SELECT * FROM PCD ORDER BY cls_codigo'
        data = self.app.cursor.execute(query).fetchall()
        description = [ col[0] for col in self.app.cursor.description ]
        return [ dict(zip(description,item)) for item in data ]

    def _create_all_nodes(self):
        """Generates all nodes and sorts them between parents and
        children, returns a tupple of (parents,children) lists
        :return: tupple"""
        self.nodes_dict = {} ## nodes instances for future reference
        parents = [] ## parents list
        children = [] ## children list
        data = self._fetch_data_into_dict() ## database items in dict
        for item in data:
            ## Creates treeview node object for each item in database \/
            label = CustomTVLabel(text=f"{item['cls_codigo']} - {item['cls_nome']}")
            label.item_data = item ## add data dict to object
            label.bind(on_touch_down= lambda node, _: self._node_callback(node)) ## bind function
            ## Adding reference to dict
            self.nodes_dict[item['legacyId']] = label
            ## sorting parents and children
            if str(item['parentId']) == 'zero':
                parents.append(label)
            else:
                children.append(label)
        return parents,children

    def populate_all_nodes(self):
        """Populate treeview with new nodes"""
        parents,children = self._create_all_nodes()

        for parent in parents:
            ## add parents to tree
            self.ids.treeview.add_node(parent)
        
        ## adds children nodes into parents
        for parent in self.ids.treeview.iterate_all_nodes():
            for child in children:
                if parent != self.ids.treeview.root: ## skip root node
                    if child.item_data['parentId'] == parent.item_data['legacyId']:
                        self.ids.treeview.add_node(child,parent=parent)
                        children.remove(child)
    
    def _node_callback(self, node):
        """Callback for treeview nodes, checks if
        Form isn't already the selected node
        :param node: obj"""
        df_c = self.app.root.ids.data_frame.children
        if df_c and isinstance(df_c[0], DataManagement):
            ## Form exists
            if df_c[0].item_data['legacyId'] == node.item_data['legacyId']:
                ## Node is IN the current Form
                return
        ## Form doesn't exist or node != current node
        self.generate_data_frame(node)

    def generate_data_frame(self, node):
        """Creates data management obj from current
        node data. node = instance of selected node
        :param node: obj"""
        self.app.set_data_management_widget(
                view_only = True,
                item_data = node.item_data
                )
    
    def delete_node_from_tree(self):
        """Delete selected node from tree"""
        selected_node = self.ids.treeview.get_selected_node()
        self.ids.treeview.remove_node(selected_node)
        self.nodes_dict.pop(selected_node.item_data['legacyId'])
    """
    Buttons methods
    """
    def toggle_all_nodes(self):
        """Toggles all nodes to toggled state"""
        for node in self.ids.treeview.iterate_all_nodes():
            if node != self.ids.treeview.root:
                if self.toggled and node.is_open:
                    ## close open node
                    self.ids.treeview.toggle_node(node)
                if not self.toggled and not node.is_open:
                    ## open closed nodes
                    self.ids.treeview.toggle_node(node)
        ## switches toggled state \/
        self.toggled = not self.toggled
    
    def switch_button(self,reset=False):
        """Switches tooltip and icon when pressed"""
        if reset:
            self.btn_icon = ['unfold-more-horizontal','unfold-less-horizontal']
            self.btn_text = ['Expandir Árvore', 'Retrair Árvore']
        else:
            self.btn_icon[0], self.btn_icon[1] = self.btn_icon[1], self.btn_icon[0]
            self.btn_text[0], self.btn_text[1] = self.btn_text[1], self.btn_text[0]
    """
    Search dialog methods
    """
    def create_search_dialog(self):
        """Creates search dialog"""
        if not self.dialog:
            self.dialog = MDDialog(
                title = 'Clique na Classe para encontrá-la na árvore',
                size_hint = (.5,.9),
                pos_hint = {'right': .9},
                overlay_color = [0, 0, 0, .3],
                auto_dismiss = False,
                type = "custom",
                radius = [20,],
                content_cls = self.search_widget)
            self.dialog.bind(on_open = self.set_focus)

    def set_focus(self, *_):
        """Sets focus to text field"""
        self.search_widget.ids.to_search.focus = True
Beispiel #29
0
class NotesConfig(Screen):
    activeInter = Properties.BooleanProperty(True)
    showNotes = Properties.ObjectProperty(None)
    backg = Properties.ListProperty([224, 187, 228, 1])
    ind = 0

    def __init__(self, **kwargs):
        super(NotesConfig, self).__init__(**kwargs)
        self.pos_hint = {'center_y': 0.5, 'center_x': 0.5}
        self.showNotes.bind(minimum_height=self.showNotes.setter('height'))

        noteList = dbWrapper.getAllNotes()
        self.showNotesFunc(noteList)

    def goToMenuScreen(self, widget, selected):
        self.saveConfig()
        App.get_running_app().root.transition = FadeTransition(duration=.3)
        App.get_running_app().root.current = "menu"

    def showNotesFunc(self, noteList):
        for note in noteList:
            self.ids.showNotes.add_widget(
                ColoredLabelConfig(editing=False,
                                   noteid=note._id,
                                   texto=note.text,
                                   pinned=note.pinned,
                                   bcolor=(note.rgb[0] / 255,
                                           note.rgb[1] / 255,
                                           note.rgb[2] / 255, note.rgb[3])))
            self.ind += 1

    def writeNote(self, pinned, text, date, rgb):
        date = datetime.datetime.now()
        dbWrapper.saveNote(pinned, text, date, rgb)
        notas = dbWrapper.getAllNotes()
        nota = notas[len(notas) - 1]
        self.showNotesFunc([nota])

# --------------------------------

    def saveConfig(self):
        # guardar las configs
        print(self.activeInter)
        dbWrapper.saveNoteState(self.activeInter)

    def pressedBack(self, widget):
        anim = Animation(pos_hint={"center_x": .5, "y": -.03}, duration=.1)
        anim += Animation(pos_hint={"center_x": .5, "y": 0}, duration=.1)
        anim.bind(on_complete=partial(self.goToMenuScreen))
        anim.start(widget)

    def badAnim(self, boton):
        anim = Animation(backgSave=[.5, .4, .4, .2], duration=.1)
        anim += Animation(backgSave=[1, 1, 1, .2], duration=.1)
        anim.bind(on_complete=self.goTop)
        anim.start(boton)
        if self.ids.textinput.text == "":
            anim = Animation(canvBack=[1, 0, 0, .4], duration=.5)
            anim += Animation(canvBack=[1, 1, 1, .4], duration=.9)
            anim.start(self.ids.textinput)

    def goodAnim(self, boton):
        anim = Animation(backgSave=[1, 1, 1, .5], duration=.1)
        anim += Animation(backgSave=[1, 1, 1, .2], duration=.1)
        anim.bind(on_complete=self.goTop)
        anim.bind(on_complete=self.clearInputs)
        anim.start(boton)

    def goTop(self, boton, asd):
        anim = Animation(scroll_y=1, duration=.15)
        anim.start(self.ids.scrollCreateNote)

    def clearInputs(self, boton, asd):
        self.ids.textinput.text = ""

    def switchElegir(self, boton, asd):
        self.ids.panel.switch_to(self.ids.elegir)
Beispiel #30
0
class Game(Screen):
    all_crosses = kp.ListProperty()
    all_circles = kp.ListProperty()
    player = kp.StringProperty("")
    mob = kp.StringProperty("")
    game_over = kp.BooleanProperty(False)
    who_is_first = kp.StringProperty("mob")
    player_wins = kp.NumericProperty()
    mob_wins = kp.NumericProperty()

    def __init__(self, **kwargs):
        super().__init__()
        self.bind(size=self.draw_lines)
        self.bind(size=self.draw_crosses)
        self.bind(size=self.draw_circles)
        self.new_game()

    def new_game(self, *args):
        print("\nnew_game", args)
        self.all_circles = []
        self.all_crosses = []
        self.draw_lines()
        self.game_over = False
        self.who_is_first = "player" if self.who_is_first == "mob" else "mob"
        print("self.who_is_first", self.who_is_first)
        if self.who_is_first == "player":
            self.player = "cross"
            self.mob = "circle"
        elif self.who_is_first == "mob":
            print("is mob")
            self.player = "circle"
            self.mob = "cross"
            new_coord = self.calc_next_mob_coord()
            self.draw_symbol("mob", new_coord)
        print("self.player", self.player)

    def calc_lines(self):
        X = self.width
        Y = self.height
        x = X / 3
        y = Y / 3
        return [
            [x, 0, x, Y],
            [2 * x, 0, 2 * x, Y],
            [0, y, X, y],
            [0, 2 * y, X, 2 * y],
        ]

    def draw_lines(self, *args):
        print("draw_lines()", self.size)
        self.canvas.clear()
        lines = self.calc_lines()
        with self.canvas:
            for line in lines:
                Line(points=line)

    def calc_cross(self, coord_x, coord_y):
        X = self.width
        Y = self.height
        x = X / 3
        y = Y / 3
        offset_x = coord_x * x
        offset_y = coord_y * y
        return [[offset_x, offset_y, x + offset_x, y + offset_y],
                [x + offset_x, offset_y, offset_x, y + offset_y]]

    def draw_crosses(self, *args):
        with self.canvas:
            for cross_coord in self.all_crosses:
                print("cross_coord", cross_coord)
                lines = self.calc_cross(*cross_coord)
                for line in lines:
                    Line(points=line)

    def calc_circle(self, coord_x, coord_y):
        # print("calc_circle(%s, %s)" % (coord_x, coord_y))
        # print(self.size)
        X = self.width
        Y = self.height
        x = X / 3
        y = Y / 3
        # print(x, y)
        offset_x = coord_x * x
        offset_y = coord_y * y
        return (offset_x, offset_y, x, y)

    def draw_circles(self, *args):
        print("draw_circles()", args, self.all_circles)
        with self.canvas:
            for circle_coord in self.all_circles:
                Line(ellipse=self.calc_circle(*circle_coord))

    def calc_coord(self, pos_x, pos_y):
        print("calc_coord(%s, %s)" % (pos_x, pos_y))
        X = self.width
        Y = self.height
        x = X / 3
        y = Y / 3
        coord_x = pos_x // x
        coord_y = pos_y // y
        print("X: %s Y: %s, x: %s y: %s, coord_x: %s coord_y: %s" %
              (X, Y, x, y, coord_x, coord_y))
        if 0 <= coord_x < 3 and 0 <= coord_y < 3:
            return coord_x, coord_y

    def draw_symbol(self, who, new_coord):
        print("\ndraw_symbol(%s, %s)" % (who, new_coord))
        symbol = getattr(self, who)

        if symbol == "cross":
            coords = self.all_crosses
            function = self.draw_crosses
        elif symbol == "circle":
            coords = self.all_circles
            function = self.draw_circles

        if new_coord in self.all_crosses + self.all_circles:
            return True
        coords.append(new_coord)
        function()
        if self.check_if_win_by_who(who):
            print("\n\n%s WIN with %s\n\n\n" % (who, symbol))
            Factory.GameOverPopup(game=self, who_win=who).open()
            self.game_over = True
            if who == "player":
                self.player_wins += 1
            else:
                self.mob_wins += 1
            return True
        return False

    def on_touch_down(self, *args):
        print("on_touch_down", args[0].pos)
        print("self.all_circles", self.all_circles)
        if self.game_over:
            return

        pos = args[0].pos

        # Player:
        new_coord = self.calc_coord(*pos)
        if not new_coord:
            return
        print("self.player", self.player)
        if self.draw_symbol("player", new_coord):
            return

        # Mob:
        new_coord = self.calc_next_mob_coord()
        self.draw_symbol("mob", new_coord)

    def calc_next_mob_coord(self):
        print("calc_next_mob_coord()")
        avail_coords = [(x, y) for x in range(3) for y in range(3)]
        print("avail_coords", avail_coords)
        print("self.all_crosses + self.all_circles",
              self.all_crosses + self.all_circles)
        for coord in self.all_crosses + self.all_circles:
            print("coord", coord)
            avail_coords.remove(coord)
        print("avail_coords", avail_coords)
        if avail_coords:
            choosed_coord = random.choice(avail_coords)
            print("choosed_coord", choosed_coord)
            return choosed_coord

    def check_if_win_by_coords(self, coords):
        print("check_if_win_by_coords(%s)" % coords)
        all_possible_wins = [[(0, 0), (1, 1), (2, 2)], [(2, 0), (1, 1),
                                                        (0, 2)],
                             [(0, 0), (1, 0), (2, 0)], [(0, 1), (1, 1),
                                                        (2, 1)],
                             [(0, 2), (1, 2), (2, 2)], [(0, 0), (1, 0),
                                                        (2, 0)],
                             [(0, 0), (0, 1), (0, 2)], [(1, 0), (1, 1),
                                                        (1, 2)],
                             [(2, 0), (2, 1), (2, 2)]]
        if len(coords) < 3:
            return False
        for possible_win in all_possible_wins:
            # print("possible_win", possible_win)
            for possible_coord in possible_win:
                # print("possible_coord", possible_coord)
                # print(possible_coord not in coords, possible_coord, coords)
                if possible_coord not in coords:
                    break
            else:
                # print(possible_win)
                return True
        return False

    def check_if_win_by_who(self, who):
        symbol = getattr(self, who)
        map_symbol = {
            "cross": "all_crosses",
            "circle": "all_circles",
        }
        coords = getattr(self, map_symbol[symbol])
        return self.check_if_win_by_coords(coords)