import os
from operator import attrgetter
from pathlib import Path
from typing import Dict, List, Tuple

import av2.geometry.interpolate as interp_utils
import numpy as np

from av2.datasets.motion_forecasting import scenario_serialization
from av2.map.map_api import ArgoverseStaticMap
from numpy.typing import NDArray
from rtree import index
from shapely.geometry import LineString, Point
from tqdm.contrib.concurrent import process_map

from metric.lane_assignment import LaneAssignment
from viz.scenario_visualization import visualize_scenario

FIXED_PLOT_SIZE = (120, 120)

DATASET_SAMPLING_FREQUENCY = 10  # Hertz

VELOCITY_TRHESHOLD_FACTOR = 0.2  # Meter / (Meter / Second) = Second
VELOCITY_TRHESHOLD_OFFSET = 0.7  # Meter

DISTANCE_THRESHOLD = 5.0  # Meter
ORIENTATION_ESTIMATION_STEP_SIZE = 0.001  # Meter
ORIENTATION_THRESHOLD = np.pi  # Rad
ORIENTATION_WEIGHTING = 0.5  # -

ASSIGNMENT_CONFIDENCE_THRESHOLD = 0.1  # -

class LaneMissRate:
    def __init__(
        self,
        dataset_root: str,
        plot_dir: str = None,
    ):
        """Lane Miss Rate (LMR) metric class.

        Args:
            dataset_root (str): Dataset root path.
            plot_dir (str, optional): Output directory of scenario plots.
                Defaults to None, meaning to plots are generated.
        """
        self.dataset_root = dataset_root
        self.plot_dir = plot_dir

    def compute_lane_miss_rate(
        self,
        forecasted_trajectories: Dict[int, NDArray[np.float64]],
        gt_trajectories: Dict[int, NDArray[np.float64]],
        velocity_treshold_factor: float = VELOCITY_TRHESHOLD_FACTOR,
        velocity_threshold_offset: float = VELOCITY_TRHESHOLD_OFFSET,
        n_cpus: int = 1,
    ) -> Dict[str, float]:
        """Calculate the Lane Miss Rate (LMR) for k=1 and multi-modal predictions.
            The results are accumulated over all given scenarios.

        Args:
            forecasted_trajectories (Dict[int, NDArray[np.float64]]): Sequence ids
                and predicted trajectories in the format
                [Number of Modes, Number of Timesteps, 2 (x and y coordinates)].
            gt_trajectories (Dict[int, NDArray[np.float64]]): Sequence ids and
                ground-truth trajectory in the format
                [Number of Timesteps, 2 (x and y coordinates)].
            velocity_treshold_factor (float, optional): Factor to determine
                hit threshold. Defaults to VELOCITY_TRHESHOLD_FACTOR.
            velocity_threshold_offset (float, optional): Constant offset to determine
                hit threshold. Defaults to VELOCITY_TRHESHOLD_OFFSET.
            n_cpus (int, optional): Number of CPUs for parallel processing.
                Defaults to 1.

        Returns:
            Dict[str, float]: Lane Miss Rate (LMR).
        """
        input_values = [
            (
                forecasted_trajectories[key],
                gt_trajectories[key],
                key,
                velocity_treshold_factor,
                velocity_threshold_offset,
            )
            for key in forecasted_trajectories
        ]

        # Parallel computation of hits and misses, returning values
        # for the top 1 prediction (k=1) and all predictions
        is_miss = process_map(
            self._compute_is_missed_lane_wrapper, input_values, max_workers=n_cpus
        )
        is_miss = np.stack(is_miss)

        # Average misses over the whole dataset
        metrics = dict()
        metrics["lmr_k1"] = is_miss[:, 0].mean()
        metrics["lmr"] = is_miss.all(axis=-1).mean()

        return metrics

    def _compute_is_missed_lane_wrapper(self, args: tuple) -> NDArray[np.bool_]:
        """Wrapper method to enable parallel processing of scenarios.

        Args:
            args (tuple): Input values.

        Returns:
            NDArray[np.bool_]: Boolean flag that indicates for each predicted
                trajectory whether it is a hit (False) or a miss (True).
        """
        return self.compute_is_missed_lane(*args)

    def compute_is_missed_lane(
        self,
        forecasted_trajectories: NDArray[np.float64],
        gt_trajectory: NDArray[np.float64],
        argo_id: str,
        velocity_treshold_factor: float = VELOCITY_TRHESHOLD_FACTOR,
        velocity_threshold_offset: float = VELOCITY_TRHESHOLD_OFFSET,
    ) -> NDArray[np.bool_]:
        """Caluclate whether predictions are a hit or a
            miss for a single scenario.

        Args:
            forecasted_trajectories (NDArray[np.float64]): Predicted trajectories
                in the format
                [Number of Modes, Number of Timesteps, 2 (x and y coordinates)].
            gt_trajectory (NDArray[np.float64]): Ground-truth trajectory
                in the format [Number of Timesteps, 2 (x and y coordinates)].
            argo_id (str): Argoverse 2 id of the current scenario.
            velocity_treshold_factor (float, optional): Factor to determine
                hit threshold. Defaults to VELOCITY_TRHESHOLD_FACTOR.
            velocity_threshold_offset (float, optional): Constant offset to
                determine hit threshold. Defaults to VELOCITY_TRHESHOLD_OFFSET.

        Returns:
            NDArray[np.bool_]: Boolean flag that indicates for each predicted
                trajectory whether it is a hit (False) or a miss (True).
        """
        # Load the map of the current scenario
        scenario_root = os.path.join(self.dataset_root, argo_id)
        static_map_path = os.path.join(scenario_root, f"log_map_archive_{argo_id}.json")
        scenario_map = ArgoverseStaticMap.from_json(Path(static_map_path))

        # Get centerlines
        lane_segments = scenario_map.vector_lane_segments
        scenario_lane_centerlines = {
            lane_seg_id: interp_utils.compute_midpoint_line(
                left_ln_boundary=lane_segment.left_lane_boundary.xyz,
                right_ln_boundary=lane_segment.right_lane_boundary.xyz,
                num_interp_pts=interp_utils.NUM_CENTERLINE_INTERP_PTS,
            )
            for lane_seg_id, lane_segment in lane_segments.items()
        }

        # Initialize R-tree
        rtree = self._get_rtree(scenario_lane_centerlines)

        # Calculate average velocity of ground-truth trajectory
        gt_deltas = gt_trajectory[1:] - gt_trajectory[:-1]
        gt_velocity_per_ts = (
            np.sqrt(gt_deltas[:, 0] ** 2 + gt_deltas[:, 1] ** 2)
            * DATASET_SAMPLING_FREQUENCY
        )
        gt_velocity = np.mean(gt_velocity_per_ts)

        # Calculate velocity-dependent lane hit threshold s_hit
        s_val_threshold = (
            velocity_treshold_factor * gt_velocity
        ) + velocity_threshold_offset

        # Get assignment for the ground-truth
        gt_orientation = np.arctan2(
            gt_trajectory[-1, 1] - gt_trajectory[-2, 1],
            gt_trajectory[-1, 0] - gt_trajectory[-2, 0],
        )
        gt_assignment = self._get_lane_assignments(
            scenario_lane_centerlines, rtree, gt_trajectory[-1], gt_orientation
        )

        # Check if there is no ground-truth assignment
        # We then fall back to original Miss Rate but use
        # the dynamic threshold we defined
        if len(gt_assignment) == 0:
            distance_to_gt = np.sqrt(
                (
                    (
                        forecasted_trajectories[:, -1]
                        - np.expand_dims(gt_trajectory[-1], 0)
                    )
                    ** 2
                ).sum(axis=-1)
            )
            return distance_to_gt > s_val_threshold

        # Extract assignment with highest confidence value
        max_gt_assignment = max(gt_assignment, key=attrgetter("confidence"))

        forecasted_assignments = []
        for forecasted_trajectory in forecasted_trajectories:
            # Get assignments for the prediction
            forecasted_orientation = np.arctan2(
                forecasted_trajectory[-1, 1] - forecasted_trajectory[-2, 1],
                forecasted_trajectory[-1, 0] - forecasted_trajectory[-2, 0],
            )
            curr_forecasted_assignments = self._get_lane_assignments(
                scenario_lane_centerlines,
                rtree,
                forecasted_trajectory[-1],
                forecasted_orientation,
            )

            if len(curr_forecasted_assignments) >= 1:
                # Extract assignment with highest confidence value
                max_forecasted_assignment = max(
                    curr_forecasted_assignments, key=attrgetter("confidence")
                )

                # Extract all assignments within threshold of assignment confidence
                max_forecasted_assignment_confidence = (
                    max_forecasted_assignment.confidence
                )
                curr_forecasted_assignments = [
                    x
                    for x in curr_forecasted_assignments
                    if x.confidence
                    >= max_forecasted_assignment_confidence
                    - ASSIGNMENT_CONFIDENCE_THRESHOLD
                ]

                # Sort remaining assignments by confidence (highest first)
                curr_forecasted_assignments = sorted(
                    curr_forecasted_assignments,
                    key=attrgetter("confidence"),
                    reverse=True,
                )

                # Take the highest confidence and remove all
                # others that assign to succ or prec lane segments
                curr_forecasted_assignments_clean = curr_forecasted_assignments
                for curr_forecasted_assignment in curr_forecasted_assignments:
                    # Check if curr_forecasted_assignmend is in
                    # curr_forecasted_assignments_clean
                    # If this is the case, remove all with lower confidence
                    if curr_forecasted_assignment in curr_forecasted_assignments_clean:
                        # Get index in curr_forecasted_assignments_clean
                        idx = curr_forecasted_assignments_clean.index(
                            curr_forecasted_assignment
                        )

                        successing_ids = scenario_map.vector_lane_segments[
                            curr_forecasted_assignment.lane_seg_id
                        ].successors
                        preceding_ids = scenario_map.vector_lane_segments[
                            curr_forecasted_assignment.lane_seg_id
                        ].predecessors
                        combined_ids = successing_ids + preceding_ids

                        idx_of_ids_to_delete = set()
                        # Check all remaining ones (with higher numbers than the current index)
                        # if they are they are directly successing or preceding wrt
                        # to the current lane segment
                        for i in range(idx + 1, len(curr_forecasted_assignments_clean)):
                            id_to_check = curr_forecasted_assignments_clean[
                                i
                            ].lane_seg_id
                            if id_to_check in combined_ids:
                                idx_of_ids_to_delete.add(i)

                        # Remove the assignments
                        curr_forecasted_assignments_clean = [
                            i
                            for j, i in enumerate(curr_forecasted_assignments_clean)
                            if j not in list(idx_of_ids_to_delete)
                        ]
            else:
                curr_forecasted_assignments_clean = [None]
            forecasted_assignments.append(curr_forecasted_assignments_clean)

        # Get the lanes and the s values on these lanes that are reachable
        # from the ground-truth assignment via the s_val_treshold
        reachable_lanes = self._get_reachable_lanes(
            max_gt_assignment.lane_seg_id,
            max_gt_assignment.s_val,
            s_val_threshold,
            scenario_map,
        )

        is_missed = []
        # Check if predictions are reachable from the ground-truth assignment
        # and lie within the s_val_treshold
        for curr_forecasted_assignments in forecasted_assignments:
            curr_is_missed = []
            for forecasted_assignment in curr_forecasted_assignments:
                if forecasted_assignment is None:
                    curr_is_missed.append(True)
                elif forecasted_assignment.lane_seg_id not in reachable_lanes:
                    curr_is_missed.append(True)
                else:
                    # Prediction and ground-truth are on the same lane segment
                    if (
                        forecasted_assignment.lane_seg_id
                        == max_gt_assignment.lane_seg_id
                    ):
                        # Prediction is in front of ground-truth
                        if forecasted_assignment.s_val > max_gt_assignment.s_val:
                            if (
                                reachable_lanes[max_gt_assignment.lane_seg_id][
                                    "forward"
                                ]
                                == -1
                                or reachable_lanes[max_gt_assignment.lane_seg_id][
                                    "forward"
                                ]
                                >= forecasted_assignment.s_val
                            ):
                                curr_is_missed.append(False)
                            else:
                                curr_is_missed.append(True)
                        else:
                            if (
                                reachable_lanes[max_gt_assignment.lane_seg_id][
                                    "backward"
                                ]
                                == -1
                                or reachable_lanes[max_gt_assignment.lane_seg_id][
                                    "backward"
                                ]
                                <= forecasted_assignment.s_val
                            ):
                                curr_is_missed.append(False)
                            else:
                                curr_is_missed.append(True)
                    else:
                        # Whole segment is reachable in forward direction
                        if (
                            "forward"
                            in reachable_lanes[forecasted_assignment.lane_seg_id]
                            and reachable_lanes[forecasted_assignment.lane_seg_id][
                                "forward"
                            ]
                            == -1
                        ):
                            curr_is_missed.append(False)
                        # Whole segment is reachable in backward direction
                        elif (
                            "backward"
                            in reachable_lanes[forecasted_assignment.lane_seg_id]
                            and reachable_lanes[forecasted_assignment.lane_seg_id][
                                "backward"
                            ]
                            == -1
                        ):
                            curr_is_missed.append(False)
                        # Prediction assignment is reachable in forward direction
                        elif (
                            "forward"
                            in reachable_lanes[forecasted_assignment.lane_seg_id]
                            and forecasted_assignment.s_val
                            <= reachable_lanes[forecasted_assignment.lane_seg_id][
                                "forward"
                            ]
                        ):
                            curr_is_missed.append(False)
                        # Prediction assignment is reachable in backward direction
                        elif (
                            "backward"
                            in reachable_lanes[forecasted_assignment.lane_seg_id]
                            and forecasted_assignment.s_val
                            >= reachable_lanes[forecasted_assignment.lane_seg_id][
                                "backward"
                            ]
                        ):
                            curr_is_missed.append(False)
                        # Not reachable
                        else:
                            curr_is_missed.append(True)
            # Current prediction only is a miss, if all assignments result in a miss
            is_missed.append(all(curr_is_missed))

        is_missed = np.array(is_missed)

        if self.plot_dir is not None:
            scenario = scenario_serialization.load_argoverse_scenario_parquet(
                os.path.join(scenario_root, f"scenario_{argo_id}.parquet")
            )
            save_path = os.path.join(self.plot_dir, f"{argo_id}.pdf")

            visualize_scenario(
                scenario,
                scenario_map,
                gt_trajectory=gt_trajectory,
                gt_assignment=max_gt_assignment,
                reachable_lanes=reachable_lanes,
                forecasted_trajectories=forecasted_trajectories,
                forecasted_assignments=forecasted_assignments,
                is_missed=is_missed,
                save_path=save_path,
                fixed_plot_size=FIXED_PLOT_SIZE,
            )

        return is_missed

    def _get_lane_assignments(
        self,
        scenario_lane_centerlines: Dict[int, Tuple[NDArray[np.float64], float]],
        rtree: index.Index,
        query_xy: NDArray[np.float64],
        query_orientation: float = None,
        query_radius: float = 3.0,  # width of a US freeway is 12 feet ~= 4m
    ) -> List[LaneAssignment]:
        """Assign a trajectory to one ore multiple lane segment centerlines.

        Args:
            scenario_lane_centerlines (Dict[int, Tuple[NDArray[np.float64], float]]):
                Lane segment ids and tuples containing centerline
                coordinates and lane widths.
            rtree (index.Index): R-tree of lane segments.
            query_xy (NDArray[np.float64]): Query location, in this
                case a trajectory endpoint.
            query_orientation (float, optional): Query orientation, in this case the
                orientation of the trajectory at the endpoint. Defaults to None.
            query_radius (float, optional): Query radius around the endpoint.
                Defaults to 3.0.

        Returns:
            List[LaneAssignment]: List of lane assignments.
        """
        # Use R-tree to get nearby lane segments
        query_box = (
            query_xy[0] - query_radius,
            query_xy[1] - query_radius,
            query_xy[0] + query_radius,
            query_xy[1] + query_radius,
        )
        box_hits = rtree.intersection(query_box, objects="raw")

        query_point = Point(query_xy)

        lane_assignements = []
        unique_lane_ids = []
        for box_hit in box_hits:
            lane_seg_id = box_hit[0]

            # Only check each lane segment once (the R-tree can result in
            # multiple matches per segment)
            if lane_seg_id in unique_lane_ids:
                continue
            else:
                unique_lane_ids.append(lane_seg_id)

            line = LineString(scenario_lane_centerlines[lane_seg_id][0][:, :2])
            line_len = line.length
            s_val = line.project(query_point)
            matched_point = line.interpolate(s_val)
            d_val = np.sqrt(
                (query_point.x - matched_point.x) ** 2
                + (query_point.y - matched_point.y) ** 2
            )

            # Check if the d_val is bigger than lane width / 2.0 (assignment is
            # outside of lane boundaries)
            if d_val > (scenario_lane_centerlines[lane_seg_id][1] / 2.0):
                continue

            # Calculate distance-based assignment confidence
            assignment_confidence = max(0.0, 1.0 - (d_val / DISTANCE_THRESHOLD))

            if query_orientation is not None:
                # Calculate angle in both directions
                orientation_forward = None
                orientation_backward = None

                # Approximate orientation of lane segment by going forward and
                # backward from the assigned point
                # If the assigned point is the start or end of a lane segment,
                # only one direction is possible
                if s_val >= ORIENTATION_ESTIMATION_STEP_SIZE:
                    point_backward = line.interpolate(
                        s_val - ORIENTATION_ESTIMATION_STEP_SIZE
                    )
                    orientation_backward = np.arctan2(
                        matched_point.y - point_backward.y,
                        matched_point.x - point_backward.x,
                    )
                if s_val <= (line_len - ORIENTATION_ESTIMATION_STEP_SIZE):
                    point_forward = line.interpolate(
                        s_val + ORIENTATION_ESTIMATION_STEP_SIZE
                    )
                    orientation_forward = np.arctan2(
                        point_forward.y - matched_point.y,
                        point_forward.x - matched_point.x,
                    )
                if orientation_forward is None and orientation_backward is None:
                    print(
                        "Matched a lane segment that is too short to calculate an orientation"
                    )
                    continue

                orientations = [
                    x for x in [orientation_backward, orientation_forward] if x != None
                ]
                average_orientation = sum(orientations) / len(orientations)

                # Get orientation difference between lane and trajectory
                orientation_difference = abs(
                    np.arctan2(
                        np.sin(query_orientation - average_orientation),
                        np.cos(query_orientation - average_orientation),
                    )
                )

                # Get combined assignment confidence
                orientation_confidence = max(
                    0.0, 1.0 - (orientation_difference / ORIENTATION_THRESHOLD)
                )
                assignment_confidence = (
                    (1.0 - ORIENTATION_WEIGHTING) * assignment_confidence
                    + ORIENTATION_WEIGHTING * orientation_confidence
                )

            lane_assignements.append(
                LaneAssignment(
                    lane_seg_id,
                    assignment_confidence,
                    s_val,
                    d_val,
                    line_len,
                    [matched_point.x, matched_point.y],
                )
            )

        return lane_assignements

    def _get_rtree(
        self,
        scenario_lane_centerlines: Dict[int, Tuple[NDArray[np.float64], float]],
    ) -> index.Index:
        """Build an R-tree of lane centerline segments.

        Args:
            scenario_lane_centerlines (Dict[int, Tuple[NDArray[np.float64], float]]):
                Lane segment ids and tuples containing centerline
                coordinates and lane widths.

        Returns:
            index.Index: R-tree.
        """

        def generate_items():
            subseg_id = 0
            for lane_seg_id, lane_segment in scenario_lane_centerlines.items():
                # Only extract x and y, throw z away
                lane_seg_coords = lane_segment[0][:, :2]
                for i in range(len(lane_seg_coords) - 1):
                    x_1, y_1 = lane_seg_coords[i]
                    x_2, y_2 = lane_seg_coords[i + 1]
                    subseg = ((x_1, y_1), (x_2, y_2))
                    subseg_box = (
                        min(x_1, x_2),
                        min(y_1, y_2),
                        max(x_1, x_2),
                        max(y_1, y_2),
                    )
                    yield (subseg_id, subseg_box, (lane_seg_id, subseg))
                    subseg_id += 1

        return index.Index(generate_items())

    def _get_reachable_lanes(
        self,
        start_id: int,
        s_val_on_start: float,
        s_val_threshold: float,
        scenario_map: ArgoverseStaticMap,
    ) -> Dict[int, Dict[str, float]]:
        """Get each lane segment and also the point on each corresponding
            lane segment that is reachable from a starting point on an
            initial lane segment. Only reachable lane segments that are
            within a threshold distance along the lane graph are returned.
            Lane segments can be reachable up to a Frenet s-value in
            "forward" and "backward" direction.

        Args:
            start_id (int): Id of the initial lane segment.
            s_val_on_start (float): Frenet s-value of starting point on
                the initial lane segment.
            s_val_threshold (float): Threshold distance along the lane graph.
            scenario_map (ArgoverseStaticMap): Scenario map api of Argoverse 2.

        Returns:
            Dict[int, Dict[str, float]]: Dictionary consisting of the lane
                segment id and dictionary pairs.
                The second-order dictionary holds the reachability of the
                corresponding lane segment:
                A float value assigned to the "forward" key indicatates that
                the lane segment is reachable up to the Frenet s-value
                in forward direction.
                A float value assigned to the "backward" key indicatates that
                the lane segment is reachable up to the Frenet s-value
                in backward direction.
                In both cases the value -1 indicates that the whole lane
                segment is reachable.
        """
        centerline = scenario_map.get_lane_segment_centerline(start_id)
        centerline_length = LineString(centerline).length

        # Perform dfs in forward and backward direction
        # starting from the assigned lane segment
        visited = {}
        dfs_result_forward = self._dfs(
            visited=visited,
            direction="forward",
            start_id=start_id,
            s_val_on_start=s_val_on_start,
            start_centerline_length=centerline_length,
            s_val_traveled=centerline_length - s_val_on_start,
            s_val_threshold=s_val_threshold,
            scenario_map=scenario_map,
        )

        visited = {}
        dfs_result_backward = self._dfs(
            visited=visited,
            direction="backward",
            start_id=start_id,
            s_val_on_start=s_val_on_start,
            start_centerline_length=centerline_length,
            s_val_traveled=s_val_on_start,
            s_val_threshold=s_val_threshold,
            scenario_map=scenario_map,
        )

        dfs_result = dfs_result_forward + dfs_result_backward

        # It might be possible to visit some lane segments multiple times (loops)
        # We then only keep the one segment and the reachable position that is further
        # away from the starting point
        reachable_lanes = dict()
        for dfs_sequence in dfs_result:
            for dfs_sequence_entry in dfs_sequence:
                if dfs_sequence_entry[0] not in reachable_lanes:
                    reachable_lanes[dfs_sequence_entry[0]] = dict()

                if dfs_sequence_entry[1] == "forward":
                    if "forward" not in reachable_lanes[dfs_sequence_entry[0]]:
                        reachable_lanes[dfs_sequence_entry[0]][
                            "forward"
                        ] = dfs_sequence_entry[2]
                    elif dfs_sequence_entry[2] == -1:
                        reachable_lanes[dfs_sequence_entry[0]]["forward"] = -1
                    else:
                        reachable_lanes[dfs_sequence_entry[0]]["forward"] = max(
                            reachable_lanes[dfs_sequence_entry[0]]["forward"],
                            dfs_sequence_entry[2],
                        )

                if dfs_sequence_entry[1] == "backward":
                    if "backward" not in reachable_lanes[dfs_sequence_entry[0]]:
                        reachable_lanes[dfs_sequence_entry[0]][
                            "backward"
                        ] = dfs_sequence_entry[2]
                    elif dfs_sequence_entry[2] == -1:
                        reachable_lanes[dfs_sequence_entry[0]]["backward"] = -1
                    else:
                        reachable_lanes[dfs_sequence_entry[0]]["backward"] = min(
                            reachable_lanes[dfs_sequence_entry[0]]["backward"],
                            dfs_sequence_entry[2],
                        )

        return reachable_lanes

    def _dfs(
        self,
        visited: Dict[int, Dict[str, bool]],
        direction: str,
        start_id: int,
        s_val_on_start: float,
        start_centerline_length: float,
        s_val_traveled: float,
        s_val_threshold: float,
        scenario_map: ArgoverseStaticMap,
    ) -> List[List[Tuple[int, str, float]]]:
        """Directed depth-first search that is able to go into
            forward or backward direction.

        Args:
            visited (Dict[int, Dict[str, bool]]): Dictionary consisting of lane
                segment id and dictionary pairs. The second-order dictionary
                holds the direction ("forward" or "backward") of visited
                lane segments.
            direction (str): Search direction ("forward" or "backward").
            start_id (int): Id of the initial lane segment.
            s_val_on_start (float): Frenet s-value of starting point on the
                initial lane segment.
            start_centerline_length (float): Centerline length of the initial
                lane segment.
            s_val_traveled (float): Already travelend distance along the lane
                graph.
            s_val_threshold (float): Threshold distance along the lane graph.
            scenario_map (ArgoverseStaticMap): Scenario map api of Argoverse 2.

        Returns:
            List[List[Tuple[int, str, float]]]: List containing the results of
                the depth-first search. Each list entry contains one possible
                path. Each path is defined by edges. These edges consist of:
                    int: Id of the lane segment.
                    str: Traversed direction during the search ("forward" or
                        "backward").
                    float: Reachable Frenet s-value in search direction,
                        with -1 indicating full reachability.
        """
        # Check if node already got visited from both directions
        if start_id in visited:
            if "forward" in visited[start_id] and "backward" in visited[start_id]:
                if visited[start_id]["forward"] and visited[start_id]["backward"]:
                    return [[]]
        else:
            visited[start_id] = dict()

        # Set the visited flags
        if direction == "forward":
            visited[start_id]["forward"] = True

        if direction == "backward":
            visited[start_id]["backward"] = True

        # Check if the threshold got exceeded and return if so
        if s_val_traveled > s_val_threshold:
            if direction == "forward":
                traveled_on_current_lane_segment = (
                    start_centerline_length - s_val_on_start
                )
                traveled_without_current_lane_segment = (
                    s_val_traveled - traveled_on_current_lane_segment
                )
                left_distance_on_current_lane_segment = (
                    s_val_threshold - traveled_without_current_lane_segment
                )
                s_on_lane = s_val_on_start + left_distance_on_current_lane_segment

            if direction == "backward":
                traveled_on_current_lane_segment = s_val_on_start
                traveled_without_current_lane_segment = (
                    s_val_traveled - traveled_on_current_lane_segment
                )
                left_distance_on_current_lane_segment = (
                    s_val_threshold - traveled_without_current_lane_segment
                )
                s_on_lane = s_val_on_start - left_distance_on_current_lane_segment

            return [[(start_id, direction, s_on_lane)]]

        curr_path = []

        # If direction is forward, another dfs for all successors is
        # triggered in forward direction
        # Also, for each predecessor of each successor, a dfs in backward
        # direction is triggered
        if direction == "forward":
            successing_ids = scenario_map.vector_lane_segments[start_id].successors
            for successing_id in successing_ids:
                if successing_id in scenario_map.vector_lane_segments:

                    successing_centerline = scenario_map.get_lane_segment_centerline(
                        successing_id
                    )
                    successing_centerline_length = LineString(
                        successing_centerline
                    ).length

                    dfs_result = self._dfs(
                        visited=visited,
                        direction="forward",
                        start_id=successing_id,
                        s_val_on_start=0,
                        start_centerline_length=successing_centerline_length,
                        s_val_traveled=s_val_traveled
                        + successing_centerline_length
                        - 0,
                        s_val_threshold=s_val_threshold,
                        scenario_map=scenario_map,
                    )

                    curr_path.extend(dfs_result)

                    predecessor_ids_of_successor = scenario_map.vector_lane_segments[
                        successing_id
                    ].predecessors
                    for predecessor_id_of_successor in predecessor_ids_of_successor:
                        if (
                            predecessor_id_of_successor
                            in scenario_map.vector_lane_segments
                            and predecessor_id_of_successor != start_id
                        ):

                            centerline = scenario_map.get_lane_segment_centerline(
                                predecessor_id_of_successor
                            )
                            centerline_length = LineString(centerline).length

                            dfs_result = self._dfs(
                                visited=visited,
                                direction="backward",
                                start_id=predecessor_id_of_successor,
                                s_val_on_start=centerline_length,
                                start_centerline_length=centerline_length,
                                s_val_traveled=s_val_traveled + centerline_length,
                                s_val_threshold=s_val_threshold,
                                scenario_map=scenario_map,
                            )

                            curr_path.extend(dfs_result)

        # If direction is backward, another dfs for all predecessors is
        # triggered in backward direction
        # Also, for each successor of each predecessor, a dfs in forward
        # direction is triggered
        if direction == "backward":
            preceding_ids = scenario_map.vector_lane_segments[start_id].predecessors
            for preceding_id in preceding_ids:
                if preceding_id in scenario_map.vector_lane_segments:

                    preceding_centerline = scenario_map.get_lane_segment_centerline(
                        preceding_id
                    )
                    preceding_centerline_length = LineString(
                        preceding_centerline
                    ).length

                    dfs_result = self._dfs(
                        visited=visited,
                        direction="backward",
                        start_id=preceding_id,
                        s_val_on_start=preceding_centerline_length,
                        start_centerline_length=preceding_centerline_length,
                        s_val_traveled=s_val_traveled + preceding_centerline_length,
                        s_val_threshold=s_val_threshold,
                        scenario_map=scenario_map,
                    )

                    curr_path.extend(dfs_result)

                    successor_ids_of_predecessor = scenario_map.vector_lane_segments[
                        preceding_id
                    ].successors
                    for successor_id_of_predecessor in successor_ids_of_predecessor:
                        if (
                            successor_id_of_predecessor
                            in scenario_map.vector_lane_segments
                            and successor_id_of_predecessor != start_id
                        ):

                            centerline = scenario_map.get_lane_segment_centerline(
                                successor_id_of_predecessor
                            )
                            centerline_length = LineString(centerline).length

                            dfs_result = self._dfs(
                                visited=visited,
                                direction="forward",
                                start_id=successor_id_of_predecessor,
                                s_val_on_start=0,
                                start_centerline_length=centerline_length,
                                s_val_traveled=s_val_traveled + centerline_length,
                                s_val_threshold=s_val_threshold,
                                scenario_map=scenario_map,
                            )

                            curr_path.extend(dfs_result)

        if len(curr_path) == 0:
            return [[(start_id, direction, -1)]]

        return_value = []
        for curr_subpath in curr_path:
            return_value.append(curr_subpath + [(start_id, direction, -1)])

        return return_value


