import logging
import datetime
from typing import List, Optional
from betfairlightweight.resources.bettingresources import MarketBook, RunnerBook

from .utils import (
    SimulatedPlaceResponse,
    SimulatedCancelResponse,
    SimulatedUpdateResponse,
)
from ..utils import get_price, get_size, wap
from ..order.ordertype import OrderTypes
from .. import config

logger = logging.getLogger(__name__)

class SimulatedOrder:
    """
    Class to hold `simulated` order
    matching and status.
    """

    def __init__(self, order):
        self.order = order
        self.size_matched = 0
        self.average_price_matched = 0
        self.matched = []  # [[publishTime, price, size]..]
        self.size_cancelled = 0.0
        self.size_lapsed = 0.0
        self.size_voided = 0.0
        self.market_version = None  # version at place so we can lapse if needed
        self._piq = 0.0
        self._bsp_reconciled = False

    def __call__(self, market_book: MarketBook, runner_traded: tuple) -> None:
        # simulates order matching
        if self._bsp_reconciled is False and market_book.bsp_reconciled:
            if self.take_sp:
                runner = self._get_runner(market_book)
                self._process_sp(market_book.publish_time_epoch, runner)
                return
            else:
                self._bsp_reconciled = True

        if self.order.order_type.ORDER_TYPE == OrderTypes.LIMIT:
            if market_book.version != self.market_version:
                self.market_version = market_book.version  # update for next time
                if market_book.status == "SUSPENDED":  # Material change
                    if self.order.order_type.persistence_type == "LAPSE":
                        self.size_lapsed += self.size_remaining
                        return

            # todo estimated piq cancellations
            traded = runner_traded[1]
            if traded:
                self._process_traded(market_book.publish_time_epoch, traded)

            if config.simulation_available_prices:
                self._process_available(
                    market_book.publish_time_epoch, runner_traded[0]
                )

    def place(
        self, order_package, market_book: MarketBook, instruction: dict, bet_id: int
    ) -> SimulatedPlaceResponse:
        # simulates placeOrder request->matching->response
        # validate market status
        if market_book.status != "OPEN":
            self.size_voided += self.size_remaining
            return self._create_place_response(
                None,
                status="FAILURE",
                error_code="ERROR_IN_ORDER",
            )

        # validate market version
        self.market_version = market_book.version
        if (
            order_package.market_version
            and order_package.market_version["version"] != self.market_version
        ):
            self.size_voided += self.size_remaining
            return self._create_place_response(
                None,
                status="FAILURE",
                error_code="ERROR_IN_ORDER",
            )

        runner = self._get_runner(market_book)
        # validate runner status
        if runner.status == "REMOVED":
            self.size_voided += self.size_remaining
            return self._create_place_response(
                None,
                status="FAILURE",
                error_code="RUNNER_REMOVED",
            )
        if self.order.order_type.ORDER_TYPE == OrderTypes.LIMIT:
            price = self.order.order_type.price
            size = self.order.order_type.size
            if "limitOrder" in instruction:
                time_in_force = instruction["limitOrder"].get("timeInForce")
                min_fill_size = instruction["limitOrder"].get("minFillSize") or 0
            else:
                time_in_force = None
                min_fill_size = None
            if size is None:
                raise NotImplementedError(
                    "Simulated betTargetSize placement not implemented"
                )
            if self.order.side == "BACK":
                available_to_back = get_price(runner.ex.available_to_back, 0) or 1.01
                if (
                    not order_package.client.best_price_execution
                    and available_to_back > price
                ):
                    self.size_lapsed += self.size_remaining
                    return self._create_place_response(
                        None,
                        status="FAILURE",
                        error_code="BET_LAPSED_PRICE_IMPROVEMENT_TOO_LARGE",
                    )
                elif time_in_force == "FILL_OR_KILL":
                    available_size = get_size(runner.ex.available_to_back, 0) or 0
                    if price > available_to_back:
                        self.size_lapsed += self.size_remaining
                        return self._create_place_response(bet_id)
                    elif price == available_to_back:
                        if available_size >= min_fill_size:
                            self._process_price_matched(
                                market_book.publish_time_epoch,
                                price,
                                size,
                                runner.ex.available_to_back,
                            )
                        self.size_lapsed += self.size_remaining
                        return self._create_place_response(bet_id)
                    else:
                        self._process_price_matched_vwap(
                            market_book.publish_time_epoch,
                            price,
                            size,
                            runner.ex.available_to_back,
                            min_fill_size=min_fill_size,
                        )
                        self.size_lapsed += self.size_remaining
                        return self._create_place_response(bet_id)
                elif available_to_back >= price:
                    self._process_price_matched(
                        market_book.publish_time_epoch,
                        price,
                        size,
                        runner.ex.available_to_back,
                    )
                    return self._create_place_response(bet_id)
                available = runner.ex.available_to_lay
            else:
                available_to_lay = get_price(runner.ex.available_to_lay, 0) or 1000
                if (
                    not order_package.client.best_price_execution
                    and available_to_lay < price
                ):
                    self.size_lapsed += self.size_remaining
                    return self._create_place_response(
                        None,
                        status="FAILURE",
                        error_code="BET_LAPSED_PRICE_IMPROVEMENT_TOO_LARGE",
                    )
                elif time_in_force == "FILL_OR_KILL":
                    available_size = get_size(runner.ex.available_to_lay, 0) or 0
                    if price < available_to_lay:
                        self.size_lapsed += self.size_remaining
                        return self._create_place_response(bet_id)
                    elif price == available_to_lay:
                        if available_size >= min_fill_size:
                            self._process_price_matched(
                                market_book.publish_time_epoch,
                                price,
                                size,
                                runner.ex.available_to_lay,
                            )
                        self.size_lapsed += self.size_remaining
                        return self._create_place_response(bet_id)
                    else:
                        self._process_price_matched_vwap(
                            market_book.publish_time_epoch,
                            price,
                            size,
                            runner.ex.available_to_lay,
                            min_fill_size=min_fill_size,
                        )
                        self.size_lapsed += self.size_remaining
                        return self._create_place_response(bet_id)
                elif available_to_lay <= price:
                    self._process_price_matched(
                        market_book.publish_time_epoch,
                        price,
                        size,
                        runner.ex.available_to_lay,
                    )
                    return self._create_place_response(bet_id)
                available = runner.ex.available_to_back

            # calculate position in queue
            for avail in available:
                if avail["price"] == price:
                    self._piq = avail["size"]
                    break

            logger.debug("Simulated order %s PIQ: %s", self.order.id, self._piq)
            return self._create_place_response(bet_id)
        else:
            # validate BSP available, not reconciled and market not inplay
            if (
                market_book.market_definition.bsp_market is False
                or market_book.bsp_reconciled is True
                or market_book.inplay is True
            ):
                self.size_voided += self.size_remaining
                return self._create_place_response(
                    None,
                    status="FAILURE",
                    error_code="MARKET_NOT_OPEN_FOR_BSP_BETTING",
                )
            return self._create_place_response(bet_id)

    def _create_place_response(
        self,
        bet_id: Optional[int],
        status: str = "SUCCESS",
        order_status: str = None,
        error_code: str = None,
    ) -> SimulatedPlaceResponse:
        if self.order.client.simulated_full_match:
            if status == "SUCCESS" and self.size_remaining:
                self.matched.append(
                    [0, self.order.order_type.price, self.size_remaining]
                )
                self.size_matched, self.average_price_matched = wap(self.matched)
        if order_status is None:
            if self.size_remaining == 0:
                order_status = "EXECUTION_COMPLETE"
            else:
                order_status = "EXECUTABLE"
        return SimulatedPlaceResponse(
            status=status,
            order_status=order_status,
            bet_id=str(bet_id) if bet_id else bet_id,
            average_price_matched=self.average_price_matched,
            size_matched=self.size_matched,
            placed_date=datetime.datetime.utcnow(),
            error_code=error_code,
        )

    def cancel(self, market_book: MarketBook) -> SimulatedCancelResponse:
        # simulates cancelOrder request->cancel->response
        if market_book.status != "OPEN":
            return SimulatedCancelResponse(
                status="FAILURE",
                error_code="ERROR_IN_ORDER",
            )
        if self.order.order_type.ORDER_TYPE == OrderTypes.LIMIT:
            _size_reduction = (
                self.order.update_data.get("size_reduction") or self.size_remaining
            )
            _size_cancelled = min(
                _size_reduction, self.size_remaining
            )  # cancelled cannot be more than remaining (does not error)
            self.size_cancelled += _size_cancelled
            return SimulatedCancelResponse(
                status="SUCCESS",  # todo handle errors
                size_cancelled=_size_cancelled,
                cancelled_date=datetime.datetime.utcnow(),
            )
        else:
            return SimulatedCancelResponse(
                status="FAILURE",
                error_code="BET_ACTION_ERROR",
            )

    def update(
        self, market_book: MarketBook, instruction: dict
    ) -> SimulatedUpdateResponse:
        # simulates updateOrder request->update->response
        if market_book.status != "OPEN":
            return SimulatedUpdateResponse(
                status="FAILURE",
                error_code="ERROR_IN_ORDER",
            )
        # validate BSP available
        if market_book.market_definition.persistence_enabled is False:
            return SimulatedUpdateResponse(
                status="FAILURE",
                error_code="INVALID_PERSISTENCE_TYPE",
            )
        if (
            self.order.order_type.ORDER_TYPE == OrderTypes.LIMIT
            and self.size_remaining > 0
        ):
            self.order.order_type.persistence_type = instruction.get(
                "newPersistenceType"
            )
            return SimulatedUpdateResponse(status="SUCCESS")
        else:
            return SimulatedUpdateResponse(
                status="FAILURE",
                error_code="BET_ACTION_ERROR",
            )

    def _get_runner(self, market_book: MarketBook) -> RunnerBook:
        runner_dict = {
            (runner.selection_id, runner.handicap): runner
            for runner in market_book.runners
        }
        return runner_dict.get((self.order.selection_id, self.order.handicap))

    def _process_price_matched(
        self, publish_time: int, price: float, size: float, available: list
    ) -> None:
        # calculate matched on execution
        size_remaining = size
        for avail in available:
            if size_remaining == 0:
                break
            elif (self.side == "BACK" and price <= avail["price"]) or (
                self.side == "LAY" and price >= avail["price"]
            ):
                _size_remaining = size_remaining
                size_remaining = max(size_remaining - avail["size"], 0)
                if size_remaining == 0:
                    _size_matched = _size_remaining
                else:
                    _size_matched = avail["size"]
                _matched = [publish_time, avail["price"], round(_size_matched, 2)]
                self._update_matched(_matched)
            else:
                break

    def _process_price_matched_vwap(
        self,
        publish_time: int,
        price: float,
        size: float,
        available: list,
        min_fill_size: float,
    ) -> None:
        # calculate vwap matched on execution
        size_remaining = size
        for avail in available:
            if size_remaining == 0:
                break
            # create copy of current matched
            _all_matched = self.matched.copy()
            # get current match
            _size_remaining = size_remaining
            size_remaining = max(size_remaining - avail["size"], 0)
            if size_remaining == 0:
                _size_matched = _size_remaining
            else:
                _size_matched = avail["size"]
            _matched = [publish_time, avail["price"], round(_size_matched, 2)]
            _all_matched.append(_matched)
            # get potential vwap
            _, _average_price_matched = wap(_all_matched)
            # check
            if self.side == "BACK" and _average_price_matched >= price:
                self._update_matched(_matched)
            elif self.side == "LAY" and _average_price_matched <= price:
                self._update_matched(_matched)
            else:
                break
        if self.size_matched < min_fill_size:
            self.matched = []
            self.size_matched, self.average_price_matched = wap(self.matched)
            self.size_lapsed += self.size_remaining

    def _process_sp(self, publish_time: int, runner: RunnerBook) -> None:
        # calculate matched on BSP reconciliation
        actual_sp = runner.sp.actual_sp
        if actual_sp:
            self._bsp_reconciled = True
            _order_type = self.order.order_type
            if _order_type.ORDER_TYPE == OrderTypes.LIMIT:
                if self.side == "BACK":
                    size = self.size_remaining
                else:
                    remaining_risk = (_order_type.price - 1.0) * self.size_remaining
                    client = self.order.client
                    if remaining_risk >= client.min_bsp_liability:
                        size = round(remaining_risk / (actual_sp - 1.0), 2)
                        # Cancel remaining size
                        self.size_cancelled += round(self.size_remaining - size, 2)
                    else:  # lapse
                        self.size_lapsed += self.size_remaining
                        self.order.execution_complete()
                        return
            elif _order_type.ORDER_TYPE == OrderTypes.LIMIT_ON_CLOSE:
                if self.side == "BACK":
                    if actual_sp < _order_type.price:
                        self.order.execution_complete()
                        return
                    size = _order_type.liability
                else:
                    if actual_sp > _order_type.price:
                        self.order.execution_complete()
                        return
                    size = round(
                        _order_type.liability / (actual_sp - 1), 2
                    )  # todo round 2dp down
            elif _order_type.ORDER_TYPE == OrderTypes.MARKET_ON_CLOSE:
                if self.side == "BACK":
                    size = _order_type.liability
                else:
                    size = round(_order_type.liability / (actual_sp - 1), 2)
            else:
                raise NotImplementedError()
            self._update_matched([publish_time, actual_sp, size])
            self.order.execution_complete()
        else:
            logger.warning(
                "SP not available for order %s on runner %s",
                self.order.id,
                runner.selection_id,
            )

    def _process_traded(self, publish_time: int, traded: dict) -> None:
        # calculate matched on MarketBook update
        price = self.order.order_type.price
        side = self.side
        for traded_price, traded_size in traded.items():
            if logger.isEnabledFor(logging.DEBUG):
                logger.debug(
                    "Simulated order %s traded: %s - %s",
                    self.order.id,
                    traded_price,
                    traded_size,
                )
            if side == "BACK" and traded_price >= price:
                matched = self._calculate_process_traded(publish_time, traded_size)
                if matched:
                    traded[traded_price] = max(traded_size - matched, 0.0)
            elif side == "LAY" and traded_price <= price:
                matched = self._calculate_process_traded(publish_time, traded_size)
                if matched:
                    traded[traded_price] = max(traded_size - matched, 0.0)

    def _calculate_process_traded(self, publish_time: int, traded_size: float) -> float:
        _traded_size = traded_size / 2
        if self._piq - _traded_size < 0:
            size = _traded_size - self._piq
            size = round(min(self.size_remaining, size), 2)
            if size:
                self._update_matched(
                    [
                        publish_time,
                        self.order.order_type.price,
                        size,
                    ]
                )
            _matched = (self._piq + size) * 2
            self._piq = 0
            return _matched
        else:
            self._piq -= _traded_size
            logger.debug("Simulated order %s PIQ: %s", self.order.id, self._piq)
            return traded_size

    def _process_available(self, publish_time: int, runner: RunnerBook) -> None:
        # todo prevent double counting
        price = self.order.order_type.price
        side = self.side
        if side == "BACK":
            for update in runner.ex.available_to_back:
                if update["price"] >= price:
                    self._calculate_process_available(
                        publish_time, update["price"], update["size"]
                    )
        elif side == "LAY":
            for update in runner.ex.available_to_lay:
                if update["price"] <= price:
                    self._calculate_process_available(
                        publish_time, update["price"], update["size"]
                    )

    def _calculate_process_available(
        self, publish_time: int, price: float, size: float
    ) -> None:
        size = round(min(self.size_remaining, size), 2)
        if size:
            self._update_matched(
                [
                    publish_time,
                    price,
                    size,
                ]
            )
        self._piq = 0

    @property
    def take_sp(self) -> bool:
        if self.order.order_type.ORDER_TYPE == OrderTypes.LIMIT:
            if self.order.order_type.persistence_type == "MARKET_ON_CLOSE":
                return True
            return False
        else:
            return True

    @property
    def side(self) -> str:
        return self.order.side

    def _update_matched(self, data: List) -> None:
        logger.debug("Simulated order %s matched: %s", self.order.id, data)
        self.matched.append(data)
        self.size_matched, self.average_price_matched = wap(self.matched)

    @property
    def size_remaining(self) -> float:
        if self.order.order_type.ORDER_TYPE == OrderTypes.LIMIT:
            size = self.order.order_type.size or self.order.order_type.bet_target_size
            return round(
                size
                - self.size_matched
                - self.size_cancelled
                - self.size_lapsed
                - self.size_voided,
                2,
            )
        else:
            return 0.0

    @property
    def profit(self) -> float:
        number_of_dead_heat_winners = self.order.number_of_dead_heat_winners or 1
        if self.order.market_type == "EACH_WAY":
            divisor = self.order.each_way_divisor
            win = self.size_matched * (self.average_price_matched - 1)
            place = self.size_matched * (
                (self.average_price_matched - 1) * (1 / divisor)
            )
            if number_of_dead_heat_winners > 1:  # todo dead heat
                logger.error("Each Way Dead Heat Detected but not handled")
            if self.order.runner_status == "WINNER":
                profit = round(win + place, 2)
                if self.side == "BACK":
                    return profit
                else:
                    return -profit
            elif self.order.runner_status == "PLACED":
                if self.side == "BACK":
                    profit = place - self.size_matched
                    return round(profit, 2)
                else:
                    profit = self.size_matched - place
                    return round(profit, 2)
            elif self.order.runner_status == "LOSER":
                matched = round(self.size_matched * 2, 2)
                if self.side == "BACK":
                    return -matched
                else:
                    return matched
            else:
                return 0.0
        else:
            if self.order.runner_status == "WINNER":
                profit = (self.size_matched / number_of_dead_heat_winners) * (
                    self.average_price_matched - 1
                )
                if number_of_dead_heat_winners == 2:
                    profit = profit - (self.size_matched / number_of_dead_heat_winners)
                elif number_of_dead_heat_winners > 2:
                    profit = profit - (
                        self.size_matched
                        * (number_of_dead_heat_winners - 1)
                        / number_of_dead_heat_winners
                    )
                if self.side == "LAY":
                    profit = -profit
                return round(profit, 2)
            elif self.order.runner_status == "LOSER":
                if self.side == "BACK":
                    return -self.size_matched
                else:
                    return self.size_matched
            else:
                return 0.0

    @property
    def status(self) -> str:
        if self.take_sp:
            if self._bsp_reconciled:
                return "EXECUTION_COMPLETE"
            else:
                return "EXECUTABLE"
        else:
            if self.size_remaining:
                return "EXECUTABLE"
            else:
                return "EXECUTION_COMPLETE"

    @property
    def info(self) -> dict:
        return {
            "profit": self.profit,
            "piq": self._piq,
            "matched": self.matched,
        }

    def __bool__(self):
        return config.simulated or bool(
            self.order.client and self.order.client.paper_trade
        )


