from PIL import Image, ImageTk
import tkinter

from . import battleship
from .battleshipconfig import *
from .errortypes import BadLocationError, PlacementError
from .gamecanvas import GameCanvas
from .targetgridcanvas import TargetGridCanvas
from .startmenucanvas import StartMenuCanvas
from .imageloader import instance as gImageLoader
from .pegsprite import PegSprite

# Canvas for setup portion of the game (placing ships). Also maintains
# visual representation of a player's own board state.
class OceanGridCanvas(GameCanvas):
    def __init__(self, parent: tkinter.Tk, player: battleship.ClassicPlayer, width: int, height: int, on_ships_are_placed: 'func'):
        super().__init__(parent, bg='blue', width=width, height=height)
        self._parent = parent
        self._width = width
        self._height = height

        self._player = player
        self._on_ships_are_placed = on_ships_are_placed

        ### load images of the board and ships ###
        ocean_grid = gImageLoader.load(OCEAN_GRID_PATH)
        self._ocean_grid_img = ocean_grid
        self._ocean_grid_photo = ImageTk.PhotoImage(self._ocean_grid_img)
        self._ocean_grid_id = None

        carrier_img = gImageLoader.load(CARRIER_PATH)
        self._carrier_img = carrier_img

        battleship_img = gImageLoader.load(BATTLESHIP_PATH)
        self._battleship_img = battleship_img

        destroyer_img = gImageLoader.load(DESTROYER_PATH)
        self._destroyer_img = destroyer_img

        patrolboat_img = gImageLoader.load(PATROLBOAT_PATH)
        self._patrolboat_img = patrolboat_img

        submarine_img = gImageLoader.load(SUBMARINE_PATH)
        self._submarine_img = submarine_img

        # Pegs to show enemy moves / hits
        self._pegs = [[PegSprite() for _ in range(battleship.COLUMNS)] for _ in range(battleship.ROWS)]

        # Images to be manipulated and turned into Photos
        self._ship_imgs = {battleship.Carrier.__name__: {0: self._carrier_img, 90: None, 180: None, 270: None, 360: None},
                           battleship.BattleShip.__name__: {0: self._battleship_img, 90: None, 180: None, 270: None, 360: None},
                           battleship.Destroyer.__name__: {0: self._destroyer_img, 90: None, 180: None, 270: None, 360: None},
                           battleship.Submarine.__name__: {0: self._submarine_img, 90: None, 180: None, 270: None, 360: None},
                           battleship.PatrolBoat.__name__: {0: self._patrolboat_img, 90: None, 180: None, 270: None, 360: None}}

        # Photos passed into create_image functions
        self._ship_photos = {battleship.Carrier.__name__: {0:ImageTk.PhotoImage(self._carrier_img),90: None, 180: None, 270: None, 360: None},
                             battleship.BattleShip.__name__: {0: ImageTk.PhotoImage(self._battleship_img), 90: None, 180: None, 270: None, 360: None},
                             battleship.Destroyer.__name__: {0: ImageTk.PhotoImage(self._destroyer_img), 90: None, 180: None, 270: None, 360: None},
                             battleship.Submarine.__name__: {0: ImageTk.PhotoImage(self._submarine_img), 90: None, 180: None, 270: None, 360: None},
                             battleship.PatrolBoat.__name__: {0:ImageTk.PhotoImage(self._patrolboat_img), 90: None, 180: None, 270: None, 360: None}}

        self._mouse_btn1_down = False
        self.bind('<Button-1>', self._on_mouse_btn1_down)
        self.bind('<ButtonRelease-1>', self._on_mouse_btn1_release)

        self._ships_are_placed = False # true if all ships placed
        self._is_placement_phase = True
        self._confirm_text_id = None
        self._confirm_text = "Press enter to confirm ship placement"
        self._confirm_x = 0
        self._confirm_y = 0
        self._confirm_width = 0

        self._has_ship_selected = False
        self._selected_ship = None
        self._selected_ship_type = None
        self._selected_ship_is_vertical = True
        self._selected_ship_degree = 0

    def display(self) -> None:
        print('Ocean should display')
        self._start()
        self.focus_set()
        self.pack()

    def hide(self) -> None:
        self.pack_forget()

    # sets peg colors depending on board state and redraws
    def on_hit(self) -> None:
        x_spacing = DEFAULT_PEG_AREA_WIDTH / battleship.COLUMNS
        y_spacing = DEFAULT_PEG_AREA_WIDTH / battleship.ROWS

        # set the PegSprite location, color for every peg
        for r in range(battleship.ROWS):
            for c in range(battleship.COLUMNS):
                peg = self._pegs[r][c]
                if self._player.ocean_grid.pegs[r][c] == battleship.RED:
                    peg.color = PEG_HIT
                else:
                    peg.color = PEG_MISS

                peg.x1 = c * x_spacing + DEFAULT_HEADER_WIDTH + DEFAULT_PEG_SIZE
                peg.y1 = r * y_spacing + DEFAULT_HEADER_HEIGHT + DEFAULT_PEG_SIZE
                peg.x2 = (c + 1) * x_spacing + DEFAULT_HEADER_WIDTH - DEFAULT_PEG_SIZE
                peg.y2 = (r + 1) * y_spacing + DEFAULT_HEADER_HEIGHT - DEFAULT_PEG_SIZE

                peg.id = self.create_oval((peg.x1, peg.y1), (peg.x2, peg.y2), fill=peg.color)
                self._pegs[r][c] = peg

        self._redraw()

    def _start(self) -> None:
        #self.delete(self._click_text_id)
        self._redraw()
        self.bind('<Motion>', self._on_mouse_moved)
        self.bind('<Shift_L>', self._on_shift_down)
        self.bind('<Return>', self._on_return_down)

    def _on_return_down(self, event: tkinter.Event) -> None:
        if self._ships_are_placed:
            self._on_ships_are_placed()

            if self._confirm_text_id:
                self.delete(self._confirm_text_id)

            self.unbind('<Return>')
            self._is_placement_phase = False

    def _redraw(self) -> None:
        # Redraw ships ( and later pegs )
        if self._ocean_grid_id:
            self.delete(self._ocean_grid_id)

        self._ocean_grid_id = self.create_image((round(self._width/2), round(self._height/2)),
                                                image=self._ocean_grid_photo, anchor='center')

        if self._confirm_text_id:
            self.delete(self._confirm_text_id)

            if self._ships_are_placed and self._is_placement_phase:
                self._confirm_text_id = self.create_text((self._confirm_x, self._confirm_y), width=self._confirm_width,
                                                         text=self._confirm_text, fill='white', anchor='w')

        for ship in self._player.ships.values():
            if ship:
                sprite = ship.sprite
                if sprite.id:
                    self.delete(sprite.id)

                    sprite.id = self.create_image(
                        (sprite.x, sprite.y),
                        image=sprite.photo,
                        anchor="center")

        for r in range(battleship.ROWS):
            for c in range(battleship.COLUMNS):
                if self._player.ocean_grid.pegs[r][c] != None:
                    peg = self._pegs[r][c]
                    if peg.id:
                        self.delete(peg.id)

                    peg.id = self.create_oval((peg.x1, peg.y1), (peg.x2, peg.y2), fill=peg.color)

    def _on_mouse_btn1_down(self, event: tkinter.Event) -> None:
        self._mouse_btn1_down = True

##        if not self._ships_are_placed:
        x_ratio = event.x / self.winfo_width() # ratio of click in relation to entire window
        bay_x_ratio = DEFAULT_SHIPBAY_X1 / DEFAULT_WIDTH

        print(event.x, event.y)
        print(x_ratio, bay_x_ratio)

        if self._is_placement_phase:
            if x_ratio <=1 and x_ratio >= bay_x_ratio:
                self._select_ship_from_bay(event.y)
                if self._selected_ship_type:
                    existing_ship = self._player.ships[self._selected_ship_type]
                    if existing_ship:
                        if existing_ship.is_placed:
                            self._deselect_ship(False)
                            return
                        print(self._selected_ship_type, existing_ship.is_placed)

                    ROTATION_DEGREE = 0

                    selected_sprite = self._selected_ship.sprite
                    selected_sprite.x = event.x
                    selected_sprite.y = event.y
                    selected_sprite.degree = self._selected_ship_degree
                    selected_sprite.image = self._ship_imgs[self._selected_ship_type][ROTATION_DEGREE]
                    selected_sprite.photo = self._ship_photos[self._selected_ship_type][ROTATION_DEGREE]
                    selected_sprite.id = self.create_image(
                        (selected_sprite.x, selected_sprite.y),
                        image=selected_sprite.photo,
                        anchor="center")

                    print(selected_sprite.id)

            else:
                x_ratio = DEFAULT_PEG_AREA_WIDTH / battleship.COLUMNS
                y_ratio = DEFAULT_PEG_AREA_WIDTH / battleship.ROWS

                click_col = int(event.x/x_ratio)
                col = click_col - 1

                click_row = int(event.y/y_ratio)
                row = click_row - 1

                row_str = None
                try:
                    row_str = battleship.ROW_LETTERS[row]
                except KeyError as e:
                    print(e)
                else:
                    try:
                        ship_at_click = self._player.ocean_grid.at((row_str, col))
                    except BadLocationError as e:
                        print(e)
                    else:
                        if ship_at_click:
                            self._select_ship(ship_at_click)
                            self._player.ocean_grid.unplace(ship_at_click)

    def _on_mouse_btn1_release(self, event: tkinter.Event) -> None:
        self._mouse_btn1_down = False
        if self._has_ship_selected:
            col_width = DEFAULT_PEG_AREA_WIDTH / battleship.COLUMNS
            row_height = DEFAULT_PEG_AREA_WIDTH / battleship.ROWS

            print(int(event.y/row_height))
            click_col = int(event.x/col_width)
            col = click_col - 1

            click_row = int(event.y/row_height)
            row = click_row - 1
            start_row = end_row = start_col = end_col = None

            if self._selected_ship_is_vertical:
                print('Vertical placement')
                if self._selected_ship.length > 2:
                    if self._selected_ship.length % 2 != 0:
                        start_row = row - int(self._selected_ship.length/2)
                        end_row = row + int(self._selected_ship.length/2)
                    else:
                        start_row = row - self._selected_ship.length % 3
                        end_row = row + int(self._selected_ship.length/2)
                else:
                    start_row = row
                    end_row = row + 1

                start_col = end_col = col
            else:
                print('Horizontal placement')
                if self._selected_ship.length > 2:
                    if self._selected_ship.length % 2 != 0:
                        start_col = col - int(self._selected_ship.length/2)
                        end_col = col + int(self._selected_ship.length/2)
                        print('col: {}, click_col: {}, start_col: {}, end_col: {}'.format(col, click_col, start_col, end_col))
                    else:
                        start_col = col - self._selected_ship.length % 3
                        end_col = col + int(self._selected_ship.length/2)
                else:
                    start_col = col
                    end_col = col + 1

                start_row = end_row = row

            try:
                start_row_str = battleship.ROW_LETTERS[start_row]
                end_row_str = battleship.ROW_LETTERS[end_row]
                print('Attempting place. Degree: {}'.format(self._selected_ship_degree))
                self._player.ocean_grid.place((start_row_str, start_col), (end_row_str, end_col), self._selected_ship)
            except PlacementError as place_error:
                print(place_error)
                print('Failed place, x: {} y: {}, row1: {} col1: {}, row2: {} col2: {}'.format(
                    event.x, event.y, start_row_str, start_col+1, end_row_str, end_col+1))
                self._deselect_ship(True)
            except KeyError as key_error:
                print('Failed place. Numeric key is out of expected range (ship will be placed out of board).')
                print('start_row: {}, end_row: {}'.format(start_row, end_row))
                print('start_col: {}, end_col: {}'.format(start_col, end_col))
                self._deselect_ship(True)
            else:
                # Player's ship should now be placed
                print(self._selected_ship.is_placed)
                selected_sprite = self._selected_ship.sprite
                if selected_sprite.id:
                    self.delete(selected_sprite.id)

                x = y = 0

                if self._selected_ship_is_vertical:
                    if self._selected_ship.length % 2 != 0:
                        x = (click_col * DEFAULT_COL_WIDTH) + (DEFAULT_COL_WIDTH/3)
                        y = (click_row * DEFAULT_ROW_HEIGHT) + (DEFAULT_ROW_HEIGHT/3)
                    else:
                        x = (click_col * DEFAULT_COL_WIDTH) + (DEFAULT_COL_WIDTH/3)
                        y = (click_row * DEFAULT_ROW_HEIGHT) + (DEFAULT_ROW_HEIGHT * 5/6)
                else:
                    if self._selected_ship.length % 2 != 0:
                        x = (click_col * DEFAULT_COL_WIDTH) + (DEFAULT_COL_WIDTH /3)
                        y = (click_row * DEFAULT_ROW_HEIGHT) + (DEFAULT_ROW_HEIGHT/3)
                    else:
                        x = (click_col * DEFAULT_COL_WIDTH) + (DEFAULT_COL_WIDTH * 5/6)
                        y = (click_row * DEFAULT_ROW_HEIGHT) + (DEFAULT_ROW_HEIGHT/3)

                print('Click: {}, {}. Placed at: {},{}'.format(event.x, event.y, x, y))
                print('row1: {} col1: {}, row2: {} col2: {}'.format(start_row_str, start_col+1, end_row_str, end_col+1))
                print('Degrees: {}'.format(self._selected_ship_degree))

                selected_sprite.x = x
                selected_sprite.y = y
                selected_sprite.degree = self._selected_ship_degree
                selected_sprite.image = self._ship_imgs[self._selected_ship_type][self._selected_ship_degree]
                selected_sprite.photo = self._ship_photos[self._selected_ship_type][self._selected_ship_degree]
                selected_sprite.id = self.create_image(
                    (selected_sprite.x, selected_sprite.y),
                    image=selected_sprite.photo,
                    anchor="center")

                self._player.ships[self._selected_ship_type] = self._selected_ship
                print(self._player.ships)

                self._deselect_ship(False)

                print('Checking if all placed')
                self._ships_are_placed = self._player.ships_are_placed()
                if self._ships_are_placed:
                    print('all placed: {}'.format(self._ships_are_placed))
                    print('All ships placed')