from credentials import *
import tweepy
from time import sleep
import pprint

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
leftHand = {"q","w","e","r","t","a","s","d","f","g","z","x","c","v","b"," ","1","2","3","4","5","!","@","#","$","%"}
for tweet in tweepy.Cursor(api.search,q='#Rockets').items():
    try:
        onlyLeft = True
        for letters in tweet.text:
            print(letters)
            if letters.lower() not in leftHand:
                print("not in set")
                onlyLeft = False
                break
        print(onlyLeft)
        if onlyLeft == True:
            tweet.retweet()
            print(tweet.user.screen_name + ' only used their left hand to type : ' + tweet.text)
        sleep(5)

    except tweepy.TweepError as e:
        print(e.reason)

    except StopIteration:
        break


""" Views para usuarios """

# Django rest framework
from rest_framework import status, viewsets, mixins
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.generics import get_object_or_404

# Permisos
from rest_framework.permissions import IsAuthenticated
from facebook.permissions import IsAccountOwner

# Modelos
from facebook.models import User

# Serializers
from facebook.serializers import (CreateUserSerializer, UserModelSerializer,
                                  LoginSerializer, UpdateUserSerializer)

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()

    def get_permissions(self):
        permissions= []
        if (self.action not in ['create', 'login']):
            permissions.append(IsAuthenticated)
        if (self.action in ['update', 'partial_update', 'destroy']):
            permissions.append(IsAccountOwner)
        return [p() for p in permissions]

    def get_serializer_class(self):
        if self.action == 'create':
            return CreateUserSerializer
        if self.action in ['update', 'partial_update']:
            return UpdateUserSerializer
        if self.action == 'login':
            return LoginSerializer
        return UserModelSerializer

    def create(self, request, *args, **kwargs):
        serializer_class = self.get_serializer_class()
        serializer = serializer_class(
            data = request.data,
            context = self.get_serializer_context()
        )
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        data = UserModelSerializer(user).data
        return Response(data, status=status.HTTP_201_CREATED)

    @action(detail=False, methods=['post'])
    def login(self, request):
        """ Vista para el login, esta vista obtiene o crea el token """
        serializer_class = self.get_serializer_class()
        serializer = serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        user, token = serializer.save()
        data = {
            'user': UserModelSerializer(user).data,
            'access_token': token
        }
        return Response(data, status=status.HTTP_201_CREATED)

    @action(detail=False, methods=['post'])
    def logout(self, request):
        """ Vista para logout del usuario, esta vista destruye el token """
        try:
            request.user.auth_token.delete()
        except (ObjectDoesNotExist):
            return Response(status=status.HTTP_404_NOT_FOUND)

        return Response({"success": "Successfully logged out."},
                    status=status.HTTP_200_OK)