from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.common.by import By

class BasePage:
    _black_list = [
        (By.XPATH, "//*[@text='确认']"),
        (By.XPATH, "//*[@text='下次再说']"),
        (By.XPATH, "//*[@text='确定']"),
    ]
    _max_num = 3
    _error_num = 0

    def __init__(self, driver: WebDriver = None):
        self._driver = driver

    def find(self, locator, value: str = None):
        try:
            element = self._driver.find_element(*locator) if isinstance(locator, tuple) else self._driver.find_element(locator, value)
            self._error_num = 0
            self._driver.implicitly_wait(10)
            return element
        except Exception as e:
            self._driver.implicitly_wait(1)
            if self._error_num > self._max_num:
                raise e
            self._error_num += 1
            for ele in self._black_list:
                elements = self._driver.find_elements(*ele)
                if len(elements) > 0:
                    elements[0].click()
                    break
            return self.find(locator, value)


from collections import deque
import sys
M, N = map(int, input().split())

matrix = [list(map(int,input().split())) for i in range(N)]
# print(matrix)

dx = [-1,1,0,0]
dy = [0,0,-1,1]
queue = deque()
def bfs():
    while queue:
        x, y = queue.popleft()
        for k in range(4):
            nx = x + dx[k]
            ny = y + dy[k]
            if 0 <= nx < N and 0 <= ny < M and matrix[nx][ny] == 0:
                queue.append([nx,ny])
                matrix[nx][ny] = matrix[x][y] +1

for i in range(N):
    for j in range(M):
        if matrix[i][j] == 1:
            queue.append([i,j])
bfs()
result = -2 # -2보다 작을 수는 없으므로 최소값을 -2로 자븜
flag = False
for i in matrix:
    for j in i:
        if j == 0:  # 0이 하나라도 있으면 모두 익지 못하는 상황임
            flag = True
        result = max(result, j)
if flag == True:
    print(-1)
elif result == -1:
    print(0)
else:
    print(result-1)


from collections import defaultdict
import pprint
from timeit import default_timer as timer