##                    self._on_ships_are_placed()
                    self._draw_confirm_text()

            if self._is_placement_phase and not self._ships_are_placed and self._confirm_text_id:
                self.delete(self._confirm_text_id)

    def _draw_confirm_text(self) -> None:
        self._confirm_x = DEFAULT_SHIPBAY_X1
        self._confirm_y = DEFAULT_SHIPBAY_Y2 + DEFAULT_ROW_HEIGHT
        self._confirm_width = DEFAULT_WIDTH - self._confirm_x

        if self._confirm_text_id:
            self.delete(self._confirm_text_id)
        self._confirm_text_id = self.create_text((self._confirm_x, self._confirm_y), width=self._confirm_width,
                                                 fill='white', text=self._confirm_text, anchor='w')

    def _select_ship(self, ship: battleship.Ship) -> None:
        self._has_ship_selected = True
        self._selected_ship = ship
        self._selected_ship_type = type(ship).__name__
        print(self._selected_ship_type)
        self._selected_ship_degree = ship.sprite.degree
        self._selected_ship_is_vertical = (self._selected_ship_degree == 0
                                               or self._selected_ship_degree == 180
                                               or self._selected_ship_degree == 360)
        self._ships_are_placed = False

    def _select_ship_from_bay(self, y: int) -> None:
        ship = self._get_bay_ship_type(y)
        if ship:
            self._has_ship_selected = True
            self._selected_ship = ship()
            self._selected_ship_type = ship.__name__
            print(self._selected_ship_type)
            self._selected_ship_degree = 0
            self._selected_ship_is_vertical = True

    def _deselect_ship(self, should_delete: bool) -> None:
        # Deselect currently selected ship
        selected_sprite = self._selected_ship.sprite
        if selected_sprite.id:
            if should_delete:
                self.delete(selected_sprite.id)

                self._player.ships[self._selected_ship_type] = None

        self._has_ship_selected = False
        self._selected_ship = None
        self._selected_ship_type = None
        self._selected_ship_degree = 0
        self._selected_ship_is_vertical = True

    def _on_mouse_moved(self, event: tkinter.Event) -> None:
        if self._mouse_btn1_down:
            if self._has_ship_selected and self._is_placement_phase:
                if self._is_placement_phase and not self._ships_are_placed and self._confirm_text_id:
                    self.delete(self._confirm_text_id)

                selected_sprite = self._selected_ship.sprite
                if selected_sprite.id:
                    self.delete(selected_sprite.id)
                    selected_sprite.x = 0
                    selected_sprite.y = 0
                    selected_sprite.degree = 0
                    selected_sprite.photo = None
                    selected_sprite.image = None

                selected_sprite.x = event.x
                selected_sprite.y = event.y
                selected_sprite.degree = self._selected_ship_degree
                selected_sprite.image = self._ship_imgs[self._selected_ship_type][self._selected_ship_degree]
                selected_sprite.photo = self._ship_photos[self._selected_ship_type][self._selected_ship_degree]
                selected_sprite.id = self.create_image(
                    (event.x, event.y),
                    image=selected_sprite.photo,
                    anchor="center")

    def _on_shift_down(self, event: tkinter.Event) -> None:
        if self._mouse_btn1_down and self._has_ship_selected:
            ROTATION_DEGREE = 90

            if self._selected_ship_degree >= 360:
                self._selected_ship_degree = 0
            self._selected_ship_degree += ROTATION_DEGREE

            print('[SHIFT] Degree: {}'.format(self._selected_ship_degree))

            self._selected_ship_is_vertical = (self._selected_ship_degree == 0
                                               or self._selected_ship_degree == 180
                                               or self._selected_ship_degree == 360)

            if not self._ship_photos[self._selected_ship_type][self._selected_ship_degree]:
                BASE_DEGREE = 0
                self._ship_imgs[self._selected_ship_type][self._selected_ship_degree] = (
                    self._ship_imgs[self._selected_ship_type][BASE_DEGREE].rotate(self._selected_ship_degree, expand=True))

                self._ship_photos[self._selected_ship_type][self._selected_ship_degree] = (
                    ImageTk.PhotoImage(self._ship_imgs[self._selected_ship_type][self._selected_ship_degree]))

            selected_sprite = self._selected_ship.sprite
            if selected_sprite.id:
                    self.delete(selected_sprite.id)
                    selected_sprite.x = 0
                    selected_sprite.y = 0
                    selected_sprite.degree = 0
                    selected_sprite.photo = None
                    selected_sprite.image = None

            selected_sprite.x = event.x
            selected_sprite.y = event.y
            selected_sprite.degree = self._selected_ship_degree
            selected_sprite.image = self._ship_imgs[self._selected_ship_type][self._selected_ship_degree]
            selected_sprite.photo = self._ship_photos[self._selected_ship_type][self._selected_ship_degree]
            selected_sprite.id = self.create_image(
                (selected_sprite.x, selected_sprite.y),
                image=selected_sprite.photo,
                anchor="center")

    def _get_bay_ship_type(self, y: int) -> battleship.Ship:
        y_ratio = y / self.winfo_height()
        height = DEFAULT_HEIGHT

        patrolboat_y1_ratio = 0
        patrolboat_y2_ratio = DEFAULT_PATROLBOAT_Y2 / height
        battleship_y1_ratio = DEFAULT_BATTLESHIP_Y1 / height
        battleship_y2_ratio = DEFAULT_BATTLESHIP_Y2 / height
        submarine_y1_ratio = DEFAULT_SUBMARINE_Y1 / height
        submarine_y2_ratio = DEFAULT_SUBMARINE_Y2 / height
        carrier_y1_ratio = DEFAULT_CARRIER_Y1 / height
        carrier_y2_ratio = DEFAULT_CARRIER_Y2 / height
        destroyer_y1_ratio = DEFAULT_DESTROYER_Y1 / height
        destroyer_y2_ratio = DEFAULT_DESTROYER_Y2 / height

        if y_ratio >= patrolboat_y1_ratio and y_ratio <= patrolboat_y2_ratio:
            return battleship.PatrolBoat
        if y_ratio >= battleship_y1_ratio and y_ratio <= battleship_y2_ratio:
            return battleship.BattleShip
        if y_ratio >= submarine_y1_ratio and y_ratio <= submarine_y2_ratio:
            return battleship.Submarine
        if y_ratio >= carrier_y1_ratio and y_ratio <= carrier_y2_ratio:
            return battleship.Carrier
        if y_ratio >= destroyer_y1_ratio and y_ratio <= destroyer_y2_ratio:
            return battleship.Destroyer

        return None


import scrapy
import re
from competition.items import CompetitionItem