import pandas as pd
import speech_recognition as sr
import moviepy.editor as mp
from pydub import AudioSegment
from pydub.silence import split_on_silence
import shutil
import os
import subprocess

# create a directory to store the audio chunks
def create_folder(folder_name):
    if not os.path.isdir(folder_name):
        os.mkdir(folder_name)
    return folder_name

def rename_file(start, files, step2):
    for file in files:
        name_date = file#.split('_')[1:4]
        # new_name =  "_".join(name_date).replace(' ', '-')
        new_name =  name_date.replace(' ', '-')
        # print(name_date)
        # print(new_name)
        ## move files to next step
        shutil.copy(f"{start}/{file}", f"{step2}/{new_name}.mp4")

# a function that splits the audio file into chunks
# and applies speech recognition
def get_large_audio_transcription(path):
    """
    Splitting the large audio file into chunks
    and apply speech recognition on each of these chunks
    """
    # create a speech recognition object
    r = sr.Recognizer()
    # open the audio file using pydub
    sound = AudioSegment.from_wav(path)
    # split audio sound where silence is 700 miliseconds or more and get chunks
    chunks = split_on_silence(sound,
        # experiment with this value for your target audio file
        min_silence_len = 500,
        # adjust this per requirement
        silence_thresh = sound.dBFS-14,
        # keep the silence for 1 second, adjustable as well
        keep_silence=500,
    )
    folder_name = "audio-chunks"
    # create a directory to store the audio chunks
    if not os.path.isdir(folder_name):
        os.mkdir(folder_name)
    whole_text = ""
    # process each chunk
    for i, audio_chunk in enumerate(chunks, start=1):
        # export audio chunk and save it in
        # the `folder_name` directory.
        chunk_filename = os.path.join(folder_name, f"chunk{i}.wav")
        audio_chunk.export(chunk_filename, format="wav")
        # recognize the chunk
        with sr.AudioFile(chunk_filename) as source:
            audio_listened = r.record(source)
            # try converting it to text
            try:
                text = r.recognize_google(audio_listened)
            except sr.UnknownValueError as e:
                error = {}
                error['count'] += 1
            else:
                text = f"{text.capitalize()}. "
                # print(chunk_filename, ":", text)
                whole_text += text
    # return the text for all chunks detected
    shutil.rmtree('audio-chunks')
    print(path, error.items())
    return whole_text