class Graph():

    '''Graph Class -> Can be directed or undirected(default)
                   -> Can be weighted or unweighted(default)
                   -> Can have a heuristic or not(default)'''

    def __init__(self, edgelist, directed=False, weighted=False, heuristic=False):

        '''
        Initialize graph using a list of edges.
        If Unweighted-> edgelist=(Node 1, Node2)
        If Weighted-> edgelist=(Node 1, Node2, Edge Weight)

        :param edgelist: Node to start search from
        :param directed: Set if graph is directed or undirected (default=Flase)
        :param weighted: Set if graph is weighted or unweighted (default=Flase)
        :param heuristic: Set if graph requires a heuristic or not (default=Flase)

        :return: None
        '''

        self.adj = defaultdict(set)
        self.directed = directed
        self.weighted = weighted
        self._initialize(edgelist) # fill out adjacency list
        if heuristic:
            self.heuristic = {}
            self.generate_heuristics() # Generate heuristic f option is set

    def _initialize(self,edgelist):

        if not self.weighted: # unweighted edges
            for source,dest in edgelist:
                self.add(source,dest)
        else:
            for source,dest,weight in edgelist: # weighted edges
                self.add(source,dest,weight)

    def add(self,node1,node2,weight=None):

        '''
        Function used to add edges to the graph.

        :param node1: Node to start search from
        :param node2: Node to search for
        :param weight: Weights of the edge for weighted Graphs (defaut=None)

        :return: None
        '''

        if weight is None:
            self.adj[node1].add(node2)
            if not self.directed: # addedge from a-b to b-a also if graph is undirected
                self.adj[node2].add(node1)
        else:
            self.adj[node1].add((node2,weight)) # add pairs node1 : (node2,weight)
            if not self.directed:
                self.adj[node2].add((node2,weight))

    def generate_heuristics(self):
        # Can be modified to generate heuristic, but we will use a hard coded one  for now
        self.heuristic = {1: 5, 2: 7, 3: 3, 4: 4, 5: 6, 6: 5, 7: 6, 8: 0, 9: 0, 10: 0}

    def bfs(self, start, target):

        '''
        Breath First Search where given a source and target node using breath
        first method we attempt to find the path to target node.

        :param start: Node to start search from
        :param target: Node to search for

        :return: Path to node if found
        '''

        visited=set()
        q=[]
        traversal=[] # remember path taken
        visited.add(start)
        q.append(start)
        while q:
            node=q.pop(0)
            traversal.append(node)
            if node==target: # stop when goal node is reached
                return traversal
            for other in self.adj[node]: # for every neighbour if not visited add to queue and mark visited
                if other not in visited:
                    visited.add(other)
                    q.append(other)
        return "Node not Found"

    def dfs(self, start, target):

        '''
        Deapth First Search where given a source and target node using depth
        first method we attempt to find the path to target node.

        :param start: Node to start search from
        :param target: Node to search for

        :return: Path to node if found
        '''

        result=[]
        visited=set()
        self._helper_dfs(start,visited,result,target)
        if target in result:
            return result
        else:
            return"Node not Found"

    def _helper_dfs(self, node, visited, result, target):
        if result and result[-1]==target: # if goal node is visited then returns
            return
        visited.add(node)
        result.append(node)

        for other in self.adj[node]: # for every neighbour if not visited run dfs on it
            if other not in visited:
                self._helper_dfs(other,visited,result,target)

    def dls(self, start, target, max_depth):

        '''
        Deapth Limited Search where given a maximum depth path will be
        returned only if node is found at or before the maximum depth.

        :param start: Node to start search from
        :param target: Node to search for
        :param max_depth: Maximum depth to limit search space <= maximum depth

        :return: Path to node if found
        '''

        result=[]
        visited=set()
        depth=defaultdict()
        depth[start]=0
        self._helper_dls(start,visited,result,target,depth,max_depth)
        if target in result:
            return result
        else:
            return"Node not Found"

    def _helper_dls(self, node, visited, result, target, depth, max_depth):

        if depth[node]>max_depth: # check maximum depth condition
            return
        if result and result[-1]==target: # check if goal node is found
            return
        visited.add(node)
        result.append(node)
        for other in self.adj[node]:
            if other not in visited:
                depth[other]=depth[node]+1 # keeps track of depth ->depth of child is parent+1
                self._helper_dls(other,visited,result,target,depth,max_depth)

    def iterative_deepening(self, start, target, max_depth):

        '''
        Iterative Deepening Search where given a maximum depth we will search
        iteratively in every depth from 0-max_depth and return path if found.

        :param start: Node to start search from
        :param target: Node to search for
        :param max_depth: Maximum depth to limit search space <= maximum depth

        :return: Path to node if found
        '''

        flag=0
        for current_depth in range(max_depth+1): # for every depth from 0 to maximum depth run a depth limited search
            result=self.dls(start,target,current_depth)
            if not isinstance(result,str):
                return result
        return "Node not Found"

    def bi_directional(self):
        pass

    def Astar(self,start, target):
        result = set()
        visited = set()
        pqueue = []
        star= defaultdict()
        star[start]= 0
        target_found =False
        self._helper_Astar(star, visited, start, target, pqueue, result, target_found)
        if target in result:
            return result
        else:
            return"Node not Found"

    def _helper_Astar(self, star, visited, node, target, pqueue, result, target_found):
        if target_found:
            return
        visited.add(node)
        result.add(node)
        for other in self.adj[node]:
            if other in visited:
                continue
            visited.add(other)
            pqueue.append(other)
            if target == other[0]:
                target_found = True
                return

        while len(pqueue)!=0:
            x = min(pqueue)[1]
            for i in range(len(pqueue)):
                if pqueue[i][1]== x:
                    x=i
                    break
            if pqueue[x] in result: result.pop(pqueue[x])
            node2 = pqueue.pop(x)
            # if node2 in visited: continue
            self._helper_Astar(star, visited, node2[0], target, pqueue, result, target_found)

    def __str__(self):
        return f'{dict(self.adj)}'

'''
    2
   /
  7 -- 10
 / \
1    6 --    5
 \    \
  8    11
   \
    9
     \
      4
'''

edgelist = [(1,7),(7,2),(7,10),(7,6),(6,5),(6,11),(1,8),(8,9),(9,4)]

# https://media.cheggcdn.com/media/cb6/cb6e15aa-4815-47a4-b2ff-ca9086722f40/phpj6mHyD
# s1  a2  b3  c4  d5  e6  f7  g1 8  g2 9  g3 10

# edgelist=[(1,2,5),(1,3,9),(1,5,6),(2,3,3),(2,8,9),(3,2,2),(3,4,2),(4,1,6),(4,7,7),(4,9,5),(5,1,1),(5,4,1),(5,6,2),(6,10,7),(7,5,2),(7,10,8),(8,9,0)]
# graph=Graph(edgelist, True, True, True)

graph=Graph(edgelist)
printer=pprint.PrettyPrinter()
printer.pprint(dict(graph.adj))
# print(graph)

'''
start = timer()

bfs=graph.bfs('A','K')

end = timer()
print(end - start)
print(bfs)
'''

print('\nPath Algorithm takes until it reaches target: \nBreath First Search (BFS)')
print(graph.bfs(1,4))

print('\nPath Algorithm takes until it reaches target: \nDepth First Search (DFS)')
print(graph.dfs(1,4))

print('\nPath Algorithm takes until it reaches target: \nDepth Limit Search (DLS)')
print(graph.dls(1,11, 4))

print('\nPath Algorithm takes until it reaches target: \nIterative Deepening (IDDFS)')
print(graph.iterative_deepening(1,11, 4))

# print('\nPath Algorithm takes until it reaches target: \nA-star (A*)')
# print(graph.Astar(1,10))


'''
File to analyse the bunch-by-bunch offset shot-by-shot.

Author: Birk Emil Karlsen-Bæck
'''

# Import --------------------------------------------------------------------------------------------------------------
import numpy as np
import matplotlib.pyplot as plt

import utility_files.data_utilities as dut
import utility_files.analysis_tools as at

# Options -------------------------------------------------------------------------------------------------------------
HOME = True
TURN_BY_TURN = True
PLT_TBT = False
SHOT_BY_SHOT = True
PLT_SBS = True

# Parameters ----------------------------------------------------------------------------------------------------------
n_points = 60
turn_points = 99999
n_turns = 100
sample_rate = 10e9
sample_period = 1 / sample_rate
N_batches = 4

# Functions -----------------------------------------------------------------------------------------------------------
if HOME:
    meas_dir = f'../../data_files/profiles_SPS_OTFB_flattop/'
else:
    meas_dir = f'/Users/bkarlsen/cernbox/SPSOTFB_benchmark_data/data/2021-11-05/profiles_SPS_OTFB_flattop/'

files = []
for i in range(104, 130):
    if i != 112:
        files.append(f'MD_{i}')

profiles_data, profiles_data_corr = dut.import_profiles(meas_dir, files)
time_array = np.linspace(0, (turn_points - 1) * sample_period, turn_points)

sbs_bbb_offset_b1 = np.zeros((len(files), 72))
sbs_bbb_offset_b2 = np.zeros((len(files), 72))
sbs_bbb_offset_b3 = np.zeros((len(files), 72))
sbs_bbb_offset_b4 = np.zeros((len(files), 72))