class CiasiSpider(scrapy.Spider):
    name = 'ciasi'
    allowed_domains = ['ciasi.org.cn']
    # start_urls = ['http://www.ciasi.org.cn/Home/safety/index?sid=15&bid=&cid=&sss=1&year=51,50']
    start_urls = ['http://www.ciasi.org.cn/Home/safety/index?sid=15&bid=&cid=&sss=1&year=52,51,50,49']

    def parse(self, response):
        list_item = response.xpath("//div[@class='eval_by_item']")
        for item in list_item:
            items = CompetitionItem()
            next_url = item.xpath("./a/@href").extract_first()
            brand = item.xpath("./a/div[@class='ev_i_brand']/p/text()").extract_first()
            menu = item.xpath("./a/div[@class='ev_i_manu']/div/p/text()").extract_first()
            models = item.xpath("./a/div[@class='ev_i_models']/div/p/text()").extract_first()
            level = item.xpath("./a/div[@class='ev_i_level']/div/p/text()").extract_first()
            model = item.xpath("./a/div[@class='ev_i_model']/div/p/text()").extract_first()
            items['brand'] = brand
            items['menu'] = menu
            items['models'] = models
            items['level'] = level
            items['model'] = model
            items['l_safe'] = ''
            items['r_pro'] = ''
            items['b_eval'] = ''
            # yield items
            if next_url is not None:
                next_url = 'http://www.ciasi.org.cn/' + next_url
                yield scrapy.Request(
                    next_url,
                    callback= self.parse_detail,
                    meta = {'item': items}
                )

    def parse_detail(self,response):
        # TODO 主页数据
        main_item = response.meta['item']
        # TODO 左侧数据
        pur_list = response.xpath("//div[@class='pur_le_item']")
        safe_pur_list = {}
        for pur in pur_list:
            title_txt = pur.xpath("./div[1]/p/text()").extract_first()
            if title_txt is not None:
                img_src = pur.xpath("./div[2]/div/img/@src").extract_first()
                img_stat = str(img_src).split('/')[-1]
                if img_stat == 'icon-greenDi.png':
                    img_stat = '车辆标配'
                elif img_stat == 'icon-radCa.png':
                    img_stat = '车辆未配备'
                elif img_stat == 'icon-yellowQu.png':
                    img_stat = '车辆选配'
                safe_pur_list[title_txt] = img_stat
        main_item['l_safe'] = safe_pur_list

        # TODO 右侧数据
        pro_index_list = []
        main_list = response.xpath("//tr[contains(@class,'pur_hd_')]")
        for i in main_list:
            right_title = i.xpath(".//div[@class='pr_e_lt']/p/text()").extract_first()
            right_result = i.xpath(".//div[@class='ev_i_bs']/span/text()").extract_first()
            pro_index_list.append({right_title:right_result,"detail": {}})
        if len(pro_index_list) > 0:
            count = 0
            for cls in ["co_p_one","co_p_two","co_p_san","co_p_si"]:
                one_item = {}
                for one in response.xpath("//tr[@class='{}']".format(cls)):
                    one_title = one.xpath(".//div[@class='pr_t_xt']/p/text()").extract_first()
                    one_result = one.xpath(".//div[@class='co_pu_s']/span/text()").extract_first()
                    one_item[one_title] = one_result
                pro_index_list[count]["detail"] = one_item
                count += 1
        elif len(pro_index_list) == 0:
            main_title_list = response.xpath("//div[@class='pr_e_lt']/p/text()").extract()
            main_price_list = response.xpath("//div[@class='ev_i_bs']/span/text()").extract()
            item_title_list = response.xpath("//div[@class='pr_t_xt']/p/text()").extract()
            item_price_list = response.xpath("//div[@class='co_pu_s']/span/text()").extract()
            pro_list = []
            for ti,pr in zip(main_title_list,main_price_list):
                _item = {ti: pr,'detail':{}}
                pro_list.append(_item)

            pro_list[0]['detail'] = {item_title_list[0]:item_price_list[0]}
            pro_list[1]['detail'] = {t:p for t,p in zip(item_title_list[1:4],item_price_list[1:4])}
            pro_list[2]['detail'] = {item_title_list[5]:item_price_list[5]}
            pro_list[3]['detail'] = {item_title_list[6]:item_price_list[6]}
            pro_index_list += pro_list

        main_item['r_pro'] = pro_index_list

        #TODO 下层数据
        evaluation_details = response.xpath("//div[@class='pa_t_ds']/p/text() | //td[@class='p_h_les']/div//p/text()").extract()
        evaluation_price = response.xpath("//div[@class='pa_t_bz']/span/text() | //div[@class='pa_t_bz']/div[@class='pa_i_rg']/span/text()").extract()

        evaluation = [{de:pr} for de,pr in zip(evaluation_details,evaluation_price)]

        table_list = response.xpath("//div[@class='par_p_block']//table")
        eval_table_data = []
        price_image = table_list[0].xpath(".//div[@class='pa_i_rg']//img/@src").extract_first()
        for index,table in enumerate(table_list):
            title_list = table.xpath(".//div[@class='pa_i_le' or @class='pa_i_xl']/p/text()").extract()
            price_list = table.xpath(".//div[@class='pa_i_rg' or @class='co_pu_s']/span/text()").extract()
            price_image = str(price_image).split('/')[-1]
            if price_image == 'icon-greenDi.png':
                price_image = '气囊未起爆'
            elif price_image == 'icon-radCa.png':
                price_image = '气囊起爆'
            if title_list[0] == '正面碰撞得分（满分30分）':
                price_list.append(price_image)

            _table_data = [{title:price} for title,price in zip(title_list,price_list)]
            eval_table_data += _table_data
        price_car = response.xpath("//div[@class='pa_bt_le']/span/text()").extract_first()
        evaluation = evaluation + eval_table_data
        evaluation.append({'price':price_car})
        main_item['b_eval'] = evaluation

        price = response.xpath("//div[@class='pa_t_bt']/div[@class='pa_bt_le']/span/text()").extract_first()
        price = re.findall(r"\d+\.?\d*",price)
        main_item['price'] = price

        yield main_item
        # //div[@class="par_p_block"]//table//div[@class='pa_i_le' or @class='pa_i_xl']/p


#!/usr/bin/python3
#
# Script for dumping/programming SPI flash chips with Hydrabus.
# Based on HydraBus BBIO documentation: https://github.com/hydrabus/hydrafw/wiki/HydraFW-Binary-SPI-mode-guide
#
# Author: MrKalach [https://github.com/MrKalach]
# License: GPLv3 (https://choosealicense.com/licenses/gpl-3.0/)
#

import hexdump
import serial
import sys
import argparse

class Params():
    serial_port     = 'COM4'
    serial_speed    = 115200

    block_size      = 0x1000      # max_buffer (HydraBus limitation)
    spi             = 1
    polarity        = 0
    clock_phase     = 0

    SPI_SPEED_TABLE = {
        "SPI1" : {
            "320k"  : 0b01100000,
            "650k"  : 0b01100001,
            "1.31m" : 0b01100010,
            "2.62m" : 0b01100011,
            "5.25m" : 0b01100100,
            "10.5m" : 0b01100101,
            "21m"   : 0b01100110,
            "42m"   : 0b01100111,
        },
        "SPI2" : {
            "160k"  : 0b01100000,
            "320k"  : 0b01100001,
            "650k"  : 0b01100010,
            "1.31m" : 0b01100011,
            "2.62m" : 0b01100100,
            "5.25m" : 0b01100101,
            "10.5m" : 0b01100110,
            "21m"   : 0b01100111,
        }
    }

    SPI_speed = 0b01100110

def check_result(result, expected, error_str):
    assert expected in result, f'{error_str}: expected={expected} != result={result}'

class SPI_hydra:
    def __init__(self, params):
        self.serial = None
        self.params = params

    def __enter__(self):
        self.serial = serial.Serial(self.params.serial_port, self.params.serial_speed)

        # Switching HydraBus to binary mode
        for _ in range(20):
            self.serial.write(b'\x00')
        check_result(b"BBIO1", self.serial.read(5), 'Could not switch into binary mode!')

        self.serial.reset_input_buffer()

        # Sitching to SPI mode
        self.write_bytes(0b00000001)
        check_result(b"SPI1", self.serial.read(4), 'Could not switch to SPI mode')

        # Configuring SPI
        cfg = 0b10000000 | self.params.polarity << 3 | self.params.clock_phase << 2 | self.params.spi
        self.write_bytes(cfg) #polarity => 0, phase => 0, SPI1
        check_result(b'\x01', self.serial.read(1),'Could not setup SPI port!')

        # Setting up SPI speed
        self.write_bytes(self.params.SPI_speed)
        check_result(b'\x01', self.serial.read(1), 'Could not setup SPI speed!')

        self.cs_off()

        return self

    def __exit__(self, type, value, traceback):
        # Switch HydraBus back to terminal mode
        self.serial.write(b'\x00')
        self.serial.write(b'\x0F')

    def write_bytes(self, data):
        if not isinstance(data, list) and not isinstance(data, bytes):
            data = [data]
        self.serial.write(data)

    def read(self, num):
        return self.serial.read(num)

    def cs_on(self):
        self.write_bytes(0b00000011)
        check_result(b'\x01', self.serial.read(1), 'Cannot switch CS to on!')

    def cs_off(self):
        self.write_bytes(0b00000010)
        check_result(b'\x01', self.serial.read(1), 'Cannot switch CS to off!')

##############################################################################################################################

def num_to_bytes(num, padding):
    return num.to_bytes(padding, byteorder='big')

def dump_chip_id(params):
    with SPI_hydra(params) as hydra:
        print("Getting chip manufacturer id ...")

        # 0b00000100 - write then read (with CS pinning)
        hydra.write_bytes([0b00000100, 0x00, 0x01, 0x00, 0x03])
        # send RDID command
        hydra.write_bytes(0x9f)

        check_result(b'\x01', hydra.read(1), 'Error occuried while getting chip id!')
        result = hydra.read(3)

        print(f'Chip manufacturer id: {hexdump.dump(result)}')

def dump_flash(params, filename, blocks, start_addr_hex):
    start_addr = int(start_addr_hex, 16)

    with SPI_hydra(params) as hydra:
        print('Start dumping ...')
        print(f'Reading blocks: ', end='')

        block = 0
        buf = bytearray()

        while block < blocks:
            # write-then-read: \x00\x04 - input size
            hydra.write_bytes(b'\x04\x00\x04' + num_to_bytes(params.block_size, 2))

            # read command (\x03) and 3 bytes of address
            hydra.write_bytes(b'\x03' + num_to_bytes(start_addr, 3))

            check_result(b'\x01', hydra.read(1), 'Error occurred while dumping!')

            buf += hydra.read(params.block_size)

            if (block % 10) == 0:
                print(block, end='')
            else:
                print('.', end='')

            block += 1
            start_addr += params.block_size

        with open(filename, 'wb+') as f:
            f.write(buf)

        print('\nDone')

# This code has been proofed && worked with Macronix MX25L12845E chip
# But somekind of generic commands is used, so it should work for most of other chips
def program_flash(params, filename, start_addr_hex, erase_before_program):
    MAX_ATTEMPTS = 30

    def enable_write():
        # Enabling write
        attempts = 0
        status = 0
        while status & 0b11 != 0b10:
            # WREN
            hydra.write_bytes(b'\x04\x00\x01\x00\x00')
            hydra.write_bytes(0x06)
            check_result(b'\x01', hydra.read(1), 'Error occurred while sending WREN!')

            # RDSR
            hydra.write_bytes(b'\x04\x00\x01\x00\x01')
            hydra.write_bytes(0x05)
            check_result(b'\x01', hydra.read(1), 'Error occurred while sending RDSR!')

            status = hydra.read(1)[0]

            if status & (1 << 7):
                assert 'Chip has a write protection!'

            attempts += 1
            if attempts > MAX_ATTEMPTS:
                assert 'Cannot set WREN!'

    def check_fail():
        # RDSCUR to check P_FAIL and E_FAIL
        hydra.write_bytes(b'\x04\x00\x01\x00\x01')
        hydra.write_bytes(0x28)
        check_result(b'\x01', hydra.read(1), 'Error occurred while sending RDSCUR!')

        status = hydra.read(1)[0]
        if status & 0x01100000 != 0: # check P_FAIL && E_FAIL
            # CLSR - clear SR Fail Register
            hydra.write_bytes(b'\x04\x00\x01\x00\x01')
            hydra.write_bytes(0x30)
            check_result(b'\x01', hydra.read(1), 'Error occurred while sending RDSCUR!')

            assert f'P_FAIL or E_FAIL: register={bin(status)}'

    def erase_sector_4k(addr):
        enable_write()

        # Erase sector/block
        # SE - sector erase, 0x20 + 3 bytes of address
        hydra.write_bytes(b'\x04\x00\x04\x00\x00')
        hydra.write_bytes(b'\x20' + num_to_bytes(start_addr, 3)) # CE - chip erase, can be used here
        check_result(b'\x01', hydra.read(1), 'Error occurred while sending SE!')

        # Check status
        status = 1
        attempts = 0
        while status & 0b1 != 0: #write in progress bit check
            # RDSR
            hydra.write_bytes(b'\x04\x00\x01\x00\x01')
            hydra.write_bytes(0x05)
            check_result(b'\x01', hydra.read(1), 'Error occurred while sending RDSR!')

            status = hydra.read(1)[0]

            attempts += 1
            if attempts > MAX_ATTEMPTS:
                assert 'Cannot read status RDSR!'

        check_fail()

    def write_page(page, data):
        if len(data) != 0x100:
            data = data + b'\x00' * (0x100 - len(data))
        assert len(data) == 0x100, f'Somthing goes wrong, data size is not 0x100 => {len(data)}'

        enable_write()

        # Program data
        # PP - page program, 0x02 + 3 bytes of address + data
        # low byte of address is always 0x00
        hydra.write_bytes(b'\x04\x01\x04\x00\x00')
        hydra.write_bytes(b'\x02' + num_to_bytes(page, 2) + b'\x00')
        hydra.write_bytes(data)
        check_result(b'\x01', hydra.read(1), 'Error occurred while sending PP!')

        # Check status
        status = 1
        attempts = 0
        while status & 0b1 != 0: #write in progress bit checking
            # RDSR
            hydra.write_bytes(b'\x04\x00\x01\x00\x01')
            hydra.write_bytes(0x05)
            check_result(b'\x01', hydra.read(1), 'Error occurred while sending RDSR!')

            status = hydra.read(1)[0]

            attempts += 1
            if attempts > MAX_ATTEMPTS:
                assert 'Cannot read status RDSR!'

        check_fail()

    start_addr = int(start_addr_hex, 16)
    assert start_addr & 0x1FF == 0, f'In program mode start address has to be aligned (0x1FF bytes boundary). start address = {start_addr}'

    print('Starting programming...')
    print('Blocks:', end='')
    page = 0
    with SPI_hydra(params) as hydra:
        with open(filename, 'rb') as f:
            while True:
                data = f.read(0x100)
                if len(data) == 0:
                    break

                if page % 0xF == 0:
                    if erase_before_program:
                        erase_sector_4k(start_addr)
                    start_addr += 0x1000
                    block_number = int(start_addr / 0x1000)
                    if block_number % 10 == 0:
                        print(block_number, end='')
                    else:
                        print('.', end='')

                write_page(page, data)
                page += 1

    print('\nDone.')