def speech_to_text(src, files, batch_name):
    pd.DataFrame(columns=['name','text']).to_csv(batch_name,index=False)
    for file in files:
        name_date = file#.split('_')[:2]
        whole_text = get_large_audio_transcription(f'{src}/{file}')
        name_date.append(whole_text)

        df = pd.read_csv(batch_name)
        try:
            s = pd.Series(name_date, index=['name','date','text'])
            df = df.append(s, ignore_index=True)

            df.to_csv(batch_name,index=False)
        except:
            print('error')

def pipeline(start, rename, convert, load):
    start = create_folder(start)
    files = os.listdir(start)

    step2 = create_folder(rename)
    rename_file(start, files, step2)

    step3 = create_folder(convert)

    subprocess.run(f"FOR %i IN (test_data/named/*.mp4) DO ffmpeg -i test_data/named/%i -acodec pcm_s16le -ar 16000 test_data/audio/%i.wav", shell=True)

    step4 = os.listdir(step3)
    speech_to_text(step3, step4, load)

pipeline('test_data/raw', 'test_data/named', 'test_data/audio', "test_data/load/final.csv")


#!/usr/bin/env python3

import rospy
import rosbag
import cv2
import time
import numpy as np
import os
import sensor_msgs.point_cloud2 as pc2
import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import Axes3D
from matplotlib.animation import FuncAnimation
from sensor_msgs.msg import PointCloud2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge

##### USE Settings #####
subscribeLidar = True
subscribeWebcam = True

savePCL = True
showPlot = True
saveImage = True
showImage = True

folderDataLidarSave = os.path.join("catkin_ws", "src", "lidar_test", "scripts", "lidar_data")
folderDataCameraSave = os.path.join("catkin_ws", "src", "lidar_test", "scripts", "camera_data")

##### General Settings #####

# Creates a 3D figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# Create a empty list to save the points
points = []

## Counter used t
contSaveLidar = 0
contSaveImage = 0
##############################

##### Callbacks #####
def callback_lidar(msg):
    global points, contSaveLidar, savePCL, showPlot, folderDataLidarSave

    ## If the save is defined
    if savePCL == True:
        pathSave = os.path.join(folderDataLidarSave, f'point_cloud{contSaveLidar}.bag')
        bag = rosbag.Bag(pathSave, 'w')
        bag.write('/rslidar_points', msg)
        bag.close()
        contSaveLidar += 1

    if showPlot == True:
        # Extect the relevant points of the PointCloud2 message
        point_cloud = pc2.read_points(msg, field_names=("x", "y", "z"), skip_nans=True)

        # Convet the points to a numpy array
        points = np.array(list(point_cloud))