if TURN_BY_TURN:
    bbb_offsets_1t = np.zeros((n_turns * profiles_data.shape[0], 72))
    bbb_offsets_2t = np.zeros((n_turns * profiles_data.shape[0], 72))
    bbb_offsets_3t = np.zeros((n_turns * profiles_data.shape[0], 72))
    bbb_offsets_4t = np.zeros((n_turns * profiles_data.shape[0], 72))

    for i in range(profiles_data.shape[0]):
        profile_data_corr = profiles_data_corr[i, :]
        profile_data_corr = profile_data_corr.reshape((n_turns, turn_points))

        N_bunches, Bunch_positions, Bunch_peaks, Bunch_lengths, Bunch_intensities, Bunch_positionsFit, Bunch_peaksFit, Bunch_exponent, Goodness_of_fit = \
            dut.getBeamPattern_4(time_array, profile_data_corr.T, distance=200, fit_option='fwhm', plot_fit=False,
                                 baseline_length=35)

        bbb_offsets_1 = np.zeros((n_turns, 72))
        bbb_offsets_2 = np.zeros((n_turns, 72))
        bbb_offsets_3 = np.zeros((n_turns, 72))
        bbb_offsets_4 = np.zeros((n_turns, 72))

        for j in range(n_turns):
            pos_fit = Bunch_positionsFit[j, :].reshape((N_batches, 72))

            bbb_offsets_1[j, :] = at.find_offset(pos_fit[0, :])
            bbb_offsets_2[j, :] = at.find_offset(pos_fit[1, :])
            bbb_offsets_3[j, :] = at.find_offset(pos_fit[2, :])
            bbb_offsets_4[j, :] = at.find_offset(pos_fit[3, :])

        bbb_offsets_1t[i * n_turns: (i + 1) * n_turns, :] = bbb_offsets_1
        bbb_offsets_2t[i * n_turns: (i + 1) * n_turns, :] = bbb_offsets_2
        bbb_offsets_3t[i * n_turns: (i + 1) * n_turns, :] = bbb_offsets_3
        bbb_offsets_4t[i * n_turns: (i + 1) * n_turns, :] = bbb_offsets_4

        PLT_B_43 = True
        if PLT_B_43 and i == 8:
            plt.figure()
            plt.title('Bunch 43, shot 9')
            plt.plot(Bunch_positionsFit[:, 43])

        if PLT_TBT:
            plt.figure()
            plt.title('batch 1')
            plt.plot(bbb_offsets_1.T)

            plt.figure()
            plt.title('batch 2')
            plt.plot(bbb_offsets_2.T)

            plt.figure()
            plt.title('batch 3')
            plt.plot(bbb_offsets_3.T)

            plt.figure()
            plt.title('batch 4')
            plt.plot(bbb_offsets_4.T)

            plt.show()

        if SHOT_BY_SHOT:
            sbs_bbb_offset_b1[i, :] = np.mean(bbb_offsets_1, axis=0)
            sbs_bbb_offset_b2[i, :] = np.mean(bbb_offsets_2, axis=0)
            sbs_bbb_offset_b3[i, :] = np.mean(bbb_offsets_3, axis=0)
            sbs_bbb_offset_b4[i, :] = np.mean(bbb_offsets_4, axis=0)

    print(bbb_offsets_1t.shape)
    print(profiles_data.shape[0])

    print('Turn-by-turn')
    print('Batch 1')
    var_max, var_min, max_ind, min_ind = at.find_turn_by_turn_variantions(bbb_offsets_1t, profiles_data.shape[0],
                                                                          ABS=True, IND_MAX=True)
    print(var_max, var_min, max_ind, min_ind)
    print(np.max(np.concatenate((var_max, np.abs(var_min)))))
    at.plot_bunch_pos(bbb_offsets_1t, 100, 8, 43)

    print('Batch 2')
    var_max, var_min = at.find_turn_by_turn_variantions(bbb_offsets_2t, profiles_data.shape[0], ABS=True)
    print(var_max, var_min)
    print(np.max(np.concatenate((var_max, np.abs(var_min)))))

    print('Batch 3')
    var_max, var_min = at.find_turn_by_turn_variantions(bbb_offsets_3t, profiles_data.shape[0], ABS=True)
    print(var_max, var_min)
    print(np.max(np.concatenate((var_max, np.abs(var_min)))))

    print('Batch 4')
    var_max, var_min = at.find_turn_by_turn_variantions(bbb_offsets_4t, profiles_data.shape[0], ABS=True)
    print(var_max, var_min)
    print(np.max(np.concatenate((var_max, np.abs(var_min)))))

    print('Shot-by-shot')
    print('Batch 1')
    var_max, var_min = at.find_shot_by_shot_variantions(bbb_offsets_1t, ABS=True)
    print(var_max, var_min)
    print(np.max(np.array([var_max, np.abs(var_min)])))

    print('Batch 2')
    var_max, var_min = at.find_shot_by_shot_variantions(bbb_offsets_2t, ABS=True)
    print(var_max, var_min)
    print(np.max(np.array([var_max, np.abs(var_min)])))

    print('Batch 3')
    var_max, var_min = at.find_shot_by_shot_variantions(bbb_offsets_3t, ABS=True)
    print(var_max, var_min)
    print(np.max(np.array([var_max, np.abs(var_min)])))

    print('Batch 4')
    var_max, var_min = at.find_shot_by_shot_variantions(bbb_offsets_4t, ABS=True)
    print(var_max, var_min)
    print(np.max(np.array([var_max, np.abs(var_min)])))

if PLT_SBS and SHOT_BY_SHOT:
    plt.figure()
    plt.title('batch 1')
    plt.plot(sbs_bbb_offset_b1.T)

    plt.figure()
    plt.title('batch 2')
    plt.plot(sbs_bbb_offset_b2.T)

    plt.figure()
    plt.title('batch 3')
    plt.plot(sbs_bbb_offset_b3.T)

    plt.figure()
    plt.title('batch 4')
    plt.plot(sbs_bbb_offset_b4.T)

    plt.show()


import numpy as np
import sklearn
import matplotlib.pyplot as plt
import pandas as pd

# This creates data with an outlier
N = 10
x = 1.0 + np.random.uniform(size=N)
y = 20.0 - 10.0 * x + 2.3 * x**2 + 0.2 * np.random.normal(size=N)
y[5] = 30

#Scatter Plot With Outliers
# plt.figure()
# plt.scatter(x,y,c='r', label = "Data points") #c = color
# plt.xlabel("X axis")
# plt.ylabel("Y axis")
# plt.show()

#Supervised Learning Example

from sklearn import linear_model

# Learn
model = linear_model.HuberRegressor() #has by default intercepts=true, can remove
X = x.reshape((-1,1)) #need to reshape bc of the different sizes of the matrix's and vectors
model.fit(X, y) #training the model

# Predict
xx = np.linspace(1, 2, 10)
XX = xx.reshape((-1,1))
yy = model.predict(XX)

# Plot
plt.figure()
plt.scatter(x,y,c='r',label="Data points")
plt.plot(xx,yy,"-*b",label="Predictions")
plt.xlabel("Height [m]")
plt.ylabel("Hair thickness [mm]")
plt.plot("Fitting Using The Optimal Linearing Model")
plt.legend()
plt.show()

print(model.intercept_)
print(model.coef_)


from django.shortcuts import render, redirect
from django.http import QueryDict
from django.utils import dateformat
from .models import Pasien
from .forms import PasienForms, PasienUpdateForms
import datetime
from django.contrib.auth.decorators import login_required

# Create your views here.
@login_required
def index(request):
    context = {
        'title':'dataset antrian',
        'body_judul':'Dataset Antrian Pasien',
    }
    jp      = Pasien.objects.values('jenis_pengobatan').distinct()
    if request.method == "POST" and request.POST['jenis_pengobatan_input'] != 'all':
        jenis_pengobatan_input = request.POST['jenis_pengobatan_input']
        pasien  = Pasien.objects.filter(jenis_pengobatan=jenis_pengobatan_input)
        context.update({
            'jenis_pengobatan_input'    : jenis_pengobatan_input,
        })
    else :
        pasien = Pasien.objects.order_by('-created_at')
        context.update({
            'jenis_pengobatan_input'    : '',
        })
    for pas in pasien:
        pas.durasi_pengobatan = int(pas.durasi_pengobatan)
    context.update({
        'pasien':pasien,
        'jp'    : jp
    })

    return render(request, 'antrian/index.html', context)

@login_required
def jenis_pengobatan(request):
    jenis_pengobatan_input = request.POST.copy()
    print(jenis_pengobatan_input['jenis_pengobatan_input'])
    # pasien  = Pasien.objects.filter(jenis_pengobatan=jenis_pengobatan_input)
    # jp      = Pasien.objects.value('jenis_pengobatan').distinct()

    context = {
        'title':'dataset antrian',
        'body_judul':'Dataset Antrian',
    #     'pasien':pasien,
    #     'jp'    : jp
    }
    return render(request, 'antrian/index.html', context)

@login_required
def selesai(request, pasien_id):
    pasien_update = Pasien.objects.get(id=pasien_id)
    pasien_update.waktu_berakhir = dateformat.format(datetime.datetime.now() , 'H:i:s')
    time1 = datetime.datetime.strptime(pasien_update.waktu_mulai, '%H:%M:%S')
    time2 = datetime.datetime.strptime(pasien_update.waktu_berakhir, '%H:%M:%S')
    durasi = time2-time1
    d = int(durasi.total_seconds())
    pasien_update.durasi_pengobatan = d
    pasien_update.save()
    return redirect('antrian:index')

@login_required
def create(request):
    pasien_form = PasienForms(request.POST.copy() or None)
    pasien = Pasien.objects.all()
    if request.method == "POST":
        post = request.POST.copy()
        post['waktu_mulai'] = dateformat.format(datetime.datetime.now(), 'H:i:s')
        pasien_form = PasienForms(post)
        if pasien_form.is_valid():
            pasien_form.save()
            return redirect('antrian:index')
    context = {
        'title':'dataset antrian',
        'body_judul':'Dataset Antrian',
        'pasien':pasien,
        'pasien_form':pasien_form,
    }
    return render(request, 'antrian/create.html', context)

@login_required
def update(request, pasien_id):
    pasien_update = Pasien.objects.get(id=pasien_id)
    data = {
        'nama_pasien'       : pasien_update.nama_pasien,
        'jenis_kelamin'     : pasien_update.jenis_kelamin,
        'umur'              : pasien_update.umur,
        'nama_dokter'       : pasien_update.nama_dokter,
        'jenis_pengobatan'  : pasien_update.jenis_pengobatan,
        'waktu_mulai'       : pasien_update.waktu_mulai,
        'waktu_berakhir'    : pasien_update.waktu_berakhir,
    }

    pasien_form = PasienUpdateForms(request.POST or None , initial=data, instance=pasien_update )
    if request.method == "POST" :
        if pasien_form.is_valid():
            pasien_form.save()
            return redirect('antrian:index')

    context = {
        'title':'dataset antrian',
        'body_judul':'Dataset Antrian',
        'pasien_form':pasien_form,
    }

    return render(request, 'antrian/create.html', context)

@login_required
def delete(request, pasien_id):
    Pasien.objects.filter(id=pasien_id).delete()
    return redirect('antrian:index')


from celery.utils.log import get_task_logger

from olx_discover import celery, app
from olx_discover.models import AdsOrigin
from olx_discover.views import OlxDiscover

LOGGER = get_task_logger('tasks')

@celery.task
def send_email_on_new_ads():
    with app.app_context():
        ads_origin_list = AdsOrigin.query.all()
        if not ads_origin_list:
            LOGGER.info('Não possuí origem cadastrado')
            return None

        for ads_origin in ads_origin_list:
            olx_discover = OlxDiscover(ads_origin.url)

            try:
                has_sent = olx_discover.send_emails_on_new_ads()
            except Exception as e:
                LOGGER.exception(e)
                has_sent = None

            if has_sent:
                LOGGER.info('Email enviado.')
            else:
                LOGGER.info('Não existem novos Ads para enviar email.')


import itertools

from clld.web.icon import ORDERED_ICONS, MapMarker
from clld.cliutil import add_language_codes
from clld.interfaces import ILanguage
from clld.db.models.common import IdentifierType, Identifier

from pyglottolog.api import Glottolog

from clld_glottologfamily_plugin.models import Family

ISOLATES_ICON = 'cff6600'

class LanguageByFamilyMapMarker(MapMarker):
    def get_icon(self, ctx, req):
        if ILanguage.providedBy(ctx):
            if ctx.family:
                return ctx.family.jsondata['icon']
            return req.registry.settings.get('clld.isolates_icon', ISOLATES_ICON)
        return super(LanguageByFamilyMapMarker, self).get_icon(ctx, req)