def main():
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '-hsp', '--hydra-serial-port',
        type=str, default=Params.serial_port,
        help='Hydra COM port (eg. COM4 or /dev/ttyS0)'
    )
    parser.add_argument(
        '-hss', '--hydra-serial-speed',
        type=int, default=Params.serial_speed,
        help='Hydra COM port speed'
    )
    parser.add_argument(
        '-bs', '--block-size',
        type=int, default=Params.block_size,
        help='Max size of data block for SPI, value should be in range (0, 4096]'
    )

    parser.add_argument(
        '-spi', '--spi-port',
        type=str, default='SPI2' if Params.spi == 0 else 'SPI1',
        help='SPI port',
        choices=['SPI1', 'SPI2']
    )

    parser.add_argument(
        '-ss', '--spi-speed',
        type=str, default='21m',
        help=f'''
            SPI speed (
                SPI1: {",".join(Params.SPI_SPEED_TABLE["SPI1"].keys())}
                SPI2: {",".join(Params.SPI_SPEED_TABLE["SPI2"].keys())}
            )
        ''',
    )

    parser.add_argument(
        '-sp', '--spi-polarity',
        type=int, default=Params.polarity,
        help=f'SPI polarity',
        choices=[0, 1]
    )

    parser.add_argument(
        '-scph', '--spi-clock-phase',
        type=int, default=Params.clock_phase,
        help=f'SPI clock phase',
        choices=[0, 1]
    )

    subparsers = parser.add_subparsers(dest='action', required=True)

    subparsers.add_parser('chip-id', help='Get manufacturer chip id')

    dump_parser = subparsers.add_parser('dump', help='Dump flash into file')
    dump_parser.add_argument('filename', type=str, help='File to store dump')
    dump_parser.add_argument('blocks', type=int, help='Blocks to read')
    dump_parser.add_argument('start_address', type=str, help='Start address (HEX)')

    burn_parser = subparsers.add_parser('program', help='Program img into flash')
    burn_parser.add_argument('filename', type=str, help='File to program')
    burn_parser.add_argument('start_address', type=str, help='Start address (HEX)')
    burn_parser.add_argument('-ebw', '--erase_before_program', action='store_true', help='Erase data before program')

    try:
        options = parser.parse_args()
        params = Params()
        params.serial_port = options.hydra_serial_port
        params.serial_speed = options.hydra_serial_speed
        if options.block_size < 1 or options.block_size > 0x1000:
            print(f'Invalid block size {options.block_size}! Value should be in range (1, 4096]')
            exit()
        params.block_size = options.block_size
        params.spi = {"SPI1" : 1, "SPI2" : 0}[options.spi_port]
        if options.spi_speed not in Params.SPI_SPEED_TABLE[options.spi_port]:
            print(f'Wrong speed({options.spi_speed}) for this({options.spi_port}) port!')
            exit()

        params.SPI_speed = Params.SPI_SPEED_TABLE[options.spi_port][options.spi_speed]
        params.polarity = options.spi_polarity
        params.clock_phase = options.spi_clock_phase

        if options.action == 'chip-id':
            dump_chip_id(params)
        elif options.action == 'dump':
            dump_flash(params, options.filename, options.blocks, options.start_address)
        elif options.action == 'program':
            program_flash(params, options.filename, options.start_address, options.erase_before_program)

    except SystemExit:
        print()
        parser.print_help()
        sys.exit(0)

if __name__ == '__main__':
    main()


import spacy
import re
import pickle
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import MultinomialNB
from sklearn.neural_network import MLPClassifier
from sklearn.linear_model import SGDClassifier
from sklearn.metrics import classification_report
from sklearn.pipeline import Pipeline
from sklearn.decomposition import TruncatedSVD
from gensim.models import Word2Vec
import numpy as np

nlp = spacy.load("en_core_web_sm")

def lematizar_documento(ruta_doc, nombre_archivo_salida):
    try:
        archivo_df = open(ruta_doc, 'rb')
        df = pickle.load(archivo_df)

        for i in range(len(df)):
            tokens = nlp(df.loc[i, 'doc'])
            lista_lemmas = []
            for t in tokens:
                lista_lemmas.append(t.lemma_)
            df.loc[i, 'doc'] = " ".join(lista_lemmas)

        salida = open(nombre_archivo_salida, 'wb')
        pickle.dump(df, salida)

        archivo_df.close()
        salida.close()
    except FileNotFoundError:
        print("No se encontro el archivo")

def quitar_sw_documento(ruta_doc, nombre_archivo_salida):
    try:
        archivo_df = open(ruta_doc, 'rb')
        df = pickle.load(archivo_df)

        for i in range(len(df)):
            tokens = nlp(df.loc[i, 'doc'])
            lista_palabras = []
            for t in tokens:
                if not t.is_stop:  # and t.pos_ != "DET" and t.pos_ != "ADP" and t.pos_ != "CONJ" and t.pos_ != "PRON":
                    lista_palabras.append(t.text)
            texto = " ".join(lista_palabras)
            texto = re.sub('\s+', ' ', texto)
            texto = texto.strip()
            df.loc[i, 'doc'] = texto

        salida = open(nombre_archivo_salida, 'wb')
        pickle.dump(df, salida)
        print(df.loc[0, 'doc'])
        archivo_df.close()
        salida.close()
    except FileNotFoundError:
        print("No se encontro el archivo")

def limpia_texto(ruta_doc, nombre_archivo_salida):
    try:
        archivo_df = open(ruta_doc, 'rb')
        df = pickle.load(archivo_df)

        for i in range(len(df)):
            tokens = nlp(df.loc[i, 'doc'])
            lista_palabras = []
            for t in tokens:
                if not t.is_punct:
                    lista_palabras.append(t.text)
            texto = " ".join(lista_palabras)
            texto = re.sub('\s+', ' ', texto)
            texto = texto.strip()
            df.loc[i, 'doc'] = texto

        salida = open(nombre_archivo_salida, 'wb')
        pickle.dump(df, salida)
        print(df.loc[0, 'doc'])
        archivo_df.close()
        salida.close()
    except FileNotFoundError:
        print("No se encontro el archivo")

# Normalizacion combinaciones :
# quitar_sw_documento("test.pkl", "test_nsw.pkl")
# quitar_sw_documento("train.pkl", "train_nsw.pkl")

# lematizar_documento("test.pkl", "test_lemma.pkl")
# lematizar_documento("train.pkl", "train_lemma.pkl")

# limpia_texto('test.pkl','test_limp.pkl')
# limpia_texto('train.pkl','train_limp.pkl')

# lematizar_documento("test_nsw.pkl","test_nsw_lemma.pkl")
# lematizar_documento("train_nsw.pkl","train_nsw_lemma.pkl")

# quitar_sw_documento("test_lemma.pkl","test_lemma_nsw.pkl")
# quitar_sw_documento("train_lemma.pkl","train_lemma_nsw.pkl")

# limpia_texto('test_nsw.pkl','test_nsw_limp.pkl')
# limpia_texto('train_nsw.pkl','train_nsw_limp.pkl')

# lematizar_documento("test_limp.pkl","test_limp_lemma.pkl")
# lematizar_documento("train_limp.pkl","train_limp_lemma.pkl")

# lematizar_documento("test_nsw_limp.pkl","test_nsw_limp_lemma.pkl")
# lematizar_documento("train_nsw_limp.pkl","train_nsw_limp_lemma.pkl")

def get_x_y_data(ruta_doc):
    try:
        archivo_df = open(ruta_doc, 'rb')
        df = pickle.load(archivo_df)
        data = df['doc']
        target = df['label']
        archivo_df.close()

        return data, target
    except FileNotFoundError:
        print("No se encontro el archivo")

def rep_vec(data_train, data_test, vectorizer):
    vectors_train = vectorizer.fit_transform(data_train)
    vectors_test = vectorizer.transform(data_test)
    print(vectorizer.get_feature_names_out())
    print(len(vectorizer.get_feature_names_out()))
    return vectors_train, vectors_test

def get_model(route_train):
    X_train, y_train = get_x_y_data(route_train)
    sentences = [sentence.lower().split() for sentence in X_train]
    model = Word2Vec(sentences, vector_size = 300, window = 16, min_count = 5, workers = 4)
    # workers = number of threads

    return model

def vectorize_embedding(sentence, w2v_model):
    words = sentence.split()
    words_vecs = [w2v_model.wv[word] for word in words if word in w2v_model.wv]
    if len(words_vecs) == 0:
        return np.zeros(300)
    words_vecs = np.array(words_vecs)
    return words_vecs.mean(axis=0)

def classify(clf, route_train, route_test, vectorizer=None):
    X_train, y_train = get_x_y_data(route_train)
    X_test, y_test = get_x_y_data(route_test)

    if vectorizer != None:
        vectors_train, vectors_test = rep_vec(X_train, X_test, vectorizer)
        clf.fit(vectors_train, y_train)
        y_pred = clf.predict(vectors_test)
    else:
        model = get_model(route_train)
        X_train = np.array([vectorize_embedding(sentence.lower(), model) for sentence in X_train])
        X_test = np.array([vectorize_embedding(sentence.lower(), model) for sentence in X_test])
        clf.fit(X_train, y_train)
        y_pred = clf.predict(X_test)
    print(y_pred)
    print(classification_report(y_test, y_pred))

def classify_svd(clf, route_train, route_test, vectorizer):
    X_train, y_train = get_x_y_data(route_train)
    X_test, y_test = get_x_y_data(route_test)
    pipe = Pipeline([('text_representation', vectorizer), ('dimensionality_reduction', TruncatedSVD(300)),
                     ('classifier', clf)])
    pipe.set_params(dimensionality_reduction__n_components = 1000)
    print(pipe)
    pipe.fit(X_train, y_train)
    y_pred = pipe.predict(X_test)
    print(classification_report(y_test, y_pred))

vectorizer_bin = CountVectorizer(binary=True)
vectorizer_freq = CountVectorizer()
vectorizer_tfidf = TfidfVectorizer()

clf_NB = MultinomialNB()
clf_LR = LogisticRegression(max_iter = 300)
clf_MLPC = MLPClassifier()
clf_SGD = SGDClassifier()

# Pruebas con los clasificadores:

print()
print()
print("No Stop Words + lemmatization : tfidf , SGD")
classify(clf_SGD, 'train_nsw_lemma.pkl', 'test_nsw_lemma.pkl', vectorizer_tfidf)
print()
print("No Stop Words + clean text + lemmatization : tfidf , SGD")
classify(clf_SGD, 'train_nsw_limp_lemma.pkl', 'test_nsw_limp_lemma.pkl', vectorizer_tfidf)

print()
print()
print("No Stop Words + lemmatization : tfidf , SGD , SVD")
classify_svd(clf_SGD, 'train_nsw_lemma.pkl', 'test_nsw_lemma.pkl', vectorizer_tfidf)
print()
print("No Stop Words + clean text + lemmatization : tfidf , SGD , SVD")
classify_svd(clf_SGD, 'train_nsw_limp_lemma.pkl', 'test_nsw_limp_lemma.pkl', vectorizer_tfidf)


"""Script that starts a P300 Speller. Run with 'python p300_speller' to show config window.

Default configuration loaded at startup is stored in /config_files/default.cfg. Creates an LSL stream of type
'P300_Marker' with one channel of 'int8' sending a marker every time an image flashes.

The script consists of three main classes.
ConfigParams: Stores all config parameters that are set in the configuration GUI
MainWindow: The main configuration window, launched at startup
P300Window: All logic concerning the Image flashing window. E.g. the flash-sequence is generated here.
"""