def callback_webcam(msg):
    global contSaveImage, folderDataCameraSave
    bridge = CvBridge()
    frame = bridge.imgmsg_to_cv2(msg, desired_encoding='rgb8')
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    if saveImage == True:
        pathSave = os.path.join(folderDataCameraSave, f"image{contSaveImage}.jpg")
        print("Salvando")
        cv2.imwrite(pathSave, frame)
        contSaveImage += 1

    if showImage == True:
        cv2.imshow('Webcam', frame)
        cv2.waitKey(1)
##############################

#### Auxiliar functions #####

# Function to update the plot
def update_plot(frame):
    global points

    # Clean the grapth
    ax.cla()

    # Show the clound point updated
    if len(points) > 0:
        ax.scatter(points[:, 0], points[:, 1], points[:, 2])

    # Additional graph settings
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    ax.set_title('3D Cloud Point')

def delete_files_folder(path):
    if os.path.isdir(path):
        for filename in os.listdir(path):
            file_path = os.path.join(path, filename)
            if os.path.isfile(file_path):
                os.remove(file_path)

if __name__ == '__main__':

    delete_files_folder(folderDataLidarSave)
    delete_files_folder(folderDataCameraSave)

    rospy.init_node('main', anonymous=True)

    if subscribeLidar == True:
        rospy.Subscriber('/rslidar_points', PointCloud2, callback_lidar)

    if subscribeWebcam == True:
        rospy.Subscriber('webcam_image', Image, callback_webcam)

    if showPlot:
        # Update continualy the graph
        ani = FuncAnimation(fig, update_plot, interval=100)
        # Show the graph
        plt.show()

    if showImage == True:
        # Wait for a moment before to create the window
        time.sleep(1)

        cv2.namedWindow('Webcam', cv2.WINDOW_NORMAL)
        cv2.resizeWindow('Webcam', 640, 480)

    ## Keep the node alive
    rospy.spin()

    if showImage == True:
        cv2.destroyAllWindows()


""" Module for implementing exceptions thrown by disclosure avoidance systems"""
# 4/9/2019
# Pavel Zhuravlev

import logging

class Error(Exception):
    """Base class for DAS exceptions."""

    def __init__(self, msg=''):
        self.message = msg
        # Log it. One of the main reasons to have this class
        logging.error(msg)
        Exception.__init__(self, msg)

    def __repr__(self):
        return self.message

    __str__ = __repr__

class DASConfigError(Error):
    """ Errors resulting from parsing the config file"""

    def __init__(self, msg, option, section):
        if option is not None:
            message = f"{msg}: No option '{option}' in config section: [{section}]"
        else:
            message = f"{msg}: No section '{section}' in config file"
        Error.__init__(self, message)
        self.option = option
        self.section = section
        self.args = (option, section)

class IncompatibleAddendsError(Error):
    """ Errors when two objects of different type or with unaddable attributes are added"""

    def __init__(self, msg, attrname, addend1attr, addend2attr):
        Error.__init__(self, f"{msg} cannot be added: addends have different {attrname}: {addend1attr} != {addend2attr}")
        self.attrname = attrname
        self.addend1attr = addend1attr
        self.addend2attr = addend2attr
        self.args = (attrname, addend1attr, addend2attr)

class DASValueError(Error):
    def __init__(self, msg, value):
        Error.__init__(self, f"{msg}: value '{value}' is invalid")
        self.value = value
        self.args = (value, )


# 자료구조를 계속 새로만드니까 시간초과 -> 자료구조를 수정하는 방식
from collections import Counter as c

def solution(topping):
    cnt=0
    bro1=c(topping)
    bro2=set()
    for i in topping:
        bro1[i] -=1
        if bro1[i] ==0:
            bro1.pop(i)

        bro2.add(i)

        if len(bro1.keys())==len(bro2):
            cnt+=1

    answer = cnt
    return answer

구현/프로그래머스_롤케이크 자르기.py

프로그래머스_롤케이크 자르기.py


from selenium import webdriver
import os
from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv())

driver = webdriver.Chrome(executable_path=os.getenv('CHROME'))
driver.get("https://rahulshettyacademy.com/AutomationPractice/")
checkboxes = driver.find_elements_by_xpath("//input[@type='checkbox']")
print(len(checkboxes))
option = "option2"
for checkbox in checkboxes:
    if checkbox.get_attribute("value") == option:
        checkbox.click()
        assert checkbox.is_selected()
radio_buttons = driver.find_elements_by_name("radioButton")
radio_buttons[2].click()
radio_buttons[2].is_selected()


import pluggy

hookspec = pluggy.HookspecMarker("example_for_pycon")
hookimpl = pluggy.HookimplMarker("example_for_pycon")

class ExampleSpec:
    """A hook specification namespace."""

    @hookspec
    def myhook(self, arg1, arg2):
        """My special little hook that you can customize."""

class MyPlugin:
    """A hook implementation namespace."""

    @hookimpl
    def myhook(self, arg1, arg2):
        print("inside Plugin_1.myhook()")
        return arg1 + arg2

# create a manager and add the spec
pm = pluggy.PluginManager("example_for_pycon")
pm.add_hookspecs(ExampleSpec)

# register plugins
pm.register(MyPlugin())

# call our `myhook` hook
results = pm.hook.myhook(arg1=1, arg2=2)
print(results)


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

"""
# File       : lora_sd.py
# Time       ：2023/3/17 15:00
# Author     ：chengbo
# version    ：python 3.8
# Description：
"""
from huggingface_hub import model_info

# LoRA weights ~3 MB
model_path = "sayakpaul/sd-model-finetuned-lora-t4"

info = model_info(model_path)
model_base = info.cardData["base_model"]
print(model_base)  # CompVis/stable-diffusion-v1-4


import sys
import csv
import json
from glob import glob
import random
import re

def get_urls(train, getRealSet):
  fake_folder_names = glob('/mnt/misinformation-real-time/FakeNewsNet/code/fakenewsnet_dataset/politifact/fake/*/')
  real_folder_names = glob('/mnt/misinformation-real-time/FakeNewsNet/code/fakenewsnet_dataset/politifact/real/*/')

  fake = []
  real = []

  random.seed(10)
  random.shuffle(fake_folder_names)
  random.shuffle(real_folder_names)

  if train == True:
    words = {}
    fake = fake_folder_names[:int(0.8 * len(fake_folder_names))]
    real = real_folder_names[:int(0.8 * len(real_folder_names))]
  else:
    fake = fake_folder_names[int(0.8 * len(fake_folder_names)):]
    real = real_folder_names[int(0.8 * len(real_folder_names)):]

  final_folder_names = real if getRealSet else fake
  for folder_name in final_folder_names:
    files = glob(folder_name +  '*json')
    if len(files) == 0:
       continue
    file = files[0]
    line = ''
    with open(file) as jsonfile:
       try:
         data = json.load(jsonfile)
         line = data['text']
       except:
          continue
    if line == '':
       continue
    line = data['url']
    if line.startswith('www'):
         line = 'http://' + line
    elif not line.startswith('http'):
         line = 'https://www.' + line
    print(line)

def main(args):
  get_urls(args[0].lower()[0] == 't', args[1].lower()[0] == 'r')

if __name__ == "__main__":
  main(sys.argv[1:])


import rospy
from py_trees import Status

import giskardpy.identifier as identifier
from giskardpy.tree.behaviors.plugin import GiskardBehavior

class CommandPublisher(GiskardBehavior):
    joint_names = []

    @profile
    def __init__(self, name, hz=100):
        super().__init__(name)
        self.hz = hz
        if not hasattr(self, 'joint_names'):
            raise NotImplementedError('you need to set joint names')
        self.world.register_controlled_joints(self.joint_names)
        self.stamp = None

    @profile
    def initialise(self):
        self.sample_period = self.god_map.get_data(identifier.sample_period)
        self.stamp = rospy.get_rostime()
        self.timer = rospy.Timer(period=rospy.Duration(1/self.hz), callback=self.publish_joint_state)
        super().initialise()

    def update(self):
        self.stamp = rospy.get_rostime()
        return Status.RUNNING

    def terminate(self, new_status):
        self.timer.shutdown()

    def publish_joint_state(self, time):
        raise NotImplementedError()


from flask import Flask, request
from flask_restful import Api, Resource
from flask_cors import CORS
import json
import os
from models import db, User, Article, Comment, Like

basedir = os.path.dirname(os.path.abspath(__file__))
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')
app = Flask(__name__)
app.config.update({
    'SQLALCHEMY_TRACK_MODIFICATIONS': True,
    "SQLALCHEMY_DATABASE_URI": SQLALCHEMY_DATABASE_URI,
})
cors = CORS(app)
api = Api(app)
db.init_app(app)

def serializer(l):
    ret = []
    for row in l:
        ret.append(json.loads(row.serialize()))
    return json.dumps(ret)

class ArticleList(Resource):
    def get_articles(self):
        articles = Article.query.all()
        return articles

    def get(self):
        articles = self.get_articles()
        return serializer(articles)

    def post(self):
        r_json = request.get_json()
        user_id = r_json['user_id']
        title = r_json['title']
        content = r_json['content']
        email = r_json['email']

        new_article = Article(user_id, title, content)
        db.session.add(new_article)
        db.session.commit()
        return "write successfully"

api.add_resource(ArticleList, '/api/articles')

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(host='0.0.0.0', port=5000, debug=True)


from itertools import product

N, A1, A2, A3 = map(int, input().split())
M = 4

MORE = 2
SAME = 1
LESS = 0

def compare(s, v):
    if s > v:
        return LESS
    if s < v:
        return MORE
    return SAME

ret = []
for p in product(((0, 0, 0), (1, 1, 0), (0, 1, 1), (1, 0, 1)), repeat=M):
    s1 = s2 = s3 = 0
    for i, (b1, b2, b3) in enumerate(p):
        x = 1 << i
        s1 += b1 * x
        s2 += b2 * x
        s3 += b3 * x

    r = (
        s1 % A1,
        s2 % A2,
        s3 % A3,
        compare(N % (1 << M), s1),
        compare(N % (1 << M), s2),
        compare(N % (1 << M), s3),
    )

    if r == (0, 0, 0, 0, 0, 0):
        print(p, s1, s2, s3)

    ret.append(r)