def load_families(data,
                  languages,
                  glottolog_repos=None,
                  strict=True,
                  icons=ORDERED_ICONS,
                  isolates_icon=ISOLATES_ICON):
    """Add Family objects to a database and update Language object from Glottolog.

    Family information is retrieved from Glottolog based on the id attribute of a
    language. This id must be either a glottocode or an ISO 639-3 code.

    :param data:
    :return:
    """
    api = Glottolog(glottolog_repos)
    icons = itertools.cycle(
        [getattr(i, 'name', i) for i in icons if getattr(i, 'name', i) != isolates_icon])
    languoids_by_code = api.languoids_by_code()
    for language in languages:
        if isinstance(language, (tuple, list)) and len(language) == 2:
            code, language = language
        else:
            code = language.id
        gl_language = languoids_by_code.get(code)
        if strict and not gl_language:
            raise KeyError(code)
        gl_family = None
        if gl_language:
            if not gl_language.lineage:
                if gl_language.level.id == api.languoid_levels.family.id:
                    # Make sure top-level families are not treated as isolates!
                    gl_family = gl_language
            else:
                gl_family = languoids_by_code[gl_language.lineage[0][1]]
            language.macroarea = \
                gl_language.macroareas[0].name if gl_language.macroareas else None
            add_language_codes(
                data, language, gl_language.iso, glottocode=gl_language.id)
            for attr in 'latitude', 'longitude', 'name':
                if getattr(language, attr) is None:
                    setattr(language, attr, getattr(gl_language, attr))

        if gl_family:
            family = data['Family'].get(gl_family.id)
            if not family:
                family = data.add(
                    Family,
                    gl_family.id,
                    id=gl_family.id,
                    name=gl_family.name,
                    description=Identifier(
                        name=gl_family.id, type=IdentifierType.glottolog.value).url(),
                    jsondata=dict(icon=next(icons)))
            language.family = family


import cv2 as cv

img = cv.imread('FaceDetect/resource/1.jpg')
# 灰度
gray_img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
cv.imshow('gray',gray_img)
cv.imwrite('FaceDetect/resource/gray_face1.jpg',gray_img)
# 修改尺寸
cv.imshow('FaceDetect/resource/read_img',img)
cv.waitKey(0)
cv.destroyAllWindows()


import torch.nn as nn

class NeuralNetwork(nn.Module):
    """
    Deep mind dueling network
    """
    hidden_layer = 512

    def __init__(self, number_of_outputs):
        super(NeuralNetwork, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=4, out_channels=32, kernel_size=8,
                               stride=4)
        self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=4,
                               stride=2)
        self.conv3 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3,
                               stride=1)

        self.advantage1 = nn.Linear(7 * 7 * 64, self.hidden_layer)
        self.advantage2 = nn.Linear(self.hidden_layer, number_of_outputs)

        self.value1 = nn.Linear(7 * 7 * 64, self.hidden_layer)
        self.value2 = nn.Linear(self.hidden_layer, 1)

        self.activation = nn.ReLU()

    def forward(self, x):
        x = x / 255
        output_conv = self.conv1(x)
        output_conv = self.activation(output_conv)
        output_conv = self.conv2(output_conv)
        output_conv = self.activation(output_conv)
        output_conv = self.conv3(output_conv)
        output_conv = self.activation(output_conv)

        output_conv = output_conv.view(output_conv.size(0), -1)  # flatten
        # Dueling
        output_advantage = self.advantage1(output_conv)
        output_advantage = self.activation(output_advantage)
        output_advantage = self.advantage2(output_advantage)

        output_value = self.value1(output_conv)
        output_value = self.activation(output_value)
        output_value = self.value2(output_value)

        output_final = output_value + output_advantage - output_advantage.mean()

        return output_final


from django.shortcuts import render
import csv
from pprint import pprint

def inflation_view(request):
    data_list = []
    template_name = 'inflation.html'
    i = 0
    with open('inflation_russia.csv', encoding='utf8', newline='') as csvfile:
        reader = csv.reader(csvfile, delimiter=';')
        for rows in reader:
            i+=1
            if i!=1:
                buf_rows = [float(x) for x in rows if (x != '') and (x != rows[0])]
                buf_rows.insert(0,rows[0])
                data_list.append(buf_rows)
    for list in data_list:
        if len(list) < 14:
            list.insert(len(list)+1, '')
            list.insert(len(list) + 1, '')
            list.insert(len(list) + 1, '')
            list.insert(len(list) + 1, '')
    head_list = ['Год','Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек', 'Суммарная']

    # чтение csv-файла и заполнение контекста
    context =  {'head_list': head_list,
                'data_list': data_list}

    return render(request, template_name,
                  context)


from sqlalchemy.orm import sessionmaker
from main import Projektas, engine

Session = sessionmaker(bind=engine) #susikuriam session ir skliaustuose nurodom su kokiu dalyku norim susieti
session = Session()

# CREATE --------------------------------------------------------------------------------
# projektas1 = Projektas("Naujas pr.", 20000)
# session.add(projektas1)
# session.commit()
#
# projektas2 = Projektas("Mazas", 750)
# session.add(projektas2)
# session.commit()

# READ --------------------------------------------------------------------------------
# projektas1 = session.get(Projektas, 1) # KREIPIAMES I KLASE !!
# projektas2 = session.query(Projektas).filter_by(name="2 projektas").one()
#
# print(projektas1)
# print(projektas2.name)

# search = session.query(Projektas).filter(Projektas.name.ilike("2%")).all() #.all grazina visas reiksme liste
# search2 = session.query(Projektas).filter(Projektas.price > 1000).all()
# search3 = session.query(Projektas).filter(Projektas.price > 1000, Projektas.name.ilike("2%")).all()
#
# print(search2)

# UPDATE --------------------------------------------------------------------------------
#reikia pirma issitraukti ir tik tada pakeisti
#
# projektas1 = session.get(Projektas, 4)
# projektas1.price = 22000
# projektas1.name = "Naujausias"
# session.commit()

# kitas variantas kuris daro update pagal price
# projektas2 = session.query(Projektas).filter_by(price=22000.0).one()
# projektas2.name = "2 projektas tikrai"
# session.commit()

# DELETE --------------------------------------------------------------------------------
# projektas1 = session.query(Projektas).filter_by(name="Mazas").one()
# session.delete(projektas1)
# session.commit()

# --------------------------------- PAVYZDYS-------------------------------
while True:
    pasirinkimas = int(input("Pasirinkite veiksmą: \n1 - atvaizduoti projektus \n2 - sukurti projektą \n3 - pakeisti projektą \n4 - ištrinti projektą\n"))

    if pasirinkimas == 1:
        projektai = session.query(Projektas).all()
        print("-------------------")
        for projektas in projektai:
            print(projektas)
        print("-------------------")

    if pasirinkimas == 2:
        name = input("Įveskite projekto pavadinimą")
        price = float(input("Įveskite projekto kainą"))
        projektas = Projektas(name, price)
        session.add(projektas)
        session.commit()

    if pasirinkimas == 3:
        projektai = session.query(Projektas).all()
        print("-------------------")
        for projektas in projektai:
            print(projektas)
        print("-------------------")
        keiciamo_id = int(input("Pasirinkite norimo pakeisti projekto ID"))
        keiciamas_projektas = session.query(Projektas).get(keiciamo_id)
        pakeitimas = int(input("Ką norite pakeisti: 1 - pavadinimą, 2 - kainą"))
        if pakeitimas == 1:
            keiciamas_projektas.name = input("Įveskite projekto pavadinimą")
        if pakeitimas == 2:
            keiciamas_projektas.price = float(input("Įveskite projekto kainą"))
        session.commit()

    if pasirinkimas == 4:
        projektai = session.query(Projektas).all()
        print("-------------------")
        for projektas in projektai:
            print(projektas)
        print("-------------------")
        trinamo_id = int(input("Pasirinkite norimo ištrinti projekto ID"))
        trinamas_projektas = session.query(Projektas).get(trinamo_id)
        session.delete(trinamas_projektas)
        session.commit()


"""
Matt Russell
University of Washington
Department of Aeronautics & Astronautics
6/9/2021
Main program file for final
"""
import numpy as np
import matplotlib.pyplot as plt
""" Problem 2 """
phiS_minus_phiP = np.asarray([-50.0,-100.0,-150.0,-200.0]) # [V] - electrostatic potential difference between sheath (S) and plasma (P)
Te = np.asarray([12.5, 16.5, 12.5, 10.0]) # [eV] - determined empirically

k_B = 1.38e-23 # [J/degK]
e = 1.6e-19

eV_to_degK = 11600.0 # 1 eV = this many degK
Joules_to_eV = (1.0/1.6)*(1.0e19)
amu_to_kg = 1.67e-27
cm_to_m = 1.0e-2

m_e = 9.11e-31 # [kg]
m_i = 131.0*amu_to_kg # [kg]<-[amu] Xenon atomic mass
n_s = 0.25e12/(cm_to_m**3) # [m^-3]<-[cm^-3] Quasineutral sheath density

r_out = 7.0*cm_to_m # [m]<-[cm]
r_in = 3.0*cm_to_m # [m]<-[cm]
L = 4.0*cm_to_m # [m]<-[cm] Length of the plasma channel
A_w = 2.0*np.pi*L*(r_in + r_out) # [m] Total area of the wall

eta_current = 0.75
eta_voltage = 0.90
I_d = 10.0 # [A]
V_d = 300.0 # [V]
I_b = eta_current*I_d
V_b = eta_voltage*V_d
P_d = I_d * V_b

P_we = np.zeros(phiS_minus_phiP.size)
P_wi = np.zeros(phiS_minus_phiP.size)
P_w = np.zeros(phiS_minus_phiP.size)
E_ions = np.zeros(phiS_minus_phiP.size)

idx = 0
Te_vs_Phi = plt.figure()
Pwe_vs_Phi = plt.figure()
Pwi_vs_Phi = plt.figure()
Pw_vs_Phi = plt.figure()
Eion_vs_Phi = plt.figure()
for phi in phiS_minus_phiP:
    v_is = np.sqrt((k_B*eV_to_degK*Te[idx])/m_i)
    P_we[idx] = 0.25*np.sqrt((8.0*k_B*eV_to_degK*Te[idx])/(np.pi*m_e))*n_s*A_w \
    *np.exp((e*phi)/(k_B*eV_to_degK*Te[idx]))*2.0*k_B*eV_to_degK*Te[idx]
    P_wi[idx] = n_s*v_is*A_w*(0.5*m_i*v_is**2 - e*phi)
    P_we[idx] = P_we[idx]/P_d
    P_wi[idx] = P_wi[idx]/P_d
    P_w[idx] = P_we[idx] + P_wi[idx]
    E_ions[idx] = Joules_to_eV*k_B*eV_to_degK*Te[idx]*(0.5 + np.log(np.sqrt((2.0*m_i)/(np.pi*m_e))))
    idx += 1

plt.figure(Te_vs_Phi.number)
plt.scatter(phiS_minus_phiP,Te)
plt.xlabel('$\phi_{s} - \phi_{p}$ [V]')
plt.ylabel('Electron Temperature [eV]')
plt.title('Electron Temperature')