import configparser
import glob
import os
from collections import deque
from tkinter import (
    EW,
    IntVar,
    Radiobutton,
    StringVar,
    Text,
    Tk,
    Toplevel,
    W,
    filedialog,
)
from tkinter.ttk import Button, Entry, Frame, Label

import numpy as np
from PIL import Image, ImageTk
from pylsl import IRREGULAR_RATE, StreamInfo, StreamOutlet, local_clock

MAX_FLASHES = 10000  # Maximum number of flashed images. Window will stop afterwards

class ConfigParams(object):
    """Stores all parameters that can be set in the MainWindow. Acts as model in MVC pattern."""

    def __init__(self):
        self.config_parser = configparser.RawConfigParser()

        # GUI Parameters
        self.imagesize = IntVar()
        self.config_file_path = StringVar()
        self.images_folder_path = StringVar()
        self.flash_image_path = StringVar()
        self.number_of_rows = IntVar()
        self.number_of_columns = IntVar()
        self.lsl_streamname = StringVar()
        self.flash_mode = IntVar()
        self.flash_duration = IntVar()
        self.break_duration = IntVar()

        # Default values
        self.config_file_path.set(os.path.join(os.path.dirname(__file__), "conf_files/default.cfg"))

        try:
            self.read_from_file()
        except configparser.NoSectionError:
            print("Config file {} not found".format(self.config_file_path.get()))

    def save_to_file(self):
        """Saves the current configuration to self.config_file_path"""
        try:
            self.config_parser.add_section("Parameters")
        except configparser.DuplicateSectionError:
            pass
        self.config_parser.set("Parameters", "Break Duration", self.break_duration.get())
        self.config_parser.set("Parameters", "Flash Duration", self.flash_duration.get())
        self.config_parser.set("Parameters", "Imagesize", self.imagesize.get())
        self.config_parser.set("Parameters", "Flash Mode", self.flash_mode.get())
        self.config_parser.set("Parameters", "LSL streamname", self.lsl_streamname.get())
        self.config_parser.set("Parameters", "Number of Rows", self.number_of_rows.get())
        self.config_parser.set("Parameters", "Number of Columns", self.number_of_columns.get())
        self.config_parser.set("Parameters", "Flash image path", self.flash_image_path.get())
        self.config_parser.set("Parameters", "Images Folder Path", self.images_folder_path.get())

        # Writing our configuration file to 'example.cfg'
        with open(self.config_file_path.get(), "w") as configfile:
            self.config_parser.write(configfile)

    def read_from_file(self):
        """Loads all configuration parameters from self.config_file_path"""
        self.config_parser.read(self.config_file_path.get())

        images_folder_fallback = os.path.join(os.path.dirname(__file__), "number_images")
        flash_image_fallback = os.path.join(os.path.dirname(__file__), "flash_images", "einstein.jpg")

        self.imagesize.set(self.config_parser.getint("Parameters", "Imagesize"))
        self.images_folder_path.set(
            self.config_parser.get("Parameters", "Images Folder Path", fallback=images_folder_fallback)
        )
        self.flash_image_path.set(
            self.config_parser.get("Parameters", "Flash image path", fallback=flash_image_fallback)
        )
        self.number_of_rows.set(self.config_parser.getint("Parameters", "Number of Rows"))
        self.number_of_columns.set(self.config_parser.getint("Parameters", "Number of Columns"))
        self.lsl_streamname.set(self.config_parser.get("Parameters", "LSL Streamname"))
        self.flash_mode.set(self.config_parser.getint("Parameters", "Flash Mode"))
        self.flash_duration.set(self.config_parser.getint("Parameters", "Flash duration"))
        self.break_duration.set(self.config_parser.getint("Parameters", "Break duration"))

class MainWindow(object):
    """Handles all the configuration and starts flashing window

    Args:
        master: Tkinter root window

    """

    def __init__(self, master: Tk):
        self.master = master
        master.title("P300 speller configuration")

        self.p300_window = None

        # Variables
        self.usable_images = []
        self.image_labels = []
        self.flash_sequence = []
        self.flash_image = None
        self.sequence_number = 0
        self.lsl_output = None

        self.config = ConfigParams()

        # Widget definition
        self.changeable_widgets = []

        self.config_file_label = Label(self.master, text="Config File:")
        self.config_file_label.grid(row=0, column=0)

        self.config_file_entry = Entry(self.master, textvariable=self.config.config_file_path)
        self.config_file_entry.grid(row=0, column=1, sticky=EW)
        self.changeable_widgets.append(self.config_file_entry)

        self.open_conf_btn = Button(
            self.master,
            text="Open config file",
            command=lambda: self.open_file_update_entry(self.config.config_file_path),
        )
        self.open_conf_btn.grid(row=0, column=2, sticky=EW)
        self.changeable_widgets.append(self.open_conf_btn)

        self.use_conf_btn = Button(self.master, text="Apply", command=self.config.read_from_file)
        self.use_conf_btn.grid(row=0, column=3)
        self.changeable_widgets.append(self.use_conf_btn)

        self.save_settings_btn = Button(self.master, text="Save", command=self.config.save_to_file)
        self.save_settings_btn.grid(row=0, column=4)
        self.changeable_widgets.append(self.save_settings_btn)

        self.images_folder_label = Label(self.master, text="Images folder:")
        self.images_folder_label.grid(row=1, column=0)

        self.images_folder_entry = Entry(self.master, textvariable=self.config.images_folder_path)
        self.images_folder_entry.grid(row=1, column=1, sticky=EW)
        self.changeable_widgets.append(self.images_folder_entry)

        self.open_images_dir_btn = Button(
            self.master,
            text="Open image folder",
            command=lambda: self.open_folder_update_entry(self.config.images_folder_path),
        )
        self.open_images_dir_btn.grid(row=1, column=2, sticky=EW)
        self.changeable_widgets.append(self.open_images_dir_btn)

        self.flash_image_label = Label(self.master, text="Flash image:")
        self.flash_image_label.grid(row=2, column=0)

        self.flash_image_file_entry = Entry(self.master, textvariable=self.config.flash_image_path)
        self.flash_image_file_entry.grid(row=2, column=1, sticky=EW)
        self.changeable_widgets.append(self.flash_image_file_entry)

        self.open_flash_dir_btn = Button(
            self.master, text="Open image", command=lambda: self.open_file_update_entry(self.config.flash_image_path)
        )
        self.open_flash_dir_btn.grid(row=2, column=2, sticky=EW)
        self.changeable_widgets.append(self.open_flash_dir_btn)

        self.imagesize_label = Label(self.master, text="Imagesize (px):")
        self.imagesize_label.grid(row=3, column=0)

        self.imagesize_entry = Entry(self.master, textvariable=self.config.imagesize)
        self.imagesize_entry.grid(row=3, column=1, sticky=W)
        self.changeable_widgets.append(self.imagesize_entry)

        self.number_of_rows_label = Label(self.master, text="Number of rows:")
        self.number_of_rows_label.grid(row=4, column=0)

        self.number_of_rows_entry = Entry(self.master, textvariable=self.config.number_of_rows)
        self.number_of_rows_entry.grid(row=4, column=1, sticky=W)
        self.changeable_widgets.append(self.number_of_rows_entry)

        self.number_of_columns_label = Label(self.master, text="Number of columns:")
        self.number_of_columns_label.grid(row=5, column=0)

        self.number_of_columns_entry = Entry(self.master, textvariable=self.config.number_of_columns)
        self.number_of_columns_entry.grid(row=5, column=1, sticky=W)
        self.changeable_widgets.append(self.number_of_columns_entry)

        self.lsl_streamname_label = Label(self.master, text="LSL Streamname:")
        self.lsl_streamname_label.grid(row=6, column=0)

        self.lsl_streamname_entry = Entry(self.master, textvariable=self.config.lsl_streamname)
        self.lsl_streamname_entry.grid(row=6, column=1, sticky=W)
        self.changeable_widgets.append(self.lsl_streamname_entry)

        self.flash_duration_label = Label(self.master, text="Flash duration (ms):")
        self.flash_duration_label.grid(row=7, column=0)

        self.flash_duration_entry = Entry(self.master, textvariable=self.config.flash_duration)
        self.flash_duration_entry.grid(row=7, column=1, sticky=W)
        self.changeable_widgets.append(self.flash_duration_entry)

        self.break_duration_label = Label(self.master, text="Break duration (ms):")
        self.break_duration_label.grid(row=8, column=0)

        self.break_duration_entry = Entry(self.master, textvariable=self.config.break_duration)
        self.break_duration_entry.grid(row=8, column=1, sticky=W)
        self.changeable_widgets.append(self.break_duration_entry)

        self.flash_mode_label = Label(self.master, text="Flashmode:")
        self.flash_mode_label.grid(row=9, column=0)

        self.flash_mode_1_rb = Radiobutton(
            self.master,
            text="Rows and Columns (Sequence not pseudorandom yet!)",
            variable=self.config.flash_mode,
            value=1,
        )
        self.flash_mode_1_rb.grid(row=9, column=1, sticky=W)
        self.changeable_widgets.append(self.flash_mode_1_rb)

        self.flash_mode_2_rb = Radiobutton(self.master, text="Single images", variable=self.config.flash_mode, value=2)
        self.flash_mode_2_rb.grid(row=10, column=1, sticky=W)
        self.changeable_widgets.append(self.flash_mode_2_rb)
        self.set_flash_mode_rbs()

        self.text_console = Text(self.master)
        self.text_console.grid(row=11, column=0, rowspan=4, columnspan=5)
        self.text_console.configure(state="disabled")

        self.close_button = Button(self.master, text="Close", command=master.quit)
        self.close_button.grid(row=15, column=0)

        self.open_button = Button(self.master, text="Open", command=self.open_p300_window)
        self.open_button.grid(row=15, column=3)
        self.changeable_widgets.append(self.open_button)

    def set_flash_mode_rbs(self):
        if self.config.flash_mode.get() == 1:
            self.flash_mode_1_rb.select()
        else:
            self.flash_mode_2_rb.select()

    def open_folder_update_entry(self, entry_var):
        new_path = filedialog.askdirectory()
        if new_path != "":
            entry_var.set(new_path)

    def open_file_update_entry(self, entry_var):
        new_path = filedialog.askopenfilename()
        if new_path != "":
            entry_var.set(new_path)

    def print_to_console(self, text_to_print):
        if not isinstance(text_to_print, str):
            text_to_print = str(text_to_print)

        self.text_console.configure(state="normal")
        self.text_console.insert("end", text_to_print + "\n")
        self.text_console.configure(state="disabled")

    def disable_all_widgets(self):
        for widget in self.changeable_widgets:
            widget.configure(state="disabled")
        self.master.iconify()

    def enable_all_widgets(self):
        for widget in self.changeable_widgets:
            widget.configure(state="normal")
        self.master.deiconify()

    def open_p300_window(self):
        p300_window_master = Toplevel(self.master)
        self.p300_window = P300Window(p300_window_master, self, self.config)
        self.disable_all_widgets()