ret.sort()
for x in ret:
    print(x)


"""
Huffman tree plotter using GraphViz

Author: Sam Barba
Created 22/11/2022
"""

from graphviz import Graph

def plot_tree(tree):
	# 1. Set up global attributes

	g = Graph(
		name='Huffman tree',
		graph_attr={'splines': 'line'},
		node_attr={'style': 'filled,setlinewidth(0)', 'shape': 'rect', 'fontname': 'consolas'},
		edge_attr={'fontname': 'consolas'}
	)

	# 2. Create nodes and edges

	nodes, edges = generate_graph(tree)

	for node in nodes:
		symbol, weight = node.split('_')
		if len(symbol) == 1:  # Leaf node (just 1 char)
			g.node(node, label=f"'{symbol}' ({weight})", fillcolor='#30e090')
		else:
			g.node(node, label=weight, fillcolor='#80c0ff')

	for n1, n2, bit in edges:
		g.edge(n1, n2, label=str(bit))

	# 3. Render graph

	g.render('tree', view=True, cleanup=True, format='png')

def generate_graph(tree, nodes=None, edges=None):
	def make_str(tree):
		return f'{tree.symbol}_{tree.weight:.2g}'

	if nodes is None: nodes = []
	if edges is None: edges = []

	if not tree: return nodes, edges

	nodes.append(make_str(tree))

	if tree.left_child:
		edges.append((make_str(tree), make_str(tree.left_child), 0))
	if tree.right_child:
		edges.append((make_str(tree), make_str(tree.right_child), 1))

	generate_graph(tree.left_child, nodes, edges)
	generate_graph(tree.right_child, nodes, edges)

	return nodes, edges


import os

"""
Gustavo Julião     300725185529511936
SharkStriker       242333420120702976
Andoniel           228668654412234762
jukabala           293595056831594496
Gulak              242333420120702976
"""
users = [300725185529511936,
         228668654412234762,
         293595056831594496,
         260438475822596097]
try:
  import discord
except ImportError:
  print ("Trying to Install required module: discord\n")
  os.system('py -3 -m pip install -U discord.py')
# -- above lines try to install requests module if not present
# -- if all went well, import required module again ( for global access)
import discord
from datetime import datetime

print("Inicializando o Tranco no serverino")
print("Aguardando Comandos")

class MyClient(discord.Client):
  async def on_message(self, message):
    #[NOME,NICK,VALOR,PRODUTO,INICIADO,GPS]
    cadastro = [0,0,0,0,0,0]
    autor_cadastro = ""

    if message.content == '!cadastro':
      autor_cadastro = message.author.id
      if message.author.id in users:
        await message.channel.send('Digire o Nome')
      else:
        await message.channel.send('Você não tem acesso a isso')

    if message.content == '!fstart':
      if message.author.id in users:
        print("user name:",message.author.name)
        print("user id:",message.author.id)
        os.system("killstart.bat")
        await message.channel.send('Fechando e Iniciando o Server')
        dha = datetime.now()
        dht = dha.strftime('%d/%m/%Y %H:%M')
        print(dht)
        print("---------------------------------")

      else:
        print("user name:",message.author.name)
        print("user id:",message.author.id)
        await message.channel.send('Você não tem acesso a isso')
        dha = datetime.now()
        dht = dha.strftime('%d/%m/%Y %H:%M')
        print(dht)
        print("---------------------------------")

    if message.content == '!start':
      print("user name:",message.author.name)
      print("user id:",message.author.id)
      print("Verificando se o Server está off caso sim iniciará automaticamente")
      os.system("verf.bat")
      await message.channel.send('Verificando se o Server está off caso sim iniciará automaticamente')
      dha = datetime.now()
      dht = dha.strftime('%d/%m/%Y %H:%M')
      print(dht)
      print("---------------------------------")

client = MyClient()
client.run('')


#!/usr/bin/env python3

"""
This client requests the server to run a function matching the name of the first argument to this script,
the rest of the command line arguments are sent as arguments to that requested function in the server.
The server's env is updated to match the env of this client when this client makes a request.

While that function runs in the server, any stdout and stderr messages are sent back to this client to be displayed.
When the function returns in the server, this client exits.
"""

import socket
import time
import json
import sys
import os

SOCKET_NAME = "./stateful-python-coordinator-socket"

class ClientEntryPoints():
    """Instantiate this class, then use that instance as a decorator for any functions that are to be used as an entry point."""
    def __init__(self):
        self.valid_entry_points = {}

    def __call__(self, func):
        self.valid_entry_points.update({func.__name__: func})
        return func

    def run(self, func_name, args):
        """Ensure a function being requested by the server has been tagged (decorated) as a valid entry point"""
        if func_name in self.valid_entry_points:
            self.valid_entry_points[func_name](*args)
        else:
            print(f"Error {func_name} not in valid entry points", file=sys.stderr)
            sys.exit(1)

CLIENT_ENTRY_POINT = ClientEntryPoints()

@CLIENT_ENTRY_POINT
def print_server_stdout(text):
    """Display messages from the server"""
    print(text, end='', file=sys.stdout)

@CLIENT_ENTRY_POINT
def print_server_stderr(text):
    """Display errors from the server"""
    print(text, end='', file=sys.stderr)

@CLIENT_ENTRY_POINT
def _exit(exit_code):
    """Named _exit to avoid redefining builtin"""
    sys.exit(exit_code)

def main():  # pylint: disable=missing-function-docstring
    if len(sys.argv) < 2:
        print("Argument required")
        sys.exit(1)

    with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client:
        try:

            # Connect to local unix socket
            connection_attempts = 0
            while True:
                try:
                    client.connect(SOCKET_NAME)
                    break
                except (ConnectionRefusedError, FileNotFoundError):
                    connection_attempts += 1
                    if connection_attempts < 10:
                        print(f"[{os.path.basename(__file__)}]: Waiting for {SOCKET_NAME}")
                        time.sleep(connection_attempts * 0.1)
                        continue
                    print(f"[{os.path.basename(__file__)}]: Couldn't connect after {connection_attempts} attempts", file=sys.stderr)
                    sys.exit(1)

            # Send argv as a json payload to the server.
            # Note the trailing newline, that is there so we can use readline() in the server
            client.sendall((json.dumps({
                "function_name": sys.argv[1],
                "args": [] if len(sys.argv) < 2 else sys.argv[2:],
                "env": dict(os.environ)
            }) + "\n").encode('utf-8'))

            # Continue reading from the server until _exit is requested from the server
            bufsize = 131072
            json_decoder = json.JSONDecoder()
            while True:
                message_from_server = client.recv(bufsize).strip().decode('utf-8')
                if message_from_server:
                    try:
                        # Client may receive several json strings concatenated into one
                        # so here we use raw_decode to iterate over the json strings
                        msg_pos, msg_last = 0, len(message_from_server) - 1
                        while msg_pos < msg_last:
                            request_from_server, msg_pos = json_decoder.raw_decode(message_from_server, msg_pos)

                            CLIENT_ENTRY_POINT.run(*[request_from_server[x] for x in ["function_name", "args"]])

                    except json.decoder.JSONDecodeError as exception:
                        print(exception)
        finally:
            client.close()

if __name__ == "__main__":
    main()


from typing import List, Optional, Any

from fastapi import Depends, FastAPI, HTTPException, status, Body, File, UploadFile
from sqlalchemy.orm import Session
from . import crud, models, schemas, deps, security
from .database import SessionLocal, engine
from fastapi.encoders import jsonable_encoder
from fastapi.responses import FileResponse
from mangum import Mangum
from fastapi.middleware.cors import CORSMiddleware
import io
import base64
from io import BytesIO

models.Base.metadata.create_all(bind=engine)

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

##users

@app.get("/")
async def root():
    return {"msg" : "hii"}

@app.post("/profile/edit", response_model=schemas.User)
async def edit_profile(user: schemas.UserUpdate, db: Session = Depends(deps.get_db), current_user: models.User = Depends(deps.get_current_user)) -> Any:
    return crud.update_user(db=db, user=user, email=user.email)

@app.post("/users/", response_model=schemas.User)
async def create_user(user: schemas.UserCreate, db: Session = Depends(deps.get_db)):
    db_user = crud.get_user_by_email(db, email=user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    return crud.create_user(db=db, user=user)

@app.get("/users/", response_model=List[schemas.User])
async def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(deps.get_db)):
    users = crud.get_users(db, skip=skip, limit=limit)
    return users

@app.get("/users/secure", response_model=schemas.User)
async def get_user_secure(
    email: str,
    db: Session = Depends(deps.get_db),
    current_user: models.User = Depends(deps.get_current_user)
    ) -> Any:

    db_user = crud.get_user_by_email(db, email=email)
    if db_user != current_user:
        raise HTTPException(status_code=404, detail="User not found")
    return db_user

@app.get("/users/{user_id}/", response_model=schemas.User)
async def read_user(user_id: str, db: Session = Depends(deps.get_db)):
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return db_user