plt.figure(Pwe_vs_Phi.number)
plt.scatter(phiS_minus_phiP,P_we)
plt.xlabel('$\phi_{s} - \phi_{p}$ [V]')
plt.ylabel('$\\frac{P_{w,e}}{P_{d}}$')
plt.title('Wall loss - electrons')

plt.figure(Pwi_vs_Phi.number)
plt.scatter(phiS_minus_phiP,P_wi)
plt.xlabel('$\phi_{s} - \phi_{p}$ [V]')
plt.ylabel('$\\frac{P_{w,i}}{P_{d}}$')
plt.title('Wall loss - ions')

plt.figure(Pw_vs_Phi.number)
plt.scatter(phiS_minus_phiP,P_w)
plt.xlabel('$\phi_{s} - \phi_{p}$ [V]')
plt.ylabel('$\\frac{P_{w}}{P_{d}}$')
plt.title('Total Wall losses')

print(E_ions)
plt.figure(Eion_vs_Phi.number)
plt.scatter(phiS_minus_phiP,E_ions)
plt.xlabel('$\phi_{s} - \phi_{p}$ [V]')
plt.ylabel('Ion energy [eV]')
plt.title('Energy of wall bombardment')

""" Problem 3 """

plt.show()


import requests
from bs4 import BeautifulSoup
from collections import defaultdict

url = 'https://en.wikipedia.org/wiki/List_of_London_Underground_stations'
dic_url = 'http://www.greenworm.net/sites/default/files/gw-assets/enable1-wwf-v4.0-wordlist.txt'

p = requests.get(url)
soup = BeautifulSoup(p.content, 'html.parser')
table = soup.find(class_ = 'wikitable')
stations = [row.find('th').text[:-1].upper() for row in table.findAll('tr')][1:]

##with open('clean_dictionary.txt', 'r') as f:
##    words = [w[:-1] for w in f.readlines()]

words = requests.get(dic_url).text.split()
words = [w.upper() for w in words]

word_stations = [station for station in stations
        if all([word if word in words else False for word in station.split()])]

##with open('c:/Users/Ferd/Documents/Crossword-Filler/themes/tube_stations.txt', 'w') as f:
##    for station in word_stations:
##        f.write(''.join(station.split())+'\n')

word_frequency = defaultdict(int)

for station in stations:
    for word in station.split():
        word_frequency[word] += 1

word_frequency = [(key, word_frequency[key]) for key in word_frequency.keys()]
word_frequency.sort(key=lambda x: x[1], reverse=True)


# coding: utf-8

# In[16]:

from __future__ import print_function
import numpy as np
import tensorflow as tf
from tensorflow.python.client import timeline
import os
import pandas as pd
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt

# In[17]:

#shape argument is optional
def weight_variable(shape,name=None):
    initializer = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initializer,name=name)

def bias_variable(shape, name=None):
    initializer = tf.constant(0.1, shape=shape)
    return tf.Variable(initializer, name=name)

def offset_variable(shape, name=None):
    print(shape)
    initializer = tf.constant(0.1, shape=shape)
    return tf.Variable(initializer, name=name)

def conv2d(x, W, strides, name=None):
    return tf.nn.conv2d(x, filter=W, strides=strides, padding='VALID', data_format="NCHW", name=name)

def max_pool_2x2(x, name=None):
    return tf.nn.max_pool(x, ksize=[1, 1, 2, 2],
                        strides=[1, 1, 2, 2], padding='SAME', data_format="NCHW", name=name)

def batch_normalization(x, offset=None, name = None):
    mean, variance = tf.nn.moments(x, axes=[0, 1, 2], shift=None, name=None, keep_dims=False)
    #momnets -- used with convolutional filters with shape [batch, height, width, depth]
    return tf.nn.batch_normalization(x, mean, variance, offset=None, scale=None, variance_epsilon = 1e-6, name=name)

# In[18]:

# Read data from csv file.
# Path to all data:  /global/cscratch1/sd/muszyng/data_astronomy_catalogs/trainingData.csv
df = np.genfromtxt('trainingData.csv', delimiter=" ")

# In[19]:

print(df.shape)

# In[20]:

# Create array of labels.
labels = df[:,-1]
print(labels)

# In[21]:

# Create binary matrix of labels.
nb_classes = 4
mat_labels = np.zeros([nb_classes, len(labels)], dtype=int)
print(mat_labels)

# In[22]:

# Convert labels to binary matrix.
for i in range(0, len(labels)):
    l = int(labels[i])
    mat_labels[l, i] = 1
print(mat_labels)

# In[29]:

train_image_size = df.shape[1] #input size
channel = 1
num_classes = 4
image_data =  tf.convert_to_tensor(df)
labels_one_hot = np.transpose(mat_labels, [1,0])

train_size = 2100000 #number of samples for training= total number of samples-test samples
train_images = image_data[:train_size]
train_labels = labels_one_hot[:train_size]
test_images = image_data[train_size:]
test_labels = labels_one_hot[train_size:]
print(image_data.shape)

# In[31]:

#model begins
run_metadata = tf.RunMetadata()
inforstring = os.getenv('inforstring')
trace_file = open('timeline'+str(inforstring)+'.ctf.json', 'w')

tf.app.flags.DEFINE_boolean('trace_flag', True, """If set, it produces an a trace of the threads  executing work during the training phase.""")
tf.app.flags.DEFINE_integer('epoch', 10, """Epochs to train the model.""")

x_train = np.float32(train_images)
test_images = np.float32(test_images)
y_train = np.float32(train_labels)

# In[9]:

#init placeholders
x = tf.placeholder(tf.float32, shape = [None, train_image_size ]) #change this to the vector shape
y = tf.placeholder(tf.float32, shape = [None, num_classes])

#dense, initializing the variables
W_fc1 = weight_variable([64, 32],name="W_fc1")
b_fc1 = bias_variable([32],name="b_fc1")
W_fc2 = weight_variable([32, 4],name="W_fc2")
b_fc2 = bias_variable([4],name="b_fc1")

# In[12]:

x_input = tf.reshape(x, [-1, train_image_size])

#dense 1
h_fc1 = tf.nn.relu(tf.matmul(x_input, W_fc1) + b_fc1)
dropout = tf.layers.dropout(h_fc1, rate=0.5)
#dense 2
y_conv = tf.matmul(dropout, W_fc2) + b_fc2

#graph construction done

cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=y_conv))

train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

# In[15]:

if (os.getenv('NUM_INTER_THREADS', None) is not None and os.getenv('NUM_INTRA_THREADS', None) is not None):
    print("Custom NERSC/Intel config:inter_op_parallelism_threads({}),""intra_op_parallelism_threads({})".format(os.environ['NUM_INTER_THREADS'],os.environ['NUM_INTRA_THREADS']))
    sess = tf.Session(config=tf.ConfigProto(inter_op_parallelism_threads=int(os.environ['NUM_INTER_THREADS']),intra_op_parallelism_threads=int(os.environ['NUM_INTRA_THREADS'])))

#batch size = all data entries
FLAGS = tf.app.flags.FLAGS
epoch = FLAGS.epoch

batch_size = 100
max_step = epoch*train_size/batch_size
print("max steps: ", max_step)
with tf.Session() as sess:
    if FLAGS.trace_flag:
        sess.run(tf.global_variables_initializer(),  options=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE), run_metadata=run_metadata)
    else:
        sess.run(tf.global_variables_initializer())
    for i in range(max_step):
        train_step.run(feed_dict={x: x_train[i*batch_size%train_size:i*batch_size%train_size+batch_size], y: y_train[i*batch_size%train_size:i*batch_size%train_size+batch_size,:]})
        if ((i+1)*batch_size) % train_size == 0:
            correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y,1))
            accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
            print("Training Accuracy:")
            if FLAGS.trace_flag:
                print(sess.run(accuracy, feed_dict={x: x_train, y: y_train}, options=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE), run_metadata=run_metadata))
            else:
                print(sess.run(accuracy, feed_dict={x: x_train, y: y_train}))

    train_step.run(feed_dict={x: test_images[:,:], y: test_labels[:,:]})

    correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y,1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    print("Test Accuracy: \n")
    if FLAGS.trace_flag:
        print(sess.run(accuracy, feed_dict={x: test_images, y: test_labels}, options=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE), run_metadata=run_metadata))
    else:
        print(sess.run(accuracy, feed_dict={x: test_images, y: test_labels}))

    print("Shapes:")
    predictor = tf.argmax(y_conv,1)
    y_pred = sess.run(predictor, feed_dict={x: test_images})
    print(y_pred)

    y_truth = labels[train_size:]
    print(y_truth)

    print(y_pred.shape)
    print(y_truth.shape)

    cmat = confusion_matrix(y_truth, y_pred)
    print(cmat)

    np.savetxt('truth_labels.txt', y_truth)
    np.savetxt('pred_labels.txt', y_pred)

if FLAGS.trace_flag:
    trace = timeline.Timeline(step_stats=run_metadata.step_stats)
    trace_file.write(trace.generate_chrome_trace_format())
    trace_file.close()

print ("printing weights, 64*32, 32*4: ", W_fc1, W_fc2)


import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import time
import os

COUNTY = "east_baton_rouge"
fileDir = os.path.dirname(__file__)
filePath = os.path.join(fileDir, "../data/east_baton_rouge.txt")
filePath = os.path.abspath(os.path.realpath(filePath))
f = open(filePath, 'w')
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
driver = webdriver.Chrome(ChromeDriverManager().install(), options = chrome_options)

def scraping(url):
    print("Scraping from " + url)
    f.write("\n\n\n")
    f.write("Scraping from " + url + "\n\n\n")
    driver.get(url)
    time.sleep(1)
    result = driver.execute_script("return document.documentElement.outerHTML")
    return BeautifulSoup(result, 'html.parser')

soup = scraping("https://www.brla.gov/2175/Restart-BR")
data = soup.find_all(class_= "secondaryNavItem")
list = set()
for i in range(len(data)):
    list.add("https://www.brla.gov" + data[i]['href'])

sublinks = set()
for i in list:
    soup = scraping(i)
    data1 = soup.find(id = "page")
    data = data1.find_all("li")
    for i in range(len(data)):
        f.write(data[i].get_text(separator = '\n'))
    data = data1.find_all("p")
    for i in range(len(data)):
        f.write(data[i].get_text(separator = '\n'))
    data = soup.find(id = "page")
    data = data.find_all("a")
    for i in range(len(data)):
        sublinks.add(data[i]['href'])

for i in sublinks:
    if i[0] == "/":
        sublinks.remove(i)
        sublinks.add("https://www.brla.gov" + i)

PDFS = []
for i in sublinks:
    if "Word" in i:
        continue
    if ("Center/View" in i and "brla.gov" in i) or ".pdf" in i or "brla.gov/businessguidelines" in i:
        PDFS.append(i)
    elif "brla.gov" in i:
        soup = scraping(i)
        data = soup.find_all("p")
        for y in range(len(data)):
            f.write(data[y].get_text(separator = '\n'))