class P300Window(object):
    """All logic for the image flashing window.

    Args:
        master: Tkinter Toplevel element
        parent: Parent that opened the window
        config: ConfigParams instance

    """

    def __init__(self, master: Toplevel, parent: MainWindow, config: ConfigParams):
        self.master = master
        self.parent = parent

        self.master.protocol("WM_DELETE_WINDOW", self.close_window)

        self.config = config
        self.running = 0

        self.image_labels = []
        self.sequence_number = 0
        self.lsl_output = None
        self.usable_images = []
        self.flash_sequence = []

        self.image_frame = Frame(self.master)
        self.image_frame.grid(
            row=0, column=0, rowspan=self.config.number_of_rows.get(), columnspan=self.config.number_of_columns.get()
        )

        self.start_btn_text = StringVar()
        self.start_btn_text.set("Start")
        self.start_btn = Button(self.master, textvariable=self.start_btn_text, command=self.start)
        self.start_btn.grid(row=self.config.number_of_rows.get() + 1, column=self.config.number_of_columns.get() - 1)

        self.pause_btn = Button(self.master, text="Pause", command=self.pause)
        self.pause_btn.grid(row=self.config.number_of_rows.get() + 1, column=self.config.number_of_columns.get() - 2)
        self.pause_btn.configure(state="disabled")

        self.close_btn = Button(self.master, text="Close", command=self.close_window)
        self.close_btn.grid(row=self.config.number_of_rows.get() + 1, column=0)

        # Initialization
        self.show_images()
        self.create_flash_sequence()
        self.lsl_output = self.create_lsl_output()

    def open_images(self):
        self.usable_images = []
        image_paths = glob.glob(os.path.join(self.config.images_folder_path.get(), "*.jpg"))
        png_images = glob.glob(os.path.join(self.config.images_folder_path.get(), "*.png"))
        for png_image in png_images:
            image_paths.append(png_image)
        min_number_of_images = self.config.number_of_columns.get() * self.config.number_of_rows.get()
        if len(image_paths) < min_number_of_images:
            self.parent.print_to_console("To few images in folder: " + self.config.images_folder_path.get())
            return

        # Convert and resize images
        for image_path in image_paths:
            image = Image.open(image_path)
            resized = image.resize((self.config.imagesize.get(), self.config.imagesize.get()), Image.ANTIALIAS)
            Tkimage = ImageTk.PhotoImage(resized)
            self.usable_images.append(Tkimage)

        flash_img = Image.open(self.config.flash_image_path.get())
        flash_img_res = flash_img.resize((self.config.imagesize.get(), self.config.imagesize.get()), Image.ANTIALIAS)
        self.flash_image = ImageTk.PhotoImage(flash_img_res)

    def show_images(self):
        self.open_images()

        if self.usable_images == []:
            self.parent.print_to_console("No images opened")
            return

        num_rows = self.config.number_of_rows.get()
        num_cols = self.config.number_of_columns.get()

        # Arrange images
        for r in range(0, num_rows):
            for c in range(0, num_cols):
                current_image = self.usable_images[r * num_cols + c]
                label = Label(self.image_frame, image=current_image)
                label.image = current_image
                label.grid(row=r, column=c)
                self.image_labels.append(label)

    def create_lsl_output(self):
        """Creates an LSL Stream outlet"""
        info = StreamInfo(
            name=self.config.lsl_streamname.get(),
            type="P300_Marker",
            channel_count=1,
            channel_format="int8",
            nominal_srate=IRREGULAR_RATE,
            source_id="marker_stream",
            handle=None,
        )

        if self.config.flash_mode == 1:
            info.desc().append_child_value("flash_mode", "Row and Column")
        elif self.config.flash_mode == 2:
            info.desc().append_child_value("flash_mode", "Single Value")

        info.desc().append_child_value("num_rows", str(self.config.number_of_rows.get()))
        info.desc().append_child_value("num_cols", str(self.config.number_of_columns.get()))

        return StreamOutlet(info)

    def create_flash_sequence(self):
        self.flash_sequence = []
        num_rows = self.config.number_of_rows.get()
        num_cols = self.config.number_of_columns.get()

        sequence_length = 700  # ms
        distance_between_similar_elements = int((sequence_length / self.config.break_duration.get()) + 1)

        if self.config.flash_mode.get() == 1:
            self.parent.print_to_console("CAUTION: Row and Column flash mode currently uses only random samples!")
            self.flash_sequence = np.random.randint(0, num_rows + num_cols, 3000)
        elif self.config.flash_mode.get() == 2:
            flash_sequence = []
            maximum_number = num_rows * num_cols

            if maximum_number * 0.7 < distance_between_similar_elements:
                self.parent.print_to_console("No sequence could be created because the break duration is too short")
                return

            number_buffer = deque(maxlen=distance_between_similar_elements)

            for _ in range(0, MAX_FLASHES):
                while True:
                    new_number = np.random.randint(0, maximum_number, 1)
                    if bool(number_buffer.count(new_number[0])) is False:
                        number_buffer.append(new_number[0])
                        flash_sequence.append(new_number[0])
                        break
            self.flash_sequence = flash_sequence

    def start(self):
        self.running = 1
        self.start_flashing()
        self.start_btn.configure(state="disabled")
        self.pause_btn.configure(state="normal")

    def pause(self):
        self.running = 0
        self.start_btn_text.set("Resume")
        self.start_btn.configure(state="normal")
        self.pause_btn.configure(state="disabled")

    def start_flashing(self):
        if self.sequence_number == len(self.flash_sequence):
            self.parent.print_to_console("All elements flashed")
            self.running = 0
            self.sequence_number = 0
            return

        if self.running == 0:
            self.parent.print_to_console("Flashing paused at sequence number " + str(self.sequence_number))
            return

        element_to_flash = self.flash_sequence[self.sequence_number]
        self.sequence_number = self.sequence_number + 1

        timestamp = local_clock()
        print([element_to_flash + 1], timestamp)
        self.lsl_output.push_sample([element_to_flash + 1], timestamp)  # add 1 to prevent 0 in markers

        if self.config.flash_mode.get() == 1:
            self.flash_row_or_col(element_to_flash)
        elif self.config.flash_mode.get() == 2:
            self.flash_single_element(element_to_flash)

        self.master.after(self.config.break_duration.get(), self.start_flashing)

    def change_image(self, label, img):
        label.configure(image=img)
        label.image = img

    def flash_row_or_col(self, rc_number):
        num_rows = self.config.number_of_rows.get()
        num_cols = self.config.number_of_columns.get()

        if rc_number < num_rows:
            for c in range(0, num_cols):
                cur_idx = rc_number * num_cols + c
                self.change_image(self.image_labels[cur_idx], self.flash_image)
        else:
            current_column = rc_number - num_rows
            for r in range(0, num_rows):
                cur_idx = current_column + r * num_cols
                self.change_image(self.image_labels[cur_idx], self.flash_image)

        self.master.after(self.config.flash_duration.get(), self.unflash_row_or_col, rc_number)

    def unflash_row_or_col(self, rc_number):
        num_rows = self.config.number_of_rows.get()
        num_cols = self.config.number_of_columns.get()
        if rc_number < num_rows:
            for c in range(0, num_cols):
                cur_idx = rc_number * num_cols + c
                self.change_image(self.image_labels[cur_idx], self.usable_images[cur_idx])
        else:
            current_column = rc_number - num_rows
            for r in range(0, num_rows):
                cur_idx = current_column + r * num_cols
                self.change_image(self.image_labels[cur_idx], self.usable_images[cur_idx])

    def flash_single_element(self, element_no):
        self.change_image(self.image_labels[element_no], self.flash_image)
        self.master.after(self.config.flash_duration.get(), self.unflash_single_element, element_no)

    def unflash_single_element(self, element_no):
        self.change_image(self.image_labels[element_no], self.usable_images[element_no])

    def close_window(self):
        self.parent.enable_all_widgets()
        self.master.destroy()

def main():
    from tkinter import Tk

    root = Tk()
    MainWindow(root)
    root.mainloop()


## objectives ##

# objective - build dashboard using 'OldFaithful.csv'
# display as a scatterplot
# D = data of recordings in month (August)
# X duration of current eruptions in minutes
# Y waiting time until the next eruption

import dash
import dash_html_components as html
import dash_core_components as dcc
import plotly.graph_objs as go
import numpy as np
import pandas as pd

df = pd.read_csv('C:/Users/eugen/OneDrive/Main_Env/udemy_dash_course/Data/OldFaithful.csv')

colors = {'background':'#111111', 'text':'#7fdbff'}

app = dash.Dash()

app.layout = html.Div(children=
                      [html.H1('Hello Dash!',
                               style={'textAlign': 'center', 'color': colors['text']}),
                       dcc.Graph(id='example',
                                 figure={'data': [go.Scatter(x=df['X'], y=df['Y']/60, mode='markers',
                                                  marker=dict(size=df['X'], color=df['Y'],
                                                              showscale=True,colorbar=dict(title='Time to Next Eruption')))],
                                                              'layout':go.Layout(title='Old Faithful Eruptions',
                                                            xaxis={'title': 'Duration of Eruption'},
                                                            yaxis={'title': 'Interval'})})])

if __name__ == '__main__':
    app.run_server()


from sklearn.base import BaseEstimator, TransformerMixin
import pandas as pd

from data_processing.helpers.check_if_nans_exist import check_if_nans_exist
from data_processing.helpers.columns_that_contain_lists import columns_that_contain_lists

class RemoveNan(BaseEstimator, TransformerMixin):
    def __init__(self, keep_nans_in_columns, suppress_output):
        self.keep_nans_in_columns = keep_nans_in_columns
        self.suppress_output = suppress_output

    def fit(self, dataset: pd.DataFrame, y=None):
        return self
    def transform(self, dataset: pd.DataFrame, y=None):
        """ This function removes all instances that have a NaN or None in all attributes that are not listed in the keep_nans_in_columns variable """
        print('Removing nans...')
        nans_exist = check_if_nans_exist(dataset, self.suppress_output)
        if nans_exist:
            all_columns = dataset.columns
            columns_with_lists = columns_that_contain_lists(dataset)
            columns_to_remove_nans_from = list(set(all_columns) - set(self.keep_nans_in_columns))
            # drop items with nan values
            dataset = dataset.dropna(subset=columns_to_remove_nans_from)
            # drop items with empty lists
            for column_with_lists in columns_with_lists:
                if column_with_lists in columns_to_remove_nans_from:
                    # drop empty items (empty e.g. length of list is zero)
                    dataset = dataset[dataset[column_with_lists].map(lambda d: len(d)) > 0]
        return dataset


from LoadData import *
import statsmodels.api as sm
import pandas as pd
import numpy as np
from diagnosticTests import *

data = loadAll() #just returns the database

data['GDP_lag1'] = data['GDP_perCap'].shift(1) #lag column for GDP variable
data['CO2_lag1'] = data['Annual_CO2_emissions_TperCap'].shift(1) #lag column for co2 variable

y=data[['Annual_CO2_emissions_TperCap']] #dependent variable

x=data[['GDP_perCap', 'GDP_lag1', 'CO2_lag1']] #regressors

x['dummy1989']=0 #dummy column
x['dummy2003']=0 #dummy columns
x.loc['1989', 'dummy1989']=1 #setting 1 for specific years....
x.loc['2003', 'dummy2003']=1

#x['GDP_lag1']=x['GDP_lag1'].fillna(0) #fixing na values
#x['CO2_lag1']=x['CO2_lag1'].fillna(0)

x=sm.add_constant(x)

reg_ols = sm.OLS(y, x.astype(float), missing='drop').fit(cov_type='HC3')

#print(reg_ols.summary())
cusumTest(reg_ols.resid)
#normalityTest(reg_ols)
#LMtestAutocorrelation(reg_ols)
#ramseyResetTest(reg_ols)
#whiteTest(reg_ols)


from PIL import Image
from django.shortcuts import render
import os
def papaya_find_ripe_raw():
    path = 'webs/color/papaya/'
    directory= os.listdir(path)
    if len(directory) == 2:
        img = Image.open('webs/color/papaya/raw_papaya.png')
        black = 0
        papaya_raw = 0
        for pixel in img.getdata():
            if pixel == (0, 0, 0): # if your image is RGB (if RGBA, (0, 0, 0, 255) or so
                black += 1
            else:
                papaya_raw += 1
        #print('yellow='+str(yellow_raw))

        img = Image.open('webs/color/papaya/ripe_papaya.png')
        black = 0
        papaya_ripe = 0
        for pixel in img.getdata():
            if pixel == (0, 0, 0): # if your image is RGB (if RGBA, (0, 0, 0, 255) or so
                black += 1
            else:
                papaya_ripe += 1
        #print('yellow='+str(yellow_ripe))

        if (papaya_raw > papaya_ripe):
            data = 'papaya is raw'
        elif(papaya_raw < papaya_ripe):
            data = 'papaya is ripe'
        elif (papaya_raw == papaya_ripe) :
            data = 'Not image in range'
    else:
        data = 'Not image in range'

    return(data)