@app.post("/token", response_model=schemas.Token)
async def login_for_access_token(db : Session = Depends(deps.get_db), form_data: deps.OAuth2PasswordRequestForm = Depends()):
    user = crud.authenticate_user(db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = security.timedelta(minutes=deps.ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = security.create_access_token(
        data={"sub": user.email}, expires_delta=access_token_expires
    )
    return {"access_token": access_token,"token_type": "bearer"}

@app.get("/profile", response_model=schemas.User)
async def get_profile(current_user: models.User = Depends(deps.get_current_user)) -> Any:
    return current_user

handler = Mangum(app)


from django.urls import path
from store import views

# TEMPLATE urls
# app_name = 'store'

urlpatterns = [
    path('', views.home, name='home'),
    path('store/', views.store, name = 'store'),
    path('store/<slug:category>/', views.filteredStore, name='filteredStore'),
    path('cart/', views.cart, name = 'cart'),
    path('checkout/', views.checkout, name = 'checkout'),
    path('update_item/', views.updateItem, name='update_item'),
    path('process_order/', views.processOrder, name='process_order'),
    path('register/', views.register, name='register'),
    path('user_login/', views.user_login, name='user_login'),
    path('logout/', views.user_logout, name='logout'),
]


from django.urls import path
from . import views

app_name = 'calendarapp'
urlpatterns = [
	path('', views.home, name='home'),
	# path('login', views.login, name='login'),
	# path('addevent', views.AddEventView.as_view(), name='addevent'),
    # path('netid', views.netid, name='netid'),
	#path('form', views.FormView.as_view(), name='form'),
	#path('filter', views.FilterView.as_view(), name='filter'),
	# path('addorg', views.AddOrgView.as_view(), name='addorg'),
    #path('cal', views.CalView.as_view(), name='cal'),
    # path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('getOrgName/<int:orgPk>/', views.getOrgName, name='getOrgName'),
    path('getEvents', views.getEvents, name='getEvents'),
	path('getOrganizations', views.getOrganizations, name='getOrganizations'),
	path('getLocations', views.getLocations, name='getLocations'),
	path('getCategories', views.getCategories, name='getCategories'),
    path('addFavorite', views.addFavorite, name='addFavorite'),
    path('submitEvent', views.createEvent, name='submitEvent'),
    path('createOrganization', views.createOrganization, name='createOrganization'),
    path('createEvent', views.createEvent, name='createEvent'),
    # path('export', views.exportToCalendar, name='export'),
    path('addUser', views.addUser, name='addUser'),
    path('authenticateUser', views.authenticateUser, name='authenticateUser'),
    path('authenticateUser', views.authenticateUser, name='authenticateUser'),
    path('checkAdminEvent', views.checkAdminEvent, name='checkAdminEvent'),
    path('deleteEvent', views.deleteEvent, name='deleteEvent'),
    path('editEvent', views.editEvent, name='editEvent'),
    path('removeFavorite', views.removeFavorite, name='removeFavorite'),
    path('checkFavorite', views.checkFavorite, name='checkFavorite'),
    # path('isAdmin', views.isAdmin, name='isAdmin'),
    # path(r'^new$', AppointmentCreateView.as_view(), name='new_appointment'),
]


"""Build a pinecone index with the Development Matters learning goals and examples."""

import os
import uuid

import openai

from dotenv import load_dotenv

from genai.eyfs import get_embedding
from genai.utils import read_json
from genai.vector_index import PineconeIndex

load_dotenv()

openai.api_key = os.environ["OPENAI_API_KEY"]
PATH_TO_DM = "src/genai/dm/dm.json"
INDEX_NAME = "eyfs-index"
ENCODER_NAME = "text-embedding-ada-002"

if "__main__" == __name__:
    data = read_json(PATH_TO_DM)
    # Temp hack to exclude the template
    data = [d for d in data if d["area_of_learning"] != ""]

    # Format the data to what pinecone needs and generate a temp uuid
    docs = []
    for elem in data:
        aol = elem["area_of_learning"]
        d = elem["age_group"]
        for age, age_dict in d.items():
            for k, items in age_dict.items():
                for item in items:
                    doc = tuple(
                        (
                            str(uuid.uuid4()),
                            get_embedding(item),
                            {
                                "age_group": age,
                                "type_": k,
                                "source": "dm",
                                "text": item,
                                "areas_of_learning": aol,
                            },
                        )
                    )
                    docs.append(doc)

    # Build the index
    conn = PineconeIndex(api_key=os.environ["PINECONE_API_KEY"], environment=os.environ["PINECONE_REGION"])

    conn.build_and_upsert(
        index_name=INDEX_NAME,
        dimension=1536,
        metric="euclidean",
        docs=docs,
        metadata_config={"indexed": ["areas_of_learning", "source", "type_", "age_group"]},
        batch_size=40,
    )


"""
Runs the Rayleigh estimation experiment, left panel of Figure 2 of the paper.
"""

import argparse
import functools

import numpy as np

import utils
from rayleigh_algorithms import rayleigh_mle, sigma

def rayleigh_phe(theta, features, targets, a=1.0):
    Z = a * np.random.normal(size=len(targets))
    return rayleigh_mle(theta, features, targets + Z)

def rayleigh_evill(theta, features, targets, a=1.0):
    n, d = features.shape
    W = a * np.sqrt(n) * np.random.normal(size=d)
    return rayleigh_mle(theta, features, targets, W)

def run_estimation_experiment(theta, estimate_fn, n, interval):
    arms = np.array([[1, 0], [0, 1]])
    features = arms[np.random.choice(2, size=n)]
    targets = np.random.rayleigh(sigma(features @ theta))
    theta_estimate = np.ones(2)

    errors = []
    for step in range(interval, n + 1, interval):
        theta_estimate = estimate_fn(theta_estimate, features[:step], targets[:step])
        errors.append(np.linalg.norm(theta_estimate - theta))

    return np.array(errors)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-n', default=10000, type=int)
    parser.add_argument('-a', default=1.0, type=float)
    parser.add_argument('--interval', default=100, type=int)
    parser.add_argument('--n_repeats', default=100, type=int)
    parser.add_argument('--output_name', default='', type=str)
    args = parser.parse_args()

    theta = np.array([0.9, 0.85])

    print("running MLE")
    results_mle = np.array(
        [run_estimation_experiment(theta, rayleigh_mle, args.n, args.interval) for _ in
         range(args.n_repeats)])
    print("running PHE")
    results_phe = np.array([
        run_estimation_experiment(theta, functools.partial(rayleigh_phe, a=args.a), args.n,
                                  args.interval) for _ in range(args.n_repeats)])
    print("running EVILL")
    results_evill = np.array([
        run_estimation_experiment(theta, functools.partial(rayleigh_evill, a=args.a), args.n,
                                  args.interval) for _ in range(args.n_repeats)])

    print(
        f"MLE: {np.mean(results_mle, axis=0)[-1]:.3f} +/- {utils.sem(results_mle, axis=0)[-1]:.3f}")
    print(
        f"PHE: {np.mean(results_phe, axis=0)[-1]:.3f} +/- {utils.sem(results_phe, axis=0)[-1]:.3f}")
    print(
        f"EVILL: {np.mean(results_evill, axis=0)[-1]:.3f} +/- {utils.sem(results_evill, axis=0)[-1]:.3f}")

    x_vals = np.array(list(range(args.interval, args.n + 1, args.interval)))
    data = {'MLE': results_mle, 'PHE': results_phe, 'EVILL': results_evill, 'x_values': x_vals}

    if args.output_name:
        np.savez(f'results/{args.output_name}.npz', data)


from .models import *
from faker import Faker
fake = Faker()
import random
choice=['math','science','english','hindi','histrory']
def seed_subdb(n):
    for i in range(0 , n):
        Subject.objects.create(
            subName = choice[i],
        )
lastname=['kumar','singh','paswaan']
def seed_prodb(n):
    for x in range(0,n):
         Professor.objects.create(
             p_fname=fake.name(),
             p_lname=lastname[random.lastname(0,3)],
             subjects=choice[random.randint(0,4)]
         )


import cv2
import matplotlib.pyplot as plt
import numpy as np
from tqdm import tqdm
from Fuzzy.readMHA_something import BRATS2015 as Brats
brats = Brats(8)

from itertools import chain

def seg_kmeans_color():
    for i in range(15):
        image, label = brats.next_train_batch(5)
    # img = cv2.imread('000129.jpg', cv2.IMREAD_COLOR)
    # # 变换一下图像通道bgr->rgb，否则很别扭啊
    # b, g, r = cv2.split(img)
    # img = cv2.merge([r, g, b])
    img = image[0,:,:,:]
    label_min = label[0, :, :]

    # 3个通道展平
    img_flat = img.reshape((img.shape[0] * img.shape[1], 4))
    img_flat = np.float32(img_flat)

    # 迭代参数
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TermCriteria_MAX_ITER, 20, 1.0)
    flags = cv2.KMEANS_RANDOM_CENTERS

    # 聚类
    compactness, labels, centers = cv2.kmeans(img_flat, 5, None, criteria, 10, flags)

    # 显示结果
    img_output = labels.reshape((img.shape[0], img.shape[1]))
    plt.subplot(131), plt.imshow(img), plt.title('input')
    plt.subplot(132), plt.imshow(img_output, 'gray'), plt.title('kmeans')
    plt.subplot(133), plt.imshow(label_min, 'gray'), plt.title('LABEL')
    plt.show()

#均值和方差
def mean_var():
    image_flair_1 = []
    image_t1_1 = []
    image_t1c_1 = []
    image_t2_1 = []

    image_flair_2 = []
    image_t1_2 = []
    image_t1c_2 = []
    image_t2_2 = []

    image_flair_3 = []
    image_t1_3 = []
    image_t1c_3 = []
    image_t2_3 = []

    image_flair_4 = []
    image_t1_4 = []
    image_t1c_4 = []
    image_t2_4 = []

    for i in tqdm(range((brats.train_batch * 155)),
                  total=((brats.train_batch * 155)),
                  ncols=70, leave=False, unit='b'):
        image_temp, label_temp = brats.next_train_batch(1)
        i_f = image_temp[0, :, :, 0]
        i_t1 = image_temp[0, :, :, 1]
        i_t1c = image_temp[0, :, :, 2]
        i_t2 = image_temp[0, :, :, 3]

        label = label_temp[0, :, :]
        class_num = 1
        image_flair_1.append(i_f[label == class_num])
        image_t1_1.append(i_t1[label == class_num])
        image_t1c_1.append(i_t1c[label == class_num])
        image_t2_1.append(i_t2[label == class_num])

        class_num = 2
        image_flair_2.append(i_f[label == class_num])
        image_t1_2.append(i_t1[label == class_num])
        image_t1c_2.append(i_t1c[label == class_num])
        image_t2_2.append(i_t2[label == class_num])

        class_num = 3
        image_flair_3.append(i_f[label == class_num])
        image_t1_3.append(i_t1[label == class_num])
        image_t1c_3.append(i_t1c[label == class_num])
        image_t2_3.append(i_t2[label == class_num])

        class_num = 4
        image_flair_4.append(i_f[label == class_num])
        image_t1_4.append(i_t1[label == class_num])
        image_t1c_4.append(i_t1c[label == class_num])
        image_t2_4.append(i_t2[label == class_num])
        # if i == 75:
        #     break
        pass
    # image_flair_total = reduce(operator.add, image_flair)
    image_flair_total_1 = list(chain(*image_flair_1))
    image_t1_total_1 = list(chain(*image_t1_1))
    image_t1c_total_1 = list(chain(*image_t1c_1))
    image_t2_total_1 = list(chain(*image_t2_1))

    image_flair_total_2 = list(chain(*image_flair_2))
    image_t1_total_2 = list(chain(*image_t1_2))
    image_t1c_total_2 = list(chain(*image_t1c_2))
    image_t2_total_2 = list(chain(*image_t2_2))

    image_flair_total_3 = list(chain(*image_flair_3))
    image_t1_total_3 = list(chain(*image_t1_3))
    image_t1c_total_3 = list(chain(*image_t1c_3))
    image_t2_total_3 = list(chain(*image_t2_3))

    image_flair_total_4 = list(chain(*image_flair_4))
    image_t1_total_4 = list(chain(*image_t1_4))
    image_t1c_total_4 = list(chain(*image_t1c_4))
    image_t2_total_4 = list(chain(*image_t2_4))

    print("class", 1)
    print("flair_mean_var", np.mean(image_flair_total_1), np.var(image_flair_total_1))
    print("t1_mean_var", np.mean(image_t1_total_1), np.var(image_t1_total_1))
    print("t1c_mean_var", np.mean(image_t1c_total_1), np.var(image_t1c_total_1))
    print("t2_mean_var", np.mean(image_t2_total_1), np.var(image_t2_total_1))

    print("class", 2)
    print("flair_mean_var", np.mean(image_flair_total_2), np.var(image_flair_total_2))
    print("t1_mean_var", np.mean(image_t1_total_2), np.var(image_t1_total_2))
    print("t1c_mean_var", np.mean(image_t1c_total_2), np.var(image_t1c_total_2))
    print("t2_mean_var", np.mean(image_t2_total_2), np.var(image_t2_total_2))

    print("class", 3)
    print("flair_mean_var", np.mean(image_flair_total_3), np.var(image_flair_total_3))
    print("t1_mean_var", np.mean(image_t1_total_3), np.var(image_t1_total_3))
    print("t1c_mean_var", np.mean(image_t1c_total_3), np.var(image_t1c_total_3))
    print("t2_mean_var", np.mean(image_t2_total_3), np.var(image_t2_total_3))

    print("class", 4)
    print("flair_mean_var", np.mean(image_flair_total_4), np.var(image_flair_total_4))
    print("t1_mean_var", np.mean(image_t1_total_4), np.var(image_t1_total_4))
    print("t1c_mean_var", np.mean(image_t1c_total_4), np.var(image_t1c_total_4))
    print("t2_mean_var", np.mean(image_t2_total_4), np.var(image_t2_total_4))

if __name__ == '__main__':
    #seg_kmeans_color()
    mean_var()


import sys
from collections import deque
input = sys.stdin.readline

def bfs(area):
    q = deque()

    check = [0] * (N + 1)
    q.append(area[0])
    check[area[0]] = 1

    cnt, total = 1, 0
    while q:
        cur = q.popleft()

        total += people[cur]
        for nxt in graph[cur]:
            if nxt in area and not check[nxt]:
                check[nxt] = 1
                cnt += 1
                q.append(nxt)
    if cnt == len(area):
        return total
    else:
        return 0

def dfs(cnt, cur, end):
    global mn

    if cnt == end:
        area1, area2 = deque(), deque()
        for i in range(1, N + 1):
            if c[i]:
                area1.append(i)
            else:
                area2.append(i)

        num_area1 = bfs(area1)
        if not num_area1:
            return

        num_area2 = bfs(area2)
        if not num_area2:
            return

        mn = min(mn, abs(num_area2 - num_area1))
        return

    for i in range(cur, N + 1):
        if c[i]:
            continue

        c[i] = 1
        dfs(cnt + 1, i, end)
        c[i] = 0

N = int(input())
people = [0] + [int(x) for x in input().split()]

graph = {}
for i in range(1, N + 1):
    graph[i] = [int(x) for x in input().split()][1:]

mn = float('inf')
for i in range(1, N // 2 + 1 + 1):
    c = [0] * (N + 1)
    dfs(0, 1, i)

print(mn if mn != float('inf') else -1)


import os
import sys
import collections
import shutil

import scraper

import os
import sys

import django

BASE_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.path.join(BASE_DIR, 'WillBeams'))
sys.path.append(BASE_DIR)

os.environ["DJANGO_SETTINGS_MODULE"] = 'WillBeams.settings'
django.setup()

from webm.models import Webm

def get_stats():
    for log_file in os.listdir(scraper.LOGS_FOLDER):
        try:
            with open(os.path.join(scraper.LOGS_FOLDER, log_file), 'r') as f:
                webms = []
                md5s = []
                for i, line in enumerate(f.readlines(), 1):
                    try:
                        w, t, m = line.split(';')
                    except ValueError:
                        continue

                    webms.append(w)
                    md5s.append(m)

                labels = 'urls', 'webms', 'md5'
                data = i, len(set(webms)), len(set(md5s))

                print('%s:' % log_file)
                for l, q in zip(labels, data):
                    print('%s: %s' % (l, q))
        except Exception as e:
            print(e)
            continue

def sort_webms_by_md5():
    for log_file in os.listdir(scraper.LOGS_FOLDER):
        with open(os.path.join(scraper.LOGS_FOLDER, log_file), 'r') as f:
            md5s = collections.defaultdict(list)
            for i, line in enumerate(f.readlines(), 1):
                try:
                    w, t, m = line[:-1].split(';')
                except ValueError:
                    continue
                md5s[m].append(t)
            for k, v in md5s.items():
                print('{}\n\t{}'.format(k, '\n\t'.join(map(str, v))))

def delete_all_webms():
    confirm = input('Really? Y/N ')

    if confirm not in ('y', 'Y', 'yes', 'yeap', 'da', 'aga', 'konechno', 'go'):
        print('Didn\'t do anything.')
        exit()

    Webm.objects.all().delete()

def count_webms():
    print(Webm.objects.count())

def clear_working_dir():
    delete_all_webms()
    project_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    for d in ('scripts/logs', 'WillBeams/media'):
        path = os.path.join(project_dir, d)
        if os.path.exists(path):
            shutil.rmtree(path)

if __name__ == '__main__':
    for arg in sys.argv[1:]:
        func = globals().get(arg, None)
        if func:
            func()


import sys
from collections import deque

#sys.stdin = open("test.txt",'r')

input = sys.stdin.readline

dx = [1,-1,0,0]
dy = [0,0,1,-1]

def bfs():
    q = deque(virus)
    count = 0
    while q:
        if count == time_cnt:
            break
        for _ in range(len(q)):
            virus_num, x, y = q.popleft()
            for i in range(4):
                nx = x + dx[i]
                ny = y + dy[i]
                if 0 <= nx < N and 0 <= ny < N and examiner_map[nx][ny] == 0:
                    examiner_map[nx][ny] = virus_num
                    q.append([virus_num,nx,ny])
        count+=1

N, K = map(int,input().split())

examiner_map = []

virus = []

for i in range(N):
    examiner_map.append(list(map(int,input().split())))
    for j in range(N):
        if examiner_map[i][j]:
            virus.append([examiner_map[i][j],i,j])

virus.sort()

time_cnt, row, column = map(int,input().split())

bfs()

print(examiner_map[row-1][column-1])


import cv2

count = 0
face_cascade = cv2.CascadeClassifier('E:\\A\\Lib\\site-packages\\cv2\\data\\haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)                               # For the access of camera 0-for same device  1-for other device

while True:
    count = count+1
    ret, frame = cap.read()                             # For capturing frame-by-frame
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)      # for converting the picture into gray scale
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)
    for (x,y,w,h) in faces:
        print(x,y,w,h)
        roi_gray = gray[y:y+h,x:x+w]
        roi_frame = frame[y:y+h,x:x+w]

        file_name_path = 'F:\\Git Projects\\Face-Recognition\\face dataset\\user'+str(count)+'.jpg' # For reading only the reasion og interest
        cv2.imwrite(file_name_path, roi_gray)

        color = (0,0,255)                               # Color of frame
        stroke = 2                                      # thickness of frame
        end_cord_x = x+w
        end_cord_y = y+h
        cv2.rectangle(frame,(x,y),(end_cord_x,end_cord_y),color,stroke) #for drawing the rectangle
        cv2.imshow('roi_gray',faces)

    # Displaying the resultant frame
    cv2.imshow('frame',frame)
    if cv2.waitKey(20) & 0xFF == ord('q') or count==50:
        break

cap.release()
cv2.destroyAllWindows()