import glob

import requests

path = "../data/" + COUNTY + "-PDF"
fileDir = os.path.dirname(__file__)
filePath = os.path.join(fileDir, path)
filePath = os.path.abspath(os.path.realpath(filePath))
os.makedirs(filePath, exist_ok=True)

def getPDFs(file_url, county):
    title = file_url.split('/').pop()
    if ".pdf" not in title:
        title += ".pdf"
    r = requests.get(file_url, stream = True)
    with open("../data/" + county + "-PDF" + "/" + title,"wb") as pdf:
        for chunk in r.iter_content(chunk_size=1024*1024):
            pdf.write(chunk)

for url in PDFS:
    getPDFs(url, COUNTY)

driver.quit()
print("finished")


from collections import deque

c = 11
b = 2

#   코나의 위치 변화
#   코니는 처음 위치에서 1초후 1만큼, 매초마다 이전 이동거리 +1 만큼 움직인다.
#   즉, 증가하는 속도가 1초마다 1씩 증가.
#   속도 : 1, 2, 3, 4, 5, 6,..
#   시간에 따라 더 해주면 된다.
#    1 2 3 4  5
#   3 4 6 9 13 18

#   브라운의 위치 변화.
#   B - 1, B + 1, 2 * B

#   모든 경우의 수 나열 -> BFS를 사용.
#   잡았다! 는 똑같은 시간에 똑같은 위치에 존재.
#   시간은 + 1
#   위치는 코니도 브라운도 값이 자유자재.
#   규칙적 -> 배열 / 자유자재 -> dict

#   각 시간마다 브라운이 갈 수 있는 위치를 저장
#   visited = [{} for _ in range(200001)] -> 시간과 위치를 알고 있으면 즉각적으로 알수있는 자료구조.
#   visited [0] = {   -> 0은 time
#       2: True    -> location
#   }
#   visited [1] = {
#       1: True,
#       3: True,
#       4: True
#   }
#   즉, visited[time][cony_loc] 하면 도달했는지 도달하지 않았는지 알 수 있다.
#   즉, visited[위치][시간] -> visited[3] 에 5 라는 키가 있냐? 라고 하면 3위치에 5초에 간 적이 있냐? 이다.
#   0   1   2   -> visited[2] = { 0 : True, 2 : True}
#   2 ->1   0   -> visited[1] = { 1 : True }
#       3   2   -> visited[3] = { 1 : True }
#       4   3   -> visited[4] = { 1 : True }

def catch_me(cony_loc, brown_loc):
    time = 0
    queue = deque()
    queue.append((brown_loc, 0))  # 위치와 시간을 동시에 담아준다. 즉, 위치와 시간이 같아야 만났다라고 할 수 있기 때문.
    visited = [{} for _ in range(200001)]  # -> 200000만개의 딕셔너리를 배열 안에 넣는다는 의미

    while cony_loc <= 200000:
        cony_loc += time  # 시간만큼 이동 즉, +1 +2 +3 +4..
        if time in visited[cony_loc]:
            return time

        for i in range(0, len(queue)):
            current_position, current_time = queue.popleft()

            new_time = current_time

            new_position = current_position - 1
            if 0 <= new_position <= 200000:
                queue.append((new_position, new_time))
            new_position = current_position + 1
            if 0 <= new_position <= 200000:
                queue.append((new_position, new_time))
            new_position = current_position * 2
            if 0 <= new_position <= 200000:
                queue.append((new_position, new_time))

    return -1

print(catch_me(c, b))  # 5가 나와야 합니다!


from functools import wraps
from flask import request
from project.main.service.auth_helper import Auth

def \
        token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        data, status = Auth.get_logged_in_user(request)
        print("decorator token_required data: {}".format(data))
        token = data.get('data')
        if not token:
            return data, status

        return f(*args, **kwargs)

    return decorated

def admin_token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        data, status = Auth.get_logged_in_user(request)
        token = data.get('data')

        if not token:
            return data, status

        admin = token.get('admin')
        if not admin:
            response = {
                'status': 'fail',
                'message': 'admin token required'
            }
            return response, 401

        return f(*args, **kwargs)

    return decorated

def self_or_admin_required(public_id: str):
    """only self or admin could visit"""
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            data, status = Auth.get_logged_in_user(request)
            token = data.get('data')

            if not token:
                return data, status

            admin = token.get('admin')
            if admin or public_id == data.get('public_id'):
                return f(*args, **kwargs)
            response = {
                'status': 'fail',
                'message': 'admin token required'
            }
            return response, 401

        return wrapper

    return decorator


# -*- coding: utf-8 -*-
"""

@author: barengific
"""
#testing class list

import numpy as np
import cv2

img = cv2.imread(r'D:\Python\land.jpg')
#print(type(img))
#print(img)
#print(img.shape)

rows = open(r'D:\Python\words.txt').read().strip().split("\n")

clas = [r[r.find(' ') + 1: ] for r in rows]

for(i,c) in enumerate(clas):
    if i==4:
        break
    print(i,c)

cv2.imshow('Image', img)
cv2.waitKey(0)


import glob
import logging
import numpy as np
import os
import random
import torch
import torch.utils.data
import h5py
from tqdm import tqdm

device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')

class ImNetImageSamples(torch.utils.data.Dataset):
    def __init__(self,
                 data_path: str,
                 auto_encoder=None,
                 max_batch=32,
                 sample_interval=1,
                 image_idx=None,
                 sample_voxel_size: int = 64,
                 ):
        super(ImNetImageSamples, self).__init__()
        data_dict = h5py.File(data_path, 'r')
        self.data_voxels = data_dict['voxels'][:]
        self.data_voxels = np.reshape(self.data_voxels, [-1, 1, self.data_voxels.shape[1], self.data_voxels.shape[2],
                                                         self.data_voxels.shape[3]])
        self.data_values = data_dict['values_' + str(sample_voxel_size)][:].astype(np.float32)
        self.data_points = (data_dict['points_' + str(sample_voxel_size)][:].astype(np.float32) + 0.5) / 256 - 0.5

        ### get file
        label_txt_path = data_path[:-5] + '.txt'
        self.obj_paths = [os.path.basename(line).rstrip('\n') for line in open(label_txt_path, mode='r').readlines()]

        ### extract the latent vector
        if auto_encoder is not None:
            self.extract_latent_vector(data_voxels = self.data_voxels, auto_encoder = auto_encoder, max_batch = max_batch)

        ### interval
        self.sample_interval = sample_interval

        ### views num
        self.view_num = 24
        self.view_size = 137
        self.crop_size = 128
        self.crop_edge = self.view_size - self.crop_size

        ### pixels
        self.crop_size = 128
        offset_x = int(self.crop_edge / 2)
        offset_y = int(self.crop_edge / 2)
        self.data_pixels = np.reshape(
            data_dict['pixels'][:, :, offset_y:offset_y + self.crop_size, offset_x:offset_x + self.crop_size],
            [-1, self.view_num, 1, self.crop_size, self.crop_size])

        self.image_idx = image_idx

    def __len__(self):
        return self.data_pixels.shape[0] // self.sample_interval

    def __getitem__(self, idx):

        idx = idx * self.sample_interval

        if self.image_idx is None:
            view_index = np.random.randint(0, self.view_num)
        else:
            view_index = self.image_idx

        image = self.data_pixels[idx, view_index].astype(np.float32) / 255.0

        if hasattr(self, 'latent_vectors'):
            latent_vector_gt = self.latent_vectors[idx]
        else:
            latent_vector_gt = None

        processed_inputs = image, latent_vector_gt

        return processed_inputs, idx

    def extract_latent_vector(self, data_voxels,  auto_encoder, max_batch):

        num_batch = int(np.ceil(data_voxels.shape[0] / max_batch))

        results = []
        print("start to extract GT!!!")
        with tqdm(range(num_batch), unit='batch') as tlist:
            for i in tlist:
                batched_voxels = data_voxels[i*max_batch:(i+1)*max_batch].astype(np.float32)
                batched_voxels = torch.from_numpy(batched_voxels).float().to(device)

                latent_vectors = auto_encoder.encoder(batched_voxels).detach().cpu().numpy()
                results.append(latent_vectors)

        if len(results) == 1:
            self.latent_vectors = results
        else:
            self.latent_vectors = np.concatenate(tuple(results), axis = 0)
        print("Done the extraction of GT!!!")

class ImNetSamples(torch.utils.data.Dataset):
    def __init__(self,
                 data_path: str,
                 sample_voxel_size: int,
                 interval=1):
        super(ImNetSamples, self).__init__()
        self.sample_voxel_size = sample_voxel_size
        data_dict = h5py.File(data_path, 'r')
        self.data_points = (data_dict['points_' + str(self.sample_voxel_size)][:].astype(np.float32) + 0.5) / 256 - 0.5
        self.data_values = data_dict['values_' + str(self.sample_voxel_size)][:].astype(np.float32)
        self.data_voxels = data_dict['voxels'][:]
        self.data_voxels = np.reshape(self.data_voxels, [-1, 1, self.data_voxels.shape[1], self.data_voxels.shape[2],
                                                         self.data_voxels.shape[3]])

        ### get file
        label_txt_path = data_path[:-5] + '.txt'
        self.obj_paths = [os.path.basename(line).rstrip('\n') for line in open(label_txt_path, mode='r').readlines()]

        ## interval
        self.interval = interval

    def __len__(self):
        return self.data_points.shape[0] // self.interval

    def __getitem__(self, idx):

        idx = idx * self.interval

        processed_inputs = self.data_voxels[idx].astype(np.float32), self.data_points[idx].astype(np.float32), \
                           self.data_values[idx]

        return processed_inputs, idx


import logging

import docker

from services.shemas.service import ServiceRun

logging.basicConfig(level=logging.INFO)

class ContainerManager:

    def __init__(self):
        self._client = docker.from_env()

    async def get_container_list(self):
        return [
            {'name': container.name, 'short_id': container.short_id, 'status': container.status}
            for container in self._client.containers.list(all=True)]

    async def run_service(self, service: ServiceRun):
        container = self._client.containers.run('esmdev/test_platform:0.3',
                                                environment=[f'BOT_TOKEN={service.token}', f'URL={service.repository_url}',
                                                             f'EXEC_FILE={service.py_file}'], detach=True)
        return {'name': container.name, 'short_id': container.short_id, 'status': container.status}

    async def stop_service(self, short_id: str):
        container = self._client.containers.get(short_id)
        container.stop()
        return {'name': container.name, 'short_id': container.short_id, 'status': container.status}

    async def get_service_by_id(self, service_id):
        container = self._client.containers.get(service_id)
        return {'name': container.name, 'short_id': container.short_id, 'status': container.status}


import asyncio
import importlib
import logging
import re
import sys
from dataclasses import dataclass
from typing import Any, List, Type, TypeVar, Union