import time
import os
import hashlib

from absl import app, flags, logging
from absl.flags import FLAGS
import tensorflow as tf
import lxml.etree
import tqdm

flags.DEFINE_string('data_dir', './my_data/voc2020_raw/VOCdevkit/VOC2020/',
                    'path to raw PASCAL VOC dataset')
flags.DEFINE_enum('split', 'train', [
                  'train', 'val'], 'specify train or val spit')
flags.DEFINE_string('output_file', './my_data/voc2020_train.tfrecord', 'output dataset')
flags.DEFINE_string('classes', './my_data/classes.names', 'classes file')
flags.DEFINE_string('emphasized_class', 'smoke', 'Select in which class to emphasize the dataset. \nOne of \'smoke\', \'fire\', \'all\' ')
flags.DEFINE_string('excluded_name', 'captures', 'define a name that it`s included in _train|_val .txt file in order to exclude it from dataset.')

def build_example(annotation, class_map):
    img_path = os.path.join(
        FLAGS.data_dir, 'JPEGImages', annotation['filename'])
    with open(img_path, 'rb') as img:
        img_raw = img.read()
        key = hashlib.sha256(img_raw).hexdigest()

    width = int(annotation['size']['width'])
    height = int(annotation['size']['height'])

    xmin = []
    ymin = []
    xmax = []
    ymax = []
    classes = []
    classes_text = []
    truncated = []
    views = []
    difficult_obj = []
    if 'object' in annotation:
        for obj in annotation['object']:
            if FLAGS.excluded_name in annotation['filename']:
                continue
            difficult = bool(int(obj['difficult']))
            difficult_obj.append(int(difficult))

            xmin.append(float(obj['bndbox']['xmin']) / width)
            ymin.append(float(obj['bndbox']['ymin']) / height)
            xmax.append(float(obj['bndbox']['xmax']) / width)
            ymax.append(float(obj['bndbox']['ymax']) / height)
            classes_text.append(obj['name'].encode('utf8'))
            classes.append(class_map[obj['name']])
            truncated.append(int(obj['truncated']))
            views.append(obj['pose'].encode('utf8'))

    example = tf.train.Example(features=tf.train.Features(feature={
        'image/height': tf.train.Feature(int64_list=tf.train.Int64List(value=[height])),
        'image/width': tf.train.Feature(int64_list=tf.train.Int64List(value=[width])),
        'image/filename': tf.train.Feature(bytes_list=tf.train.BytesList(value=[
            annotation['filename'].encode('utf8')])),
        'image/source_id': tf.train.Feature(bytes_list=tf.train.BytesList(value=[
            annotation['filename'].encode('utf8')])),
        'image/key/sha256': tf.train.Feature(bytes_list=tf.train.BytesList(value=[key.encode('utf8')])),
        'image/encoded': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])),
        'image/format': tf.train.Feature(bytes_list=tf.train.BytesList(value=['jpeg'.encode('utf8')])),
        'image/object/bbox/xmin': tf.train.Feature(float_list=tf.train.FloatList(value=xmin)),
        'image/object/bbox/xmax': tf.train.Feature(float_list=tf.train.FloatList(value=xmax)),
        'image/object/bbox/ymin': tf.train.Feature(float_list=tf.train.FloatList(value=ymin)),
        'image/object/bbox/ymax': tf.train.Feature(float_list=tf.train.FloatList(value=ymax)),
        'image/object/class/text': tf.train.Feature(bytes_list=tf.train.BytesList(value=classes_text)),
        'image/object/class/label': tf.train.Feature(int64_list=tf.train.Int64List(value=classes)),
        'image/object/difficult': tf.train.Feature(int64_list=tf.train.Int64List(value=difficult_obj)),
        'image/object/truncated': tf.train.Feature(int64_list=tf.train.Int64List(value=truncated)),
        'image/object/view': tf.train.Feature(bytes_list=tf.train.BytesList(value=views)),
    }))
    return example

def parse_xml(xml):
    if not len(xml):
        return {xml.tag: xml.text}
    result = {}
    for child in xml:
        child_result = parse_xml(child)
        if child.tag != 'object':
            result[child.tag] = child_result[child.tag]
        else:
            if child.tag not in result:
                result[child.tag] = []
            result[child.tag].append(child_result[child.tag])
    return {xml.tag: result}

def main(_argv):
    with open(FLAGS.classes) as f:
        class_map = {name: idx for idx, name in enumerate(
            f.read().splitlines())}
    logging.info("Class mapping loaded: {}".format(class_map))

    writer = tf.io.TFRecordWriter(FLAGS.output_file)
    with open(os.path.join(FLAGS.data_dir, 'ImageSets', 'Main', '%s_%s.txt' % (FLAGS.emphasized_class, FLAGS.split))) as f:
        image_list = f.read().splitlines()
    logging.info("Image list loaded: %d", len(image_list))
    for image in tqdm.tqdm(image_list):
        name, _ = image.split()
        annotation_xml = os.path.join(
            FLAGS.data_dir, 'Annotations', name + '.xml')
        with open(annotation_xml) as f:
            annotation_xml = lxml.etree.fromstring(f.read())
        annotation = parse_xml(annotation_xml)['annotation']
        tf_example = build_example(annotation, class_map)
        writer.write(tf_example.SerializeToString())
    writer.close()
    logging.info("Done")

if __name__ == '__main__':
    app.run(main)


import logging
from datetime import datetime, timedelta
import random
import pytest
import pytz
from show_my_solutions.dbmanager import Submission

OJS = ['POJ', 'LeetCode', 'Codeforces', 'TopCoder', 'HackerRank', 'ACM']
MAX_ROW = 100

LOGGER = logging.getLogger(__name__)

def setup_module(module):
    from show_my_solutions.dbmanager import start_database
    start_database(name='sms_test.db', echo=False)

def gen_sub(oj, problem_id, seconddelta=None):
    seconddelta = random.randint(-1e6, 1e6) if seconddelta is None else seconddelta
    return Submission(oj,
                      problem_id,
                      'Test {}'.format(random.randint(0, MAX_ROW)),
                      '{}.com/test_{}.html'.format(oj.lower(), problem_id),
                      datetime.now(tz=pytz.utc) + timedelta(seconds=seconddelta))

def gen_rand_subs(n=MAX_ROW, sort=False):
    data = [gen_sub(random.choice(OJS), str(i)) for i in range(n)]
    if sort:
        data.sort(key=lambda x: x.submit_time)
    return data

def refill_submissions(data=None):
    from show_my_solutions.dbmanager import record_submissions, _reset_tables

    _reset_tables()
    if data is None:
        data = gen_rand_subs()
    record_submissions(data)
    return data

def test_record():
    from show_my_solutions.dbmanager import (fetch_submissions, record_submissions)

    def compare(data):
        result = fetch_submissions()
        data = {(d.oj, d.problem_id): d.clone() for d in data}
        data = sorted(data.values(), key=lambda x: x.submit_time)
        for i, d in enumerate(data):
            d.pid = i + 1
            d.oj = d.oj.lower()
        assert data == result

    data = refill_submissions()
    compare(data)

    # Test duplicated (oj, problem_id)
    new_sub = gen_sub(OJS[0], '-1')
    data.extend([new_sub, new_sub])
    refill_submissions(data)
    compare(data)

    # Record empty list
    refill_submissions([])
    compare([])

def test_milestone():
    from sqlalchemy.exc import IntegrityError
    from show_my_solutions.dbmanager import fetch_submissions, add_milestone

    data = [gen_sub(OJS[0], str(i), i) for i in range(MAX_ROW)]
    refill_submissions(data)

    ms = MAX_ROW / 2
    add_milestone('rand_tester', ms)
    result = fetch_submissions('rand_tester')
    pids = [x.pid for x in result]
    assert min(pids) == ms + 1
    assert len(set(pids)) == MAX_ROW - ms
    assert max(pids) == MAX_ROW

    # Out-of-bound milestone should not take effect because of forigen key
    with pytest.raises(IntegrityError):
        add_milestone('rand_tester', MAX_ROW + 1)

    add_milestone('rand_tester', MAX_ROW)
    assert fetch_submissions('rand_tester') == []

def test_latest_problem_id():
    from show_my_solutions.dbmanager import (record_submissions, get_lastest_problem_id)

    refill_submissions([])

    for oj in OJS:
        assert get_lastest_problem_id(oj) is None

    latest = {}
    data = []
    for i in range(MAX_ROW):
        oj = random.choice(OJS)
        problem_id = str(random.randint(0, 1e5))
        latest[oj] = problem_id
        data.append(gen_sub(oj, problem_id, i))
    record_submissions(data)
    LOGGER.debug('\n'.format(map(str, data)))
    for oj in OJS:
        assert get_lastest_problem_id(oj) == latest.get(oj, None)

@pytest.fixture
def reactor():
    from show_my_solutions.app import get_config, Reactor
    return Reactor(get_config())

def test_trello_handler(reactor):
    from show_my_solutions.handlers import build_handler

    handler = build_handler('trello', reactor)
    handler.upload(gen_rand_subs(10, True))

def test_leetcode_scraper(reactor):
    from show_my_solutions.scrapers import build_scraper
    from bs4 import BeautifulSoup
    # _reset_tables()

    lcs = build_scraper('leetcode', reactor)
    lcs.fetch()


from setuptools import setup, find_packages
import os

with open(os.path.join(os.path.dirname(__file__), 'README.md')) as README:
    DESCRIPTION = README.read()

with open('requirements.txt') as f:
    required = f.read().splitlines()

setup(
    name='OpenReader',
    version='0.1',
    packages = find_packages(),
    include_package_data = True,
    author = "Not Google",
    license='LICENSE.md',
    long_description=DESCRIPTION,
    description="Reading RSS feeds like it's 2012",
    url="https://github.com/craigsonoffergus/OpenReader",
    install_requires=required,
)


import pyarrow.compute as pc
import pyarrow as pa
import numpy as np
from typing import Iterator, Tuple, List
from ..model.types import (
    SubjectSymbol,
    SourceSymbol,
    ExchangeSymbol,
    InstrumentSymbol,
    MarketSymbol,
    Timestamp,
    FileId,
)

DAY_NANOSECONDS = 24 * 60 * 60 * 10 ** 9
PARTITION_COLUMNS = ["subject", "source", "exchange", "instrument"]

def _hash_array(array: pa.ChunkedArray) -> Tuple[int, pa.ChunkedArray]:
    if isinstance(array.type, pa.DictionaryType):
        encoded = array
    else:
        encoded = array.dictionary_encode()
    return (
        len(encoded.chunk(0).dictionary),
        pa.chunked_array(
            [chunk.indices.cast(pa.int64()) for chunk in encoded.iterchunks()]
        ),
    )

def _hash_arrays(arrays: List[pa.ChunkedArray]) -> Tuple[int, pa.ChunkedArray]:
    if len(arrays) == 1:
        return _hash_array(arrays[0])

    head_max, head_hashes = _hash_array(arrays[0])
    tail_max, tail_hashes = _hash_arrays(arrays[1:])

    if head_max == 1:
        return (tail_max, tail_hashes)

    return (
        head_max * tail_max,
        pc.add(pc.multiply(head_hashes, tail_max), tail_hashes),
    )

def _run_length_encoding(arrays: List[pa.ChunkedArray]) -> Iterator[Tuple[int, int]]:
    size, hashes = _hash_arrays(arrays)

    # Inspired by https://gist.github.com/nvictus/66627b580c13068589957d6ab0919e66
    where = np.flatnonzero
    starts = np.r_[0, where(np.diff(hashes.to_numpy())) + 1]
    stops = np.r_[starts[1:], len(hashes)]
    return zip(starts.tolist(), stops.tolist())