import ujson as json
from action.errors import UserReadableException
from bgcalc.adapter.abstract import AbstractBgClient, AbstractResultWrapper
from bgcalc.errors import BgCalcError, CalcTaskNotFoundError
from dataclasses_json import dataclass_json
from redis import Redis
from rq import Queue
from rq.exceptions import NoSuchJobError
from rq.job import Job
from rq_scheduler import Scheduler

T = TypeVar('T')

@dataclass_json
@dataclass
class ExcParams:
    path: str  # name with path to exception class
    args: List[Any]  # list of json serializable args

class JSONSerializedError(Exception):
    def __init__(self, exc_params: ExcParams):
        super().__init__(exc_params.to_json())

def handle_custom_exception(func):
    async def wrapper(*args, **kwargs):
        try:
            return await func(*args, **kwargs)
        except Exception as e:
            # compose exception name with path
            module = e.__class__.__module__
            if module is None or module == str.__class__.__module__:
                path = e.__class__.__name__  # Avoid reporting __builtin__
            else:
                path = module + '.' + e.__class__.__name__

            raise JSONSerializedError(ExcParams(path, e.args)) from e
    return wrapper

class ResultWrapper(AbstractResultWrapper[T]):

    status_map = dict(
        queued='PENDING',
        started='STARTED',
        deferred='deferred',  # TODO Rq specific
        finished='SUCCESS',
        failed='FAILURE'
    )

    def __init__(self, job):
        self._job = job
        self.result: Union[T, Exception] = None

    def _infer_error(self, exc_info, job_id):
        last = [x for x in re.split(r'\n', exc_info) if x.strip() != ''][-1]
        srch = re.match(r'^([\w_\.]+):\s+(.+)$', last)
        if srch is not None:
            exc_params = ExcParams(srch.group(1), [srch.group(2)])
            if exc_params.path.endswith(JSONSerializedError.__name__):
                exc_params = ExcParams.from_json(srch.group(2))

            if '.' in exc_params.path:
                module, cls_name = exc_params.path.rsplit('.', 1)
                try:
                    m = importlib.import_module(module)
                    cls = getattr(m, cls_name, None)
                    err = cls(*exc_params.args) if cls else Exception(*exc_params.args)
                except ModuleNotFoundError:
                    logging.getLogger(__name__).warning(
                        'Failed to infer calc backend job error {}'.format(exc_params.path))
                    err = Exception(f'Task failed: {job_id}')
            else:
                cls = getattr(sys.modules['builtins'], exc_params.path, None)
                err = cls(*exc_params.args) if cls else Exception(*exc_params.args)
            return err
        return Exception(f'Task failed: {job_id}')

    async def get(self, timeout=None):
        try:
            total_time = 0
            while True:
                await asyncio.sleep(0.5)
                if self._job.is_finished:
                    self.result = self._job.result
                    break
                elif self._job.is_failed:
                    self._job.refresh()
                    self.result = self._infer_error(self._job.exc_info, self._job.id)
                    break
                elif timeout and total_time > timeout:
                    self.result = Exception(f'Task result timeout: {self._job}')
                    break
                total_time += 0.5
        except Exception as e:
            self.result = e
        return self.result

    @property
    def status(self):
        if self._job and self._job.get_status():
            return ResultWrapper.status_map[self._job.get_status()]
        return 'FAILURE'

    @property
    def id(self):
        return self._job.id

class RqConfig:
    HOST = None
    PORT = None
    DB = None
    SCHEDULER_CONF_PATH = None

class Control:

    def __init__(self, redis_conn):
        self._conn = redis_conn

    def revoke(self, task_id, terminate=None, signal=None):
        try:
            job = Job.fetch(task_id, connection=self._conn)
            job.cancel()
        except NoSuchJobError as ex:
            raise CalcTaskNotFoundError(str(ex))

class RqClient(AbstractBgClient):

    def __init__(self, conf: RqConfig, prefix: str = ''):
        self.redis_conn = Redis(host=conf.HOST, port=conf.PORT, db=conf.DB)
        self.queue = Queue(connection=self.redis_conn)
        self.prefix = prefix
        self.scheduler = Scheduler(connection=self.redis_conn, queue=self.queue)
        self.scheduler_conf_path = conf.SCHEDULER_CONF_PATH
        self._control = Control(self.redis_conn)

    def init_scheduler(self):
        # remove old scheduled tasks
        for job in self.scheduler.get_jobs():
            self.scheduler.cancel(job)

        # create new tasks from config file
        if self.scheduler_conf_path:
            with open(self.scheduler_conf_path) as f:
                for entry in json.load(f):
                    self.scheduler.cron(
                        entry['schedule'],
                        f'{self.prefix}.{entry["task"]}',
                        kwargs=entry['kwargs'] if 'kwargs' in entry else None,
                        use_local_timezone=True,
                    )
            logging.getLogger(__name__).info(
                f'Loaded configuration for Rq-scheduler from {self.scheduler_conf_path}')
        else:
            logging.getLogger(__name__).warning(
                'No Rq-scheduler configuration path defined. '
                'Regular system maintenance will be disabled which may lead to disks becoming full.')

    @staticmethod
    def _resolve_limit(softl, hardl):
        if softl is not None and hardl is not None:
            return min(softl, hardl)
        elif softl is not None:
            return softl
        elif hardl is not None:
            return hardl
        return None

    @property
    def control(self):
        return self._control

    def send_task_sync(self, name, ans_type: Type[T], args=None, time_limit=None, soft_time_limit=None) -> ResultWrapper[T]:
        tl = self._resolve_limit(time_limit, soft_time_limit)
        try:
            job = self.queue.enqueue(f'{self.prefix}.{name}', job_timeout=tl, args=args)
            return ResultWrapper(job)
        except Exception as ex:
            logging.getLogger(__name__).error(ex)

    async def send_task(self, name, ans_type: Type[T], args=None, time_limit=None, soft_time_limit=None) -> ResultWrapper[T]:
        """
        Send a task to the worker.

        Please note that Rq does not know hard vs. soft time limit. In case both
        values are filled in (time_limit, soft_time_limit), the smaller one is
        selected. Otherwise, the non-None is applied.
        """
        return await asyncio.get_event_loop().run_in_executor(
            None, self.send_task_sync, name, ans_type, args, time_limit, soft_time_limit)

    def get_task_error(self, task_id):
        try:
            job = Job.fetch(task_id, connection=self.redis_conn)
            if job.get_status() == 'failed':
                return BgCalcError(job.exc_info)
        except NoSuchJobError as ex:
            return CalcTaskNotFoundError(ex)
        return None

    def AsyncResult(self, ident):
        try:
            return ResultWrapper(Job.fetch(ident, connection=self.redis_conn))
        except NoSuchJobError:
            logging.getLogger(__name__).warning(f'Job {ident} not found')
            return None

    def is_wrapped_user_error(self, err):
        return isinstance(err, UserReadableException)


import argparse
import multiprocessing
import os
from os import PathLike
from typing import List, Union
import time
import librosa
import numpy as np
import paddleaudio
import yaml
from paddleaudio.utils.log import Logger
import paddle
logger = Logger(__file__)

class FeatureExtractor:
    def __init__(self, **kwargs):
        self.kwargs = kwargs
        self.transform = paddleaudio.transforms.MelSpectrogram(**kwargs)

    def process_wav(self, wav: Union[PathLike, np.ndarray]) -> np.ndarray:

        if isinstance(wav, str):
            #import pdb;pdb.set_trace()
            #wav, sr = librosa.load(wav, sr=None)
            target_sr = self.kwargs.get('sr')
            try:
                #wav, sr = paddleaudio.load(wav, sr=target_sr)
                wav, sr = librosa.load(
                    wav, sr=target_sr, res_type='kaiser_fast')
            except:
                print(f'error load {f}')
                return None
            #assert sr == target_sr, f'sr: {sr} ~= {target_sr}'

            #if wav.dtype == 'int16':
            # wav = pa.depth_convert(wav, 'float32')
        wav = paddle.to_tensor(wav).unsqueeze(0)
        x = self.transform(wav)
        x = paddle.log(paddle.clip(x, 1e-5))
        return x.numpy()

def wav_list_to_fbank(wav_list: List[PathLike],
                      key_list: List[str],
                      mel_folder: PathLike,
                      feature_extractor: FeatureExtractor) -> None:
    """Convert wave list to fbank
    """

    logger.info(f'saving to {mel_folder}')
    logger.info(f'{len(wav_list)} wav files listed')
    for f, key in zip(wav_list, key_list):
        x = feature_extractor.process_wav(f)
        if x is not None:
            dst_file = os.path.join(mel_folder,
                                    f.split('/')[-1].split('.')[0] + '.npy')
            np.save(dst_file, x)

def wav_to_fbank_mp(params):
    """Convert wave list to fbank, store into an h5 file, multiprocessing warping"""
    import paddle
    f, key, output_folder = params
    x = feature_extractor.process_wav(f)
    dst_file = os.path.join(output_folder,
                            f.split('/')[-1].split('.')[0] + '.npy')
    np.save(dst_file, x)

def read_scp(scp_file):
    scp_file = os.path.expanduser(scp_file)
    with open(scp_file) as f:
        lines = f.read().split('\n')

    names = [l.split()[0] for l in lines if len(l) > 1]
    files = [l.split()[1] for l in lines if len(l) > 1]
    return names, files

def read_list(list_file):
    list_file = os.path.expanduser(list_file)
    with open(list_file) as f:
        lines = f.read().split('\n')
    lines = [l for l in lines if len(l) > 1]
    return lines

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='wave2mel')
    parser.add_argument(
        '-c', '--config', type=str, required=True, default='config.yaml')
    args = parser.parse_args()

    with open(args.config) as f:
        config = yaml.safe_load(f)
    paddle.set_device(config['device'])
    feature_extractor = FeatureExtractor(**config['fbank'])
    try:
        names, wav_files = read_scp(config['wav_scp'])
    except:
        wav_files = read_list(config['wav_scp'])
        names = [f.split('/')[-1].split('.')[0] for f in wav_files]

    t0 = time.time()
    mel_folder = config['output_folder']
    mel_folder = os.path.expanduser(mel_folder)
    os.makedirs(mel_folder, exist_ok=True)
    n_workers = config['num_works']
    logger.info(f'using {n_workers} process(es)')
    if n_workers <= 1:
        wav_list_to_fbank(wav_files, names, mel_folder, feature_extractor)
    else:
        pool = multiprocessing.Pool(n_workers)
        dst_files = []
        # Collect multi-processing parameters
        params = [(file, name, mel_folder)
                  for file, name in zip(wav_files, names)]

        pool.map(wav_to_fbank_mp, params)
        pool.close()
        pool.join()

    time_used = time.time() - t0
    logger.info('done!')
    logger.info(f'processed {len(wav_files)} files in {int(time_used)} seconds')