def _fileid_from_chunk(chunk: pa.Table) -> FileId:
    timestamp = Timestamp(chunk["time"][0].as_py())
    subject = SubjectSymbol(chunk["subject"][0].as_py())
    source = SourceSymbol(chunk["source"][0].as_py())
    exchange = ExchangeSymbol(chunk["exchange"][0].as_py())
    instrument = InstrumentSymbol.from_symbol(chunk["instrument"][0].as_py())
    market = MarketSymbol(exchange, instrument)
    file = FileId(subject, source, market, timestamp)
    return file

def partition_records(records: pa.Table) -> Iterator[Tuple[FileId, pa.Table]]:
    time = records["time"].cast(pa.int64())
    assert records["time"].type.tz == "UTC", "time column must be in UTC"
    assert np.all(np.diff(time.to_numpy()) >= 0), "time column must be monotonic"

    date = pc.divide(time, DAY_NANOSECONDS)

    partition_columns = [records[name] for name in PARTITION_COLUMNS] + [date]
    for start, stop in _run_length_encoding(partition_columns):
        chunk = records[start:stop]
        yield _fileid_from_chunk(chunk), chunk.drop(PARTITION_COLUMNS)


from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
from datetime import datetime
from django.utils.translation import gettext_lazy as _
from service.models import Skill

User = get_user_model()

class Expert(models.Model):
    user = models.OneToOneField(User, verbose_name='کاربر', on_delete=models.CASCADE)
    national_code = models.CharField(_('کد ملی'), max_length=10)
    father_name = models.CharField(_('نام پدر'), max_length=26)
    expert_province = models.CharField(_('استان'), max_length=100)
    expert_city = models.CharField(_('شهر'), max_length=100)
    MALE = 1
    FEMALE = 2
    GENDER_CHOICE = [
        (MALE, 'MALE'),
        (FEMALE, 'FEMALE')
    ]
    gender = models.PositiveSmallIntegerField(_('جنسیت'), choices=GENDER_CHOICE)
    WOMEN = 1
    DONE = 2
    EXEMPT = 3
    SUBJECT = 4
    MILITARY_SERVICE_CHOICES = [
        (WOMEN, 'WOMEN'),
        (DONE, 'DONE'),
        (EXEMPT, 'EXEMPT'),
        (SUBJECT, 'SUBJECT')
    ]
    military_service = models.PositiveSmallIntegerField(
        _('سربازی'), choices=MILITARY_SERVICE_CHOICES
        )
    SINGLE = 1
    MARRIED = 2
    MARRIED_CHOICES = [
        (SINGLE, 'SINGLE'),
        (MARRIED, 'MARRIED')
    ]
    married_status = models.PositiveSmallIntegerField(_('وضعیت تاهل'), choices=MARRIED_CHOICES)
    is_active_expert_expire_time = models.DateTimeField(_('تاریخ غیرفعال شدن اکانت'), default=timezone.now)
    expert_lat = models.DecimalField(_('expert lat'), max_digits=9, decimal_places=6)
    expert_long = models.DecimalField(_('expert long'), max_digits=9, decimal_places=6)
    skills = models.ManyToManyField(
        Skill, verbose_name='مهارت ها', related_name='experts', through='Skillship'
        )
    created_at = models.DateTimeField(_('created_at'), auto_now_add=True)
    updated_at = models.DateTimeField(_('updated_at'), auto_now=True)

    def __str__(self):
        return self.user.get_full_name()

    def count_skills(self):
        pass

    def skills_list(self):
        pass

    @property
    def is_active(self):
        now = timezone.now()
        return self.is_active_expert_expire_time > now

    class Meta:
        verbose_name = _('متخصص')
        verbose_name_plural = _('متخصصان')

class Skillship(models.Model):
    expert = models.ForeignKey(Expert, verbose_name='متخصص', on_delete=models.CASCADE)
    skill = models.ForeignKey(Skill, verbose_name='مهارت', on_delete=models.CASCADE)
    image_of_evidence = models.ImageField(_('تصویر مدرک'), upload_to='evidences')
    description = models.TextField(_('توضیحات'))

    class Meta:
        verbose_name = _('تخصص')
        verbose_name_plural = _('تخصص ها')


import os

import jinja2
import yaml

def load_config(config_directory, env_file, config_env_overrides=None):
    if config_env_overrides is None:
        config_env_overrides = {}

    with open(os.path.join(config_directory, env_file)) as env_fd:
        config_env = yaml.load(env_fd)

    for key, value in config_env_overrides.items():
        config_env[key] = value

    jinja_env = jinja2.Environment(
        loader=jinja2.FileSystemLoader(config_directory),
        trim_blocks=True,
        lstrip_blocks=True,
    )

    sources = (
        entry
        for entry in os.listdir(config_directory)
        if entry != env_file
        and os.path.isfile(os.path.join(config_directory, entry))
    )

    result = config_env.copy()

    for source in sources:
        template = jinja_env.get_template(source)
        yaml_config = template.render(config_env)
        result[source.split(".")[0]] = yaml.load(yaml_config)

    return result


from django import forms
from django.shortcuts import render, redirect
from .forms import DetailForm
from datetime import datetime
import string
import csv

# Create your views here.

def index(request):
    print("HELLO")
    if request.method == 'POST':
        form = DetailForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']
            str = form.cleaned_data['str']
            data = detailsfunc(name, email, str)
            return render(request, 'cards.html', {'data' : data})
        else:
            print("ERROR")
    else:
        form = DetailForm(request.POST)
        msg = "ERROR"
        return render(request, 'index.html', {'data' : msg})

def detailsfunc(name, email, str):
    #main extractor
    problem = str
    data=dict()
    txts = problem.split(" ")
    duration = ""

    try:
        for i in range(len(txts)):
            if txts[i].lower() == "since" or txts[i].lower() == "from":
                duration = txts[i+1]+" "+txts[i+2]
                break
    except:
        duration=""

    data['duration'] = duration.translate(str.maketrans('', '', string.punctuation))

    symptom = ""

    try:
        z=0
        txts = problem.split(" ")
        for i in range(len(txts)):
            if txts[i].lower() in ("have","having","feel","feeling"):
                si = i
            if txts[i] == "since" or txts[i] == "from":
                sii = i
                z=1
                break
        if z == 1:
            for x in txts[si:sii]:
                symptom += x+" "
            z=0

    except:
        z=0
        symptom = problem

    data['symptom'] = symptom.translate(str.maketrans('', '', string.punctuation))

    aggrv=""
    txt = problem.lower()
    for i in ("during","while","when","increases","decreases"):
        k=-1;s=''
        try:
            k = txt.find(i)
            if k >= 0:
                s = txt[k:txt.index('.',k)]
                aggrv=s
                break
        except:
            aggrv=""
            pass
    data['name'] = name
    dt = datetime.now()
    strg = dt.strftime('%d %B %Y')
    data['date']=strg
    problem = problem.replace('\n','')
    data['aggrv']=aggrv.translate(str.maketrans('', '', string.punctuation))
    data['story']=problem.translate(str.maketrans('', '', string.punctuation))
    print(data['symptom'])
    with open("doctor.csv",'a') as f:
        f.write("\n"+data['name'] + "," +data['story'] + "," +data['duration'] + "," +data['symptom'] + "," +data['aggrv'] + "," +data['date'] )

    return data

def datatable(request):
    n,st,dr,sp,dt,af = [],[],[],[],[],[]
    with open('E:\hackathon\doctor.csv', 'r') as file:
        reader = csv.reader(file)
        k = 0
        print("-")
        for row in reader:
            if k != 0:
                print(row[0])
                print(row[0]+"-")
                n.append(row[0])
                st.append(row[1])
                dr.append(row[2])
                sp.append(row[3])
                af.append(row[4])
                dt.append(row[5])
            else:
                k+=1
    data = zip(n,st,dr,sp,af,dt)
    print(dt)
    return render(request, 'table.html',{'data':data})


# https://leetcode.com/problems/middle-of-the-linked-list/
from typing import Optional

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:

        first, second = head, head

        while first and first.next:
            first = first.next.next
            second = second.next

        return second


from typing import Any
from django import http
from django.shortcuts import render, redirect
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from common.models import Insumo, Proveedor
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.http.response import JsonResponse
from django.utils.decorators import method_decorator
import json

# Create your views here.

class InsumoView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, id=0):
        if id > 0:
            insumos = list(Insumo.objects.filter(idinsumo=id).values())
            if len(insumos) > 0:
                insumo = insumos[0]
                datos = {'mensaje': 'exito', 'insumo': insumo}
            else:
                datos = {'mensaje': 'No se encontró el insumo'}
            return JsonResponse(datos)
        else:
            insumos = list(Insumo.objects.values())
            if len(insumos) > 0:
                datos = {'mensaje': 'exito', 'cantidad': len(insumos), 'insumos': insumos}
            else:
                datos = {'mensaje': 'No se encontraron insumos'}
        return JsonResponse(datos)

    def post(self, request):
        jd = json.loads(request.body)
        proveedor_id=jd['proveedor_id']
        try:
            prov = Proveedor.objects.get(nombre=proveedor_id)
        except Proveedor.DoesNotExist:
            prov = None
        if prov:
            insumo = Insumo.objects.create(descripcion=jd['descripcion'], precio_unitario=jd['precio_unitario'], cantidad_disponible=jd['cantidad_disponible'], tipo_medida=jd['tipo_medida'], categoria=jd['categoria'], proveedor=prov)
            datos = {'mensaje': 'success'}
        else:
            datos = {'mensaje': 'El rubro no existe'}
        return JsonResponse(datos)

    def patch(self, request, id):
        jd = json.loads(request.body)
        insumos = list(Insumo.objects.filter(idinsumo=id).values())
        if len(insumos) > 0:
            insumo = Insumo.objects.get(idinsumo=id)
            insumo.descripcion = jd['descripcion']
            insumo.cantidad_disponible = jd['cantidad_disponible']
            insumo.tipo_medida = jd['tipo_medida']
            insumo.categoria = jd['categoria']
            insumo.precio_unitario = jd['precio_unitario']
            insumo.save()
            datos = {'mensaje': 'Insumo actualizado correctamente'}
        else:
            datos = {'mensaje': 'No se encontró el insumo'}
        return JsonResponse(datos)


from django.urls import path, include
from rest_framework.routers import DefaultRouter

from .views import (
    IndexView,
    AutorListCreateAPIView,
    AutorRetrieveUpdateDestroyAPIView,
    CategoriaListCreateAPIView,
    CategoriaRetrieveUpdateDestroyAPIView,
    EditorialListCreateAPIView,
    EditorialRetrieveUpdateDestroyAPIView,
    LibroViewSet,
)

# Configurar el enrutador
router = DefaultRouter()
router.register(r'libros', LibroViewSet)

urlpatterns = [
    path('', IndexView.as_view(), name='api-index'),
    path('autores/', AutorListCreateAPIView.as_view(), name='api-autor-list'),
    path('autores/<int:autor_id>/', AutorRetrieveUpdateDestroyAPIView.as_view(), name='api-autor-detail'),
    path('categorias/', CategoriaListCreateAPIView.as_view(), name='api-categoria-list'),
    path('categorias/<int:categoria_id>/', CategoriaRetrieveUpdateDestroyAPIView.as_view(), name='api-categoria-detail'),
    path('editoriales/', EditorialListCreateAPIView.as_view(), name='api-editorial-list'),
    path('editoriales/<int:editorial_id>/', EditorialRetrieveUpdateDestroyAPIView.as_view(), name='api-editorial-detail'),
    path('libros/', LibroViewSet.as_view({'post': 'create'}), name='api-libro-create'),  # Agregar esta línea
    path('admin/', include(router.urls)),
]