import json
import os
import zipfile

z = zipfile.ZipFile('/content/friends-data.zip', 'r')
z.extractall()

def get_subtitles_dict():
  '''
    Создаем функцию вывода субтитров в виде словаря
  '''
  top_folder = "/content/friends-data"
  subtitles_dict = dict()
  subtitles_dict[os.path.basename(top_folder)] = []
  for position, dirname in enumerate(os.listdir(top_folder)):
    subtitles_dict[os.path.basename(top_folder)].append({dirname:[]})
    for filename in os.listdir(os.path.join(top_folder, dirname)):
      subtitles_file = open(os.path.join(top_folder, dirname, filename), 'r')
      subtitles_dict[os.path.basename(top_folder)][position][dirname].append({filename:subtitles_file.read()})

  return subtitles_dict

dict_friends_subtitles = get_table()
json_friends_subtitles = json.dump(dict_friends_subtitles, ensure_ascii = False)

def get_subtitles_frame():
  '''
    Функция для вывода субтитров в формате датафрейма
  '''
  top_folder = "/content/friends-data" #вводим путь до разархивированного каталока
  subtitles_array = []  # Идентифицируем список для добавление в него датафрейма
  subtitles_dict = dict() # Идентифицируем словарь для добвления в него по ключам-названиям файлов текста файла
  for position, dirname in enumerate(os.listdir(top_folder)): #Проходимся по директориям
    for filename in os.listdir(os.path.join(top_folder, dirname)): #Проходимся по файлам
      subtitles_file = open(os.path.join(top_folder, dirname, filename), 'r') #добавляем текст файла в переменную
      subtitles_dict[filename] = [subtitles_file.read()] #добавляем текст файла в словарь
  subtitles_array.append(pd.DataFrame(subtitles_dict))
  return subtitles_array

subtitles_array = get_subtitles_frame()

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer

df1 = subtitles_array[0]

# Initialize
vectorizer = TfidfVectorizer()
vectorizer.fit(df1.iloc[0])
doc_vec = vectorizer.fit_transform(df1.iloc[0]) #Создаем Tf вектор

# Create dataFrame
df2 = pd.DataFrame(doc_vec.toarray().transpose(),index=vectorizer.get_feature_names()) #Создаем Tf - матрицу

# Change column headers
df2.columns = df1.columns

most_common_word = df2.min(axis='columns').idxmin() #находим наиболее часто встречающееся слово как с самым наименьшим значением в матрице
less_common_word = df2.max(axis='columns').idxmax() #находим наименее часто встречающееся слово как с самым наибольшим значением в матрице
words_in_all_document = df2[df2.isin([0.0])].dropna(axis=0,how='any').index #Находим слова которое есть во всех документах, как индексы с всемы положительными значениями в строке
most_popular_hero = df2.loc[['росс','рейчел','джо','моника','чендлер','фиби']].transpose().sum().idxmin() #Находим наиболее популярного героя


def FasterFrequentWords(text,k):
    FrequentPatterns = []                           #Ausgabeliste, leeres set
    FrequencyArray=[]
    FrequencyArray = ComputingFrequencies(text,k)
    maxCount = max(FrequencyArray)
    for i in range(0, 4**k):                        #** steht für den Exponenten
        if FrequencyArray[i]==maxCount:             #finden der Indizes, bei denen pattern maximal im FrequencyArray vorkommt
            pattern = NumberToPattern(i,k)          #index (i) wird durch 4 geteilt, der Rest
                                                    #entspricht dem letzten Nukleotid; jeder nachfolgende Quotient wird geteilt und der Rest, der einem
                                                    #weiteren vorangehenden Nukleotid entspricht, gemerkt, bis Quotient 0 ist
            FrequentPatterns.append(pattern)        #Hashwert des patterns wird in FrequentPatterns eingespeichert
    FrequentPatterns=list(set(FrequentPatterns))    #Dublikate entfernen
    return FrequentPatterns

def ComputingFrequencies(text,k):
    FrequencyArray=[]                               #FrequentArray als leeres set
    for i in range(0, 4**k):                        #Schleife, initiieren Array mit 0en, ohne -1 da der letzte Wert in der Schleife nicht mitzählt
        FrequencyArray.append(0)                    #Hashwert am Anfang für alle pattern 0
    for i in range(0,len(text)-k):                  #Schleife duch text, len() Funktion für die Länge der Liste (alle items in der Liste)
        pattern=text[i:i+k]
        j=PatternToNumber(pattern)
        FrequencyArray[j] += 1                      #setzten Counter für pattern an entsprechender Stelle im Array um 1 hoch
    return FrequencyArray

def PatternToNumber(pattern):
    if pattern == "":
        return 0
    symbol = pattern[-1]
    prefix = pattern[:-1]
    return 4 * PatternToNumber(prefix) + SymbolToNumber(symbol)

def SymbolToNumber(symbol):
    if symbol == "A":
        number = 0
    elif symbol == "C":
        number = 1
    elif symbol == "G":
        number = 2
    elif symbol == "T":
        number = 3
    return number

def NumberToPattern(i,k):
    if k==1:
        return NumberToSymbol(i)
    prefixindex=i//4
    r=i%4
    symbol=NumberToSymbol(r)
    PrefixPattern=NumberToPattern(prefixindex, k - 1)
    return PrefixPattern + symbol

def NumberToSymbol(r):
    if r == 0:
        return "A"
    elif r == 1:
        return "C"
    elif r == 2:
        return "G"
    else:
        return "T"


# 爬取中国天气网最高气温的前10个城市

import requests

from bs4 import BeautifulSoup
from pyecharts import Bar

ALL_DATA = []  # 存放全国城市最高气温

# 解析页面信息
def parse_page(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 '
                      '(KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'
    }
    # 请求网页数据
    response = requests.get(url, headers=headers)
    html = response.content.decode('utf-8', 'ignore')

    # 解析网页数据
    soup = BeautifulSoup(html, 'html5lib')
    conMidtab = soup.find('div', class_='conMidtab')  # 华北地区所有的城市
    tables = conMidtab.find_all('table')  # 每一个城市
    for table in tables:
        trs = table.find_all('tr')[2:]  # 每一个地区
        for index,tr in enumerate(trs):
            tds = tr.find_all('td')
            city_td = tds[0]  # 城市td标签
            if index == 0:  # 省份的td标签放在了第一个城市的td标签的元素0上
                city_td = tds[1]
            city = list(city_td.stripped_strings)[0]  # 城市名
            temp_td = tds[-5]  # 温度td标签
            max_temp = list(temp_td.stripped_strings)[0]  # 最高温度

            ALL_DATA.append({'city': city, 'max_temp': int(max_temp)})  # 存储下来
            # print({'city': city, 'max_temp': max_temp})

def main():
    urls = [
        'http://www.weather.com.cn/textFC/hb.shtml',
        'http://www.weather.com.cn/textFC/db.shtml',
        'http://www.weather.com.cn/textFC/hd.shtml',
        'http://www.weather.com.cn/textFC/hz.shtml',
        'http://www.weather.com.cn/textFC/hn.shtml',
        'http://www.weather.com.cn/textFC/xb.shtml',
        'http://www.weather.com.cn/textFC/xn.shtml',
        'http://www.weather.com.cn/textFC/gat.shtml'
    ]  # 全国的url
    for url in urls:
        parse_page(url)

    # 分析数据,根据最高气温排序
    ALL_DATA.sort(key=lambda data: data['max_temp'], reverse=True)
    data = ALL_DATA[0:10]  # 取气温最高的前10个

    cities = list(map(lambda x: x['city'], data))  # 城市名
    temps = list(map(lambda x: x['max_temp'], data))  # 温度

    # 数据可视化,pyecharts库
    chart = Bar('中国天气最高气温排行榜')  # Bar柱状图
    chart.add('', cities, temps)  # '': 名字，citite：x轴， temps：y轴
    chart.render('temperature.html')

if __name__ == '__main__':
    main()


import sys
sys.stdin = open('input.txt')

T = 10

for tc in range(1, T+1):
    input()
    N = 100

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

    # 가로 최대/ 세로 최대
    row_max = col_max = 0

    # 대각1합   대각2합
    diag_sum1 = diag_sum2 = 0

    for a in range(N):
        # 행합    열합
        row_sum = col_sum = 0

        for b in range(N):
            # 행 우선 순회
            row_sum += matrix[a][b]
            # 열 우선 순회
            col_sum += matrix[b][a]

        # 정 대각 순회
        diag_sum1 += matrix[a][a]
        # 반 대각 순회
        diag_sum2 += matrix[a][N-a-1]

        # 지속적으로 행 최대 갱신
        if row_sum > row_max:
            row_max = row_sum
        # 지속적으로 열 최대 갱신
        if col_sum > col_max:
            col_max = col_sum

    # 대각선 최대 갱신
    diag_max = diag_sum1 if diag_sum1 > diag_sum2 else diag_sum2

    ans = max(row_max, col_max, diag_max)
    print(f'#{tc} {ans}')


from django.urls import path

from .views import about_us, about_developers

app_name = 'about'

urlpatterns = [
    path('us/', about_us, name='about_us'),
    path('developers/', about_developers, name='about_developers'),

]


# coding=utf-8
import json
from dataclasses import dataclass, asdict
from typing import List, Optional

from src.constants import DEFAULT_LIMIT, DEFAULT_OFFSET
from src.entity.room import Room
from src.exceptions import RoomNotFoundError, RoomNumberMismatchError, MissingRequiredField, \
    IntMustBePositive, StringMustNotBeEmpty
from src.use_case.interface.room_repository import RoomRepository
from src.util.context import log_extra
from src.util.log import LOG
from src.util.validator import is_empty

@dataclass
class MutationRequest:
    room_number: str
    description: str
    phone_number: Optional[str]
    vlan_number: str

    def validate(self):
        if self.room_number is None:
            raise MissingRequiredField('room_number')

        if is_empty(self.room_number):
            raise StringMustNotBeEmpty('room_number')

        if self.description is None:
            raise MissingRequiredField('description')

        if self.vlan_number is None:
            raise MissingRequiredField('vlan_number')

        if is_empty(self.vlan_number):
            raise StringMustNotBeEmpty('vlan_number')

class RoomManager:
    def __init__(self, room_repository: RoomRepository):
        self.room_repository = room_repository

    def delete(self, ctx, room_number) -> None:
        """
        Delete a room from the database.

        User story: As an admin, I can delete a room, so I can remove rooms that do not exist.

        :raise RoomNotFound
        """
        try:
            self.room_repository.delete_room(ctx, room_number=room_number)
            LOG.info('room_delete', extra=log_extra(ctx, room_number=room_number))

        except RoomNotFoundError as e:
            raise RoomNotFoundError(room_number) from e

    def get_by_number(self, ctx, room_number) -> Room:
        """
        Get a room from the database.

        User story: As an admin, I can get a room, so that see the room information.

        :raise RoomNotFound
        """
        result, _ = self.room_repository.search_room_by(ctx, room_number=room_number)
        LOG.info('room_get_by_number', extra=log_extra(ctx, room_number=room_number))
        if not result:
            raise RoomNotFoundError(room_number)

        return result[0]

    def search(self, ctx, limit=DEFAULT_LIMIT, offset=DEFAULT_OFFSET, terms=None) -> (List[Room], int):
        """
        Search a room in the database.

        User story: As an admin, I can search rooms, so that see the room information.

        :raise IntMustBePositiveException
        """
        if limit < 0:
            raise IntMustBePositive('limit')

        if offset < 0:
            raise IntMustBePositive('offset')

        result, count = self.room_repository.search_room_by(ctx, limit=limit, offset=offset, terms=terms)
        LOG.info('room_search', extra=log_extra(
            ctx,
            terms=terms,
        ))
        return result, count

    def update_or_create(self, ctx, room_number, mutation_request: MutationRequest) -> bool:
        """
        Create/Update a room from the database.

        User story: As an admin, I can modify a room, so that I change its description.
        :return: True if the room was created, false otherwise.

        :raise MissingRequiredFieldError
        :raise VlanNotFound
        :raise RoomNumberMismatchError
        """
        # Make sure all the fields set are valid.
        mutation_request.validate()

        room, _ = self.room_repository.search_room_by(ctx, room_number=room_number)
        if room:
            # [UPDATE] Room already exists, perform a whole update.

            # Create a dict with fields to update. If field is not provided in the mutation request, consider that it
            # should be None as it is a full update of the member.
            fields_to_update = asdict(mutation_request)
            fields_to_update = {k: v for k, v in fields_to_update.items()}

            # This call will never throw a RoomNotFound because we checked for the object existence before.
            self.room_repository.update_room(ctx, room_number, **fields_to_update)

            # Log action.
            LOG.info('room_update', extra=log_extra(
                ctx,
                room_number=room_number,
                mutation=json.dumps(fields_to_update, sort_keys=True),
            ))

            return False
        else:
            # [CREATE] Room does not exist, create it.

            # Build a dict that will be transformed into a room. If a field is not set, consider that it should be
            #  None.
            if room_number != mutation_request.room_number:
                raise RoomNumberMismatchError()

            fields = asdict(mutation_request)
            fields = {k: v for k, v in fields.items()}

            self.room_repository.create_room(ctx, **fields)

            # Log action
            LOG.info('room_create', extra=log_extra(
                ctx,
                room_number=room_number,
                mutation=json.dumps(fields, sort_keys=True)
            ))

            return True


T=int(input())
for test_case in range(1, T+1):
    N=int(input())
    result=0
    cost=[]
    for i in range(N):
        cost.append(list(map(int, input())))
    # print(cost)
    size=N//2 # 어디서부터 더해야하는지
    count=1 # 몇개 더해야하는지
    increase=1
    for i in range(N):
        temp=0
        start=size
        for j in range(N):
            if(temp==count):
                break
            result+=cost[i][start]
            temp+=1
            start+=1
        # print(i,":",result)
        if(count==N):
            increase=0
        if(increase==1):
            count+=2
            size-=1
        else:
            count-=2
            size+=1
    print("#{0} {1}".format(test_case, result))


import argparse
import copy
import json
import shutil
import sys
import zipfile
from datetime import datetime
import os
from functools import partial
from time import perf_counter

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import pandas as pd

import warnings
warnings.simplefilter(action='ignore', category=pd.errors.PerformanceWarning)

import numpy as np
import itertools
from collections import defaultdict
import networkx as nx
from networkx.utils import UnionFind

from relic.distance.nppo import join_detector, groupby_detector, pivot_detector
from relic.distance.ppo import compute_all_ppo_labels, compute_baseline, compute_baseline_labels
from relic.distance.tiebreakers import tiebreak_hash_edge, tiebreak_from_computed_scores, tiebreak_hash_edge_join, \
    tiebreak_join_from_inferred_graph, tiebreak_join_computed_scores, tiebreak_join_src_containment, \
    tiebreak_groupby_replay, tiebreak_hash_edge_join_pqe, tiebreak_hash_edge_pqe
from relic.graphs.clustering import exact_schema_cluster, reverse_schema_dict, write_clusters_to_file
from relic.utils.pqedge import PQEdges, get_intra_cluster_edges_only
from relic.utils.serialize import build_df_dict_dir, write_graph, get_job_status_phases, update_phase, str2bool, \
    load_distances_from_raw_files, load_distances_from_pandas_file, update_timing_df, store_distances_to_file, \
    store_all_distances
from relic.algorithm import compute_tuplewise_similarity
from relic.approx.sampling import generate_sample_index, build_sample_df_dict_dir

from relic.utils.matching import perturb_schema_dataset

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)s %(levelname)s:%(message)s')
logger = logging.getLogger(__name__)

class RelicAlgorithm:

    def __init__(self, input_dir, output_dir, name='wf_', g_truth_file=None, max_edges=None,
                 sample_frac=1.0, sample_index_flag=False, match_schema=False,
                 alpha=0.0, beta=0.0, gamma=0.0, lsh_graph_file=None,
                 **kwargs):
        logger.info('Starting instance of RelicAlgorithm on %s', name)

        # Directory Setup
        self.nb_name = name
        self.artifact_dir = input_dir
        self.inferred_dir = output_dir
        os.makedirs(self.inferred_dir, exist_ok=True)

        # Load the dataset
        # Load/read on demand infrastructure
        # self.dataset = ArtifactDict(self.artifact_dir)
        logger.info(f'Loading Artifacts from {self.artifact_dir}')
        if sample_frac < 1.0:
            sample_index = None
            if sample_index_flag:
                sample_index = generate_sample_index(self.artifact_dir, self.inferred_dir, frac=sample_frac)
            self.dataset = build_sample_df_dict_dir(self.artifact_dir, frac=sample_frac, sample_index=sample_index)
        else:
            self.dataset = build_df_dict_dir(self.artifact_dir)
        logger.info('Loading Complete')

        # Load the Ground Truth
        # Optional GT annotation or remove entirely
        if g_truth_file:
            if g_truth_file.endswith('.txt'):
                self.g_truth = nx.read_edgelist(g_truth_file)
            if g_truth_file.endswith('.pkl'):
                self.g_truth = nx.read_gpickle(g_truth_file)

        self.match_schema = match_schema

        if alpha > 0.0:
            self.dataset, self.rename_map= perturb_schema_dataset(self.dataset, self.g_truth, alpha=alpha, beta=beta, gamma=gamma)
            self.match_schema = match_schema

        # Create the initial graph
        self.g_inferred = nx.Graph()
        self.create_initial_graph()

        # Create initial components list and clustering
        self.components = UnionFind()
        self.num_components = 0
        self.initial_cluster = {}
        self.cluster_lookup = {}

        # Create the pairwise weights_dict to store multiple weights
        # Priority queue or self-sorting datastructure in association with unionfind
        self.pairwise_weights = defaultdict(PQEdges)
        self.initialize_components()

        # Current Edge being added
        self.edge_no = 0

        # Tie Breaker Info
        self.tied_edges = {}
        self.two_tie_edges = {}

        # Serialization Info
        self.serialize = True
        self.score_records = dict()

        self.lsh_edges = None
        if lsh_graph_file:
            self.lsh_edges = self.load_lsh_edge_pairs(lsh_graph_file)
            self.lsh_triples = self.load_lsh_edge_triples(lsh_graph_file)

        # No. Max edges if present:
        if max_edges:
            self.max_n_edges = max_edges
        else:
            self.max_n_edges = len(self.dataset)

    def load_artifacts(self):
        pass

    def create_initial_graph(self):
        logger.debug('Creating the initial graph of artifact nodes')
        self.g_inferred = nx.Graph()
        for artifact in self.dataset.keys():
            if artifact not in [n for n in self.g_inferred.nodes()]:
                logger.debug('Adding artifact to graph %s', str(artifact))
                self.g_inferred.add_node(artifact)

        return self.g_inferred

    def load_lsh_edge_pairs(self, lsh_graph_file):
        logger.debug('Loading LSH Graph')
        lsh_graph = nx.read_gpickle(lsh_graph_file)
        lsh_graph.remove_edges_from(list(nx.selfloop_edges(lsh_graph)))

        return list(lsh_graph.edges())

    def load_lsh_edge_triples(self, lsh_graph_file):
        logger.debug('Loading LSH Graph for Triples')
        lsh_graph = nx.read_gpickle(lsh_graph_file)
        lsh_graph.remove_edges_from(list(nx.selfloop_edges(lsh_graph)))
        triples = set()

        for node in lsh_graph.nodes():
            node_neighbors = lsh_graph.neighbors(node)
            for n_combo in itertools.combinations(node_neighbors, 2):
                triples.add(frozenset((node, n_combo[0], n_combo[1])))

        return list(triples)

    def set_initial_clusters(self, cluster_type='exact_schema'):
        # Initial Clusters set to individual artifacts:
        if cluster_type == 'exact_schema':
            self.initial_cluster = exact_schema_cluster(self.dataset)
        self.cluster_lookup = reverse_schema_dict(self.initial_cluster)

        return self.initial_cluster

    def initialize_components(self):
        # Initializes the current list of graph components:
        logger.debug('Updating Graph Components')
        components = [n for c in nx.connected_components(self.g_inferred) for n in c]
        self.components = UnionFind(elements=components)
        self.num_components = len(components)
        return self.components

    def add_edge_and_merge_components(self, edge, data):
        logger.debug(f'About to add and merge edge {edge}')

        if type(edge[0]) == tuple:  # two sources, like join
            for e in edge[0]:
                self.g_inferred.add_edge(e, edge[1], **data)
                self.components.union(e, edge[1])
        else:
            self.g_inferred.add_edge(edge[0], edge[1], **data)
            self.components.union(edge[0], edge[1])

        logger.debug([x for x in self.components.to_sets()])
        self.edge_no += 1
        self.num_components = len([x for x in self.components])

    def compute_edges_of_type(self, edge_type='all', similarity_function=compute_all_ppo_labels,
                              n_pairs=2, pairs=None):
        if self.lsh_edges:
            if n_pairs == 2:
                pairs = self.lsh_edges
            elif n_pairs == 3:
                pairs = self.lsh_triples

        edge_scores = compute_tuplewise_similarity(self.dataset, similarity_metric=similarity_function,
                                                   label=edge_type, n_pairs=n_pairs, match_schema=self.match_schema,
                                                   pairs=pairs)
        self.pairwise_weights.update(edge_scores)
        if self.serialize == True:
            for edge_type, score_dict in edge_scores.items():
                self.score_records[edge_type] = copy.deepcopy(score_dict)

    def add_edges_of_type(self, edge_type='jaccard', intra_cluster=False, tiebreak_function=None,
                          final_function=tiebreak_hash_edge,
                          sim_threshold=0.1, max_step=False, tiebreak_pqe=None, tiebreak_kwargs=None):

        if len(self.g_inferred.edges) >= self.max_n_edges:
            logger.warning(f"Reached maximum edges, unable to add {edge_type} to graph")
            return

        # Compute all pairwise edges first
        if edge_type not in self.pairwise_weights:
            raise KeyError('Edge type not computed in pairwise_weight dict')

        if intra_cluster:
            weights_pq = get_intra_cluster_edges_only(self.pairwise_weights[edge_type], self.cluster_lookup)
            logger.debug('Intra Cluster PQEdges')
            logger.debug(self.pairwise_weights[edge_type])
            logger.debug(weights_pq)
        else:
            weights_pq = self.pairwise_weights[edge_type]

        steps = 0
        stop = False
        if not max_step:
            max_step = len(self.dataset)

        while self.num_components > 1 and steps < max_step and not stop:
            # First check if we have already reached max edges in graph:
            if len(self.g_inferred.edges) >= self.max_n_edges:
                logger.warning(f"Reached maximum edges, stopping add_edge_routing")
                stop = True
                break
            #logger.debug(f'PQ Status: {weights_pq}')
            #logger.debug(f'UnionFind Status: {[x for x in self.components.to_sets()]}')
            max_edges = weights_pq.pop_unionfind_max(self.components)
            #logger.debug(f'MaxEdges Found:  {max_edges} edge(s)...')

            add_remaining_tie_break_edges = False

            if not max_edges:
                logger.debug('No compatible edges left in PQ/UnionFind')
                stop = True
                break
            elif max_edges[0][1] < sim_threshold:
                logger.debug(f'{max_edges} edge(s) below threshold {sim_threshold}, stopping')
                stop = True
                break
            elif len(max_edges) > 1:
                logger.info(f"Tiebreaking {len(max_edges)} edges...")
                weight = max_edges[0][1]
                if tiebreak_function:
                    tiebreak_pqe = tiebreak_function(max_edges, pqe=tiebreak_pqe, **tiebreak_kwargs)
                    tie_break_edges = tiebreak_pqe.pop_max()
                else:
                    tie_break_edges = max_edges
                if len(tie_break_edges) > 1:
                    final_pqe = PQEdges()
                    logger.info(f"Applying final tiebreaker for  {len(tie_break_edges)} edges...")
                    final_pqe = final_function(tie_break_edges, pqe=final_pqe)
                    final_edges = final_pqe.pop_max()
                    edge = final_edges[0][0]
                    add_remaining_tie_break_edges = True

                else:
                    edge = tie_break_edges[0]

            else:
                edge = max_edges[0]
                weight = edge[1]

            logger.info(f"Adding edge #{self.edge_no}: {edge[0]}, type {edge_type}, weight: {weight}")
            if tiebreak_kwargs and 'pqe' in tiebreak_kwargs.keys():
                logger.debug(f"PQE status: {tiebreak_kwargs['pqe']}")
            self.add_edge_and_merge_components(list(edge[0]), {'weight': weight, 'type': edge_type, 'num': self.edge_no})
            steps += 1

            # Clean up and add back remaining edges to respective PQEs:
            if len(max_edges) > 1:
                logger.info(f'Adding back {len(max_edges)} edges to pqdict')
                for e in max_edges:
                    if e not in self.pairwise_weights[edge_type] and e != edge:
                        try:
                            if edge_type == 'join':
                                u, v = e[0][0]
                                dst = e[0][1]
                                logger.debug(f"Evaluating Join Edge info: {u},,,{v}-->{dst}")

                                if self.components[u] == self.components[dst] or self.components[v] == self.components[dst]:
                                    logger.debug(f'Skipping adding back redundant edge: {e}')
                                else:
                                    self.pairwise_weights[edge_type].additem(e[0], e[1])
                            else:
                                if self.components[e[0]] != self.components[e[1]]:
                                    self.pairwise_weights[edge_type].additem(e[0], e[1])
                        except KeyError as e:
                            logger.warning(f'Error: Trying to add back {e}, selected {edge}, to {edge_type} dict')

                if add_remaining_tie_break_edges and tiebreak_function:
                    try:
                        for e in tie_break_edges:
                            if self.components[e[0]] != self.components[e[1]]:
                                if e != edge:
                                    if e not in tiebreak_pqe:
                                        tiebreak_pqe.additem(e[0], e[1])
                    except ValueError as err:
                        logger.error(err)
                        logger.error(f"Tiebreak Edges: {tie_break_edges}")
                        logger.error(f"Edge: {e}")
                        raise(e)

def setup_arguments(args):
    parser = argparse.ArgumentParser()

    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument("--artifact_zip",
                        help="ZIP containing artifacts to be analyzed",
                        type=str)

    group.add_argument("--artifact_dir",
                        help="Directory containing artifacts to be analyzed",
                        type=str)

    parser.add_argument("--nb_name",
                        help="Name of the notebook to be analyzed",
                        type=str, default=datetime.now().strftime("%Y%m%d%H%M%S"))

    parser.add_argument("--out",
                        help="Output Directory for Results",
                        type=str, default='inferred/')

    parser.add_argument("--config_json",
                        help="Configuration JSON file for inference Job. Overrides all other job parameters if present",
                        type=str)

    parser.add_argument("--pre_cluster",
                        help="Pre cluster by exact schema",
                        type=str2bool, default=True,
                        nargs='?', const=True)

    parser.add_argument("--celljaccard",
                        help="Look for cell-level jaccard edges",
                        type=str2bool, default=True,
                        nargs='?', const=True)

    parser.add_argument("--cellcontain",
                        help="Look for cell-level containment edges",
                        type=str2bool, default=True,
                        nargs='?', const=True)

    parser.add_argument("--groupby",
                        help="Use Groupby Edge Detection",
                        type=str2bool, default=True,
                        nargs='?', const=True)

    parser.add_argument("--join",
                        help="Use Join Edge Detection",
                        type=str2bool, default=True,
                        nargs='?', const=True)

    parser.add_argument("--transform",
                        help="Use Transform Edge Detection",
                        type=str2bool, default=False,
                        nargs='?', const=False)

    parser.add_argument("--pivot",
                        help="Use Pivot Edge Detection",
                        type=str2bool, default=True,
                        nargs='?', const=True)

    parser.add_argument("--intra_cell",
                        help="Cell-Level Edge Retention Threshold",
                        type=float, default=0.1)

    parser.add_argument("--colt",
                        help="Column-Level Edge Retention Threshold",
                        type=float, default=0.1)

    parser.add_argument("--inter_cell",
                        help="Inter Cluster Cell-Level Edge Retention Threshold",
                        type=float, default=0.1)

    parser.add_argument("--intra_contain",
                        help="Cell-Level Edge Retention Threshold",
                        type=float, default=0.1)

    parser.add_argument("--inter_contain",
                        help="Inter Cluster Cell-Level Edge Retention Threshold",
                        type=float, default=0.1)

    parser.add_argument("--g_truth_file",
                        help="Ground Truth File as a pickled NetworkX graph",
                        type=str)

    parser.add_argument("--pre_compute",
                        help="Use pre-computed distances (in the appropriate distance folder)",
                        type=str2bool, default=False,
                        nargs='?', const=False)

    parser.add_argument("--max_n_edges",
                        help="Number of edges to infer (default nartifacts - 1)",
                        type=int)

    parser.add_argument("--result_prefix",
                        help="Prefix the job result file with some string",
                        type=str, default='')

    parser.add_argument("--baseline",
                        help="Run baseline comparison",
                        type=str2bool, default=False,
                        nargs='?', const=False)

    parser.add_argument("--sample_frac",
                        help="Sampling Fraction to load dataset",
                        type=float, default=1.0)

    parser.add_argument("--sample_index",
                        help="Use consistent sampling when sample_frac less than 1.0",
                        type=str2bool, default=False,
                        nargs='?', const=False)

    parser.add_argument("--store_scores",
                        help="Write computed scores to disk in output dir",
                        type=str2bool, default=True,
                        nargs='?', const=True)

    parser.add_argument("--match_schema",
                        help="Run schema matching algorithm before computing pairwise similarities",
                        type=str2bool, default=False,
                        nargs='?', const=False)

    parser.add_argument("--perturb_alpha",
                        help="Perturb Schema (Alpha) parameter",
                        type=float, default=0.0)

    parser.add_argument("--perturb_beta",
                        help="Perturb Schema (Beta) parameter",
                        type=float, default=0.0)

    parser.add_argument("--perturb_gamma",
                         help="Perturb Schema (Gamma) parameter",
                         type=float, default=0.0)

    parser.add_argument("--lsh_graph_file",
                       help="LSH Graph File after clustering",
                       type=str, default=None)

    options = parser.parse_args(args)

    return options

def run_precluster(relic_instance, options, job_status, status_file):
    if options.pre_cluster:
        update_phase(job_status, 'Clustering', status_file)
        clusters = relic_instance.set_initial_clusters()
        os.makedirs(options.out+'/inferred', exist_ok=True)
        write_clusters_to_file(clusters, options.out+'/clusters.txt')
        logger.info(f'Clustered by Schema: {len(clusters.keys())} individual clusters created.')
        logger.info('Looking for PPO edges within each cluster...')

        if options.celljaccard:
            tiebreak_pqe = PQEdges()
            final_pqe = PQEdges()
            update_phase(job_status, 'Intra-Cluster Jaccard', status_file)
            relic_instance.add_edges_of_type(edge_type='jaccard', intra_cluster=True,
                                             tiebreak_function=tiebreak_from_computed_scores,
                                             final_function=tiebreak_hash_edge_pqe,
                                             sim_threshold=options.intra_cell,
                                             tiebreak_pqe=tiebreak_pqe,
                                             tiebreak_kwargs={'pairwise_weights': relic_instance.pairwise_weights,
                                                              'score_type': 'overlap'}
                                             )

        if options.cellcontain:
            tiebreak_pqe = PQEdges()
            final_pqe = PQEdges()
            update_phase(job_status, 'Intra-Cluster Containment', status_file)
            relic_instance.add_edges_of_type(edge_type='containment', intra_cluster=True,
                                             tiebreak_function=tiebreak_from_computed_scores,
                                             final_function=tiebreak_hash_edge_pqe,
                                             sim_threshold=options.intra_contain,
                                             tiebreak_pqe=tiebreak_pqe,
                                             tiebreak_kwargs={'pairwise_weights': relic_instance.pairwise_weights,
                                                              'score_type': 'overlap'}
                                             )
    return relic_instance

def run_join(relic_instance, options, distance_load_function, job_status, status_file):
    if options.join:
        logger.info('Looking for join edges across clusters...')
        update_phase(job_status, 'Join Detection', status_file)
        if options.pre_compute:
            logger.info(f'Loading Triplewise Join distances from file...')
            distance_file = options.out + '/join.csv'
            # TODO: Fix Hack for missing join.csv in case there are no schema-eligible join candidates
            # Else consolidate all the run_functions into a bigger function that can handle different detector types
            if os.path.exists(distance_file):
                relic_instance.pairwise_weights.update(distance_load_function(distance_file))
            else:
                logger.warning(f'Missing distance file: {distance_file}')
                return relic_instance
            logger.info(f'Loading complete...')
        else:
            relic_instance.compute_edges_of_type(edge_type='join', similarity_function=join_detector, n_pairs=3)

        tiebreak_pqe = PQEdges()
        final_pqe = PQEdges()
        relic_instance.add_edges_of_type(edge_type='join', intra_cluster=False, sim_threshold=1.0,
                                         tiebreak_function=tiebreak_join_computed_scores,
                                         final_function=tiebreak_hash_edge_join_pqe,
                                         tiebreak_pqe=tiebreak_pqe,
                                         tiebreak_kwargs={'pairwise_weights': relic_instance.pairwise_weights,
                                                          'score_type': 'containment'}
                                         )
    return relic_instance

def run_inter_cell(relic_instance, options, job_status, status_file):
    logger.info('Looking for PPO edges across clusters...')
    if options.celljaccard:
        tiebreak_pqe = PQEdges()
        final_pqe = PQEdges()
        update_phase(job_status, 'Inter-Cluster Jaccard', status_file)
        relic_instance.add_edges_of_type(edge_type='jaccard', intra_cluster=False,
                                         tiebreak_function=tiebreak_from_computed_scores,
                                         final_function=tiebreak_hash_edge_pqe,
                                         sim_threshold=options.inter_cell,
                                         tiebreak_pqe=tiebreak_pqe,
                                         tiebreak_kwargs={'pairwise_weights': relic_instance.pairwise_weights,
                                                          'score_type': 'overlap'}
                                         )
    return relic_instance

def run_inter_contain(relic_instance, options, job_status, status_file):
    if options.cellcontain:
        tiebreak_pqe = PQEdges()
        final_pqe = PQEdges()
        update_phase(job_status, 'Inter-Cluster Containment', status_file)
        relic_instance.add_edges_of_type(edge_type='containment', intra_cluster=False,
                                         tiebreak_function=tiebreak_from_computed_scores,
                                         final_function=tiebreak_hash_edge_pqe,
                                         sim_threshold=options.inter_contain,
                                         tiebreak_pqe=tiebreak_pqe,
                                         tiebreak_kwargs={'pairwise_weights': relic_instance.pairwise_weights,
                                                          'score_type': 'overlap'}
                                         )
    return relic_instance

def run_groupby(relic_instance, options, distance_load_function, job_status, status_file):
    if options.groupby:
        logger.info('Looking for Groupby edges across clusters...')
        update_phase(job_status, 'Groupby Detection', status_file)
        if options.pre_compute:
            logger.info(f'Loading Pairwise Groupby distances from file...')
            relic_instance.pairwise_weights.update(distance_load_function(options.out + '/groupby.csv'))
            logger.info(f'Loading complete...')
        else:
            relic_instance.compute_edges_of_type(edge_type='groupby', similarity_function=groupby_detector, n_pairs=2)

        tiebreak_pqe = PQEdges()
        final_pqe = PQEdges()
        relic_instance.add_edges_of_type(edge_type='groupby', intra_cluster=False, sim_threshold=1.0,
                                         tiebreak_function=tiebreak_groupby_replay,
                                         final_function=tiebreak_hash_edge_pqe,
                                         tiebreak_pqe=tiebreak_pqe,
                                         tiebreak_kwargs={'df_dict': relic_instance.dataset}
                                         )
        logger.info(f'GB Tiebreak Dict: {len(tiebreak_pqe.keys())}')
    return relic_instance

def run_pivot(relic_instance, options, distance_load_function, job_status, status_file):
    if options.pivot:
        logger.info('Looking for Pivot edges across clusters...')
        update_phase(job_status, 'Pivot Detection', status_file)
        if options.pre_compute:
            logger.info(f'Loading Pairwise Pivot distances from file...')
            relic_instance.pairwise_weights.update(distance_load_function(options.out + '/pivot.csv'))
            logger.info(f'Loading complete...')
        else:
            relic_instance.compute_edges_of_type(edge_type='pivot', similarity_function=pivot_detector, n_pairs=2)
        tiebreak_pqe = PQEdges()
        final_pqe = PQEdges()
        relic_instance.add_edges_of_type(edge_type='pivot', intra_cluster=False, sim_threshold=1.0,
                                         tiebreak_function=tiebreak_from_computed_scores,
                                         final_function=tiebreak_hash_edge_pqe,
                                         tiebreak_pqe=tiebreak_pqe,
                                         tiebreak_kwargs={'pairwise_weights': relic_instance.pairwise_weights,
                                                          'score_type': 'containment'}
                                         )
    return relic_instance

def run_baseline(relic_instance, options, distance_load_function, job_status, status_file):
    if options.baseline:
        logger.info('Running column baseline')
        update_phase(job_status, 'Baseline Column', status_file)
        if options.pre_compute:
            logger.info(f'Loading Pairwise Baseline distances from file...')
            relic_instance.pairwise_weights.update(distance_load_function(options.out + '/baseline.csv'))
            logger.info(f'Loading complete...')
        else:
            relic_instance.compute_edges_of_type(edge_type='baseline', similarity_function=compute_baseline_labels, n_pairs=2)

        final_pqe = PQEdges()
        relic_instance.add_edges_of_type(edge_type='baseline', intra_cluster=False, sim_threshold=0.0,
                                         tiebreak_function=None,
                                         final_function=tiebreak_hash_edge_pqe,
                                         )
    return relic_instance

def run_relic(options):
    logger.info('Testing RELIC on input:' + str(options.artifact_dir))
    logger.info('Output directory: ' + str(options.out))
    logger.info(f'Options: {options}')
    os.makedirs(options.out, exist_ok=True)

    distance_load_function = load_distances_from_pandas_file

    # Setup Job Log
    # create file handler which logs even debug messages
    fh = logging.FileHandler(str(options.out)+'job.log')
    fh.setLevel(logging.DEBUG)
    logger.addHandler(fh)

    job_status = {
        'status': 'running',
        'job_id': options.nb_name,
        'phaseno': 0,
        'totalphases': get_job_status_phases(options)
    }

    status_file = str(options.out)+'job_status.json'

    if 'artifact_zip' in options and options.artifact_zip:  # Zip file was provided
        zip_out = options.out+'/artifacts/'
        logger.info(f'Extracting ZIP file: {options.artifact_zip} to directory {zip_out}')
        if os.path.exists(zip_out):
            shutil.rmtree(zip_out)
        os.makedirs(zip_out)
        with zipfile.ZipFile(options.artifact_zip, 'r') as zip_ref:
            zip_ref.extractall(zip_out)
        artifact_dir = zip_out
    else:
        artifact_dir = options.artifact_dir

    timing_dicts = []

    start = perf_counter()
    relic_instance = RelicAlgorithm(artifact_dir, options.out, name=options.nb_name, g_truth_file=options.g_truth_file,
                                    max_edges=options.max_n_edges, sample_frac=options.sample_frac,
                                    sample_index_flag=options.sample_index, match_schema=options.match_schema,
                                    alpha=options.perturb_alpha, beta=options.perturb_beta, gamme=options.perturb_gamma,
                                    lsh_graph_file=options.lsh_graph_file)
    end = perf_counter()
    update_timing_df(timing_dicts, options.nb_name, 'loading', end-start)

    relic_instance.create_initial_graph()

    update_phase(job_status, 'Computing Pairwise Distances', status_file)

    if options.baseline:
        run_baseline(relic_instance, options, distance_load_function, job_status, status_file)
    else:
        if options.pre_compute:
            logger.info(f'Loading Pairwise PPO distances from file...')
            relic_instance.pairwise_weights.update(distance_load_function(options.out+'/ppo.csv'))
            logger.info(f'Loading Complete...')
        else:
            start = perf_counter()
            relic_instance.compute_edges_of_type(edge_type='all', similarity_function=compute_all_ppo_labels, n_pairs=2)
            end = perf_counter()
            update_timing_df(timing_dicts, options.nb_name, 'ppo', end-start)

        functions = {
            'pre_cluster': partial(run_precluster, relic_instance, options, job_status, status_file),
            'join': partial(run_join, relic_instance, options, distance_load_function, job_status, status_file),
            'inter_cell': partial(run_inter_cell, relic_instance, options, job_status, status_file),
            'inter_contain': partial(run_inter_contain, relic_instance, options, job_status, status_file),
            'groupby': partial(run_groupby, relic_instance, options, distance_load_function, job_status, status_file),
            'pivot': partial(run_pivot, relic_instance, options, distance_load_function, job_status, status_file)
        }

        order = ['pre_cluster', 'join', 'inter_cell', 'inter_contain', 'groupby', 'pivot']
        if options.lsh_graph_file:
            order = ['inter_cell', 'inter_contain', 'groupby', 'pivot']
        #order = ['join', 'groupby', 'pivot', 'pre_cluster', 'inter_cell', 'inter_contain']

        for func in order:
            start = perf_counter()
            relic_instance = functions[func]()
            end = perf_counter()
            update_timing_df(timing_dicts, options.nb_name, func, end-start)

    write_graph(relic_instance.g_inferred, f"{options.out}/{options.result_prefix}inferred_graph.csv")
    if options.g_truth_file:
        nx.write_edgelist(relic_instance.g_truth, f"{options.out}/true_graph.csv", data=True)

    job_status['status'] = 'complete'
    with open(status_file, 'w') as fp:
        json.dump(job_status, fp)

    pd.DataFrame(timing_dicts).to_csv(f"{options.out}/{options.result_prefix}_run_time.csv")

    if options.store_scores:
        store_all_distances(relic_instance.score_records, options.out)

def main(args=sys.argv[1:]):
    logger.info(f'Arguments: {args}')
    options = setup_arguments(args)
    logger.info(f'Options: {options}')
    run_relic(options)

if __name__ == "__main__":
    main()


for N in range(95632,95651):
    a=[]
    for j in range(1,int(N**(1/2))+1):
        if (N%j)==0:
            if j%2!=0 and (j not in a):
                a.append(j)
            if (N//j)%2!=0 and ((N//j) not in a):
                a.append(N//j)
        if len(a)>6:break
    if len(a)==6:
        print(sorted(a))


from __future__ import print_function
# pylint: disable=invalid-name

import tensorflow as tf
import numpy as np

def make_model(x, y_):
    input_size = int(x.get_shape()[-1])
    input_edge = int(np.sqrt(input_size))
    output_size = int(y_.get_shape()[-1])

    # --> [batch, n, n, 1]
    input_layer = tf.reshape(x, [-1, input_edge, input_edge, 1])

    # --> [batch, n, n, 32]
    conv1 = tf.layers.conv2d(
        input_layer, 32, [5, 5], padding="same", activation=tf.nn.relu)

    # --> [batch, n/2, n/2, 32]
    pool1 = tf.layers.max_pooling2d(conv1, [2, 2], strides=2)

    '''
    # --> [batch, n/2, n/2, 16]
    conv2 = tf.layers.conv2d(
        pool1, 16, [5, 5], padding="same", activation=tf.nn.relu)

    # --> [batch, n/4, n/4, 16]
    pool2 = tf.layers.max_pooling2d(conv2, [2, 2], strides=2)

    # --> [batch, ?]
    pool2_flat = tf.contrib.layers.flatten(pool2)
    '''
    # --> [batch, ?]
    pool2_flat = tf.contrib.layers.flatten(pool1)

    # --> [batch, 1024]
    dense = tf.layers.dense(pool2_flat, 1024, tf.nn.relu)

    # --> [batch, output_size]
    logits = tf.layers.dense(dense, output_size)

    return logits


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import os
import unittest

import mozunit
from buildconfig import topobjdir
from mozunit import MockedOpen

import mozpack.path as mozpath
from mozbuild.preprocessor import Preprocessor
from mozpack.chrome.manifest import (
    ManifestBinaryComponent,
    ManifestContent,
    ManifestResource,
)
from mozpack.errors import ErrorMessage, errors
from mozpack.files import GeneratedFile
from mozpack.packager import (
    CallDeque,
    Component,
    SimpleManifestSink,
    SimplePackager,
    preprocess_manifest,
)

MANIFEST = """
bar/*
[foo]
foo/*
-foo/bar
chrome.manifest
[zot destdir="destdir"]
foo/zot
; comment
#ifdef baz
[baz]
baz@SUFFIX@
#endif
"""

class TestPreprocessManifest(unittest.TestCase):
    MANIFEST_PATH = mozpath.join("$OBJDIR", "manifest")

    EXPECTED_LOG = [
        ((MANIFEST_PATH, 2), "add", "", "bar/*"),
        ((MANIFEST_PATH, 4), "add", "foo", "foo/*"),
        ((MANIFEST_PATH, 5), "remove", "foo", "foo/bar"),
        ((MANIFEST_PATH, 6), "add", "foo", "chrome.manifest"),
        ((MANIFEST_PATH, 8), "add", 'zot destdir="destdir"', "foo/zot"),
    ]

    def setUp(self):
        class MockSink(object):
            def __init__(self):
                self.log = []

            def add(self, component, path):
                self._log(errors.get_context(), "add", repr(component), path)

            def remove(self, component, path):
                self._log(errors.get_context(), "remove", repr(component), path)

            def _log(self, *args):
                self.log.append(args)

        self.sink = MockSink()
        self.cwd = os.getcwd()
        os.chdir(topobjdir)

    def tearDown(self):
        os.chdir(self.cwd)

    def test_preprocess_manifest(self):
        with MockedOpen({"manifest": MANIFEST}):
            preprocess_manifest(self.sink, "manifest")
        self.assertEqual(self.sink.log, self.EXPECTED_LOG)

    def test_preprocess_manifest_missing_define(self):
        with MockedOpen({"manifest": MANIFEST}):
            self.assertRaises(
                Preprocessor.Error,
                preprocess_manifest,
                self.sink,
                "manifest",
                {"baz": 1},
            )

    def test_preprocess_manifest_defines(self):
        with MockedOpen({"manifest": MANIFEST}):
            preprocess_manifest(self.sink, "manifest", {"baz": 1, "SUFFIX": ".exe"})
        self.assertEqual(
            self.sink.log,
            self.EXPECTED_LOG + [((self.MANIFEST_PATH, 12), "add", "baz", "baz.exe")],
        )

class MockFinder(object):
    def __init__(self, files):
        self.files = files
        self.log = []

    def find(self, path):
        self.log.append(path)
        for f in sorted(self.files):
            if mozpath.match(f, path):
                yield f, self.files[f]

    def __iter__(self):
        return self.find("")

class MockFormatter(object):
    def __init__(self):
        self.log = []

    def add_base(self, *args):
        self._log(errors.get_context(), "add_base", *args)

    def add_manifest(self, *args):
        self._log(errors.get_context(), "add_manifest", *args)

    def add_interfaces(self, *args):
        self._log(errors.get_context(), "add_interfaces", *args)

    def add(self, *args):
        self._log(errors.get_context(), "add", *args)

    def _log(self, *args):
        self.log.append(args)

class TestSimplePackager(unittest.TestCase):
    def test_simple_packager(self):
        class GeneratedFileWithPath(GeneratedFile):
            def __init__(self, path, content):
                GeneratedFile.__init__(self, content)
                self.path = path

        formatter = MockFormatter()
        packager = SimplePackager(formatter)
        curdir = os.path.abspath(os.curdir)
        file = GeneratedFileWithPath(
            os.path.join(curdir, "foo", "bar.manifest"),
            b"resource bar bar/\ncontent bar bar/",
        )
        with errors.context("manifest", 1):
            packager.add("foo/bar.manifest", file)

        file = GeneratedFileWithPath(
            os.path.join(curdir, "foo", "baz.manifest"), b"resource baz baz/"
        )
        with errors.context("manifest", 2):
            packager.add("bar/baz.manifest", file)

        with errors.context("manifest", 3):
            packager.add(
                "qux/qux.manifest",
                GeneratedFile(
                    b"".join(
                        [
                            b"resource qux qux/\n",
                            b"binary-component qux.so\n",
                        ]
                    )
                ),
            )
        bar_xpt = GeneratedFile(b"bar.xpt")
        qux_xpt = GeneratedFile(b"qux.xpt")
        foo_html = GeneratedFile(b"foo_html")
        bar_html = GeneratedFile(b"bar_html")
        with errors.context("manifest", 4):
            packager.add("foo/bar.xpt", bar_xpt)
        with errors.context("manifest", 5):
            packager.add("foo/bar/foo.html", foo_html)
            packager.add("foo/bar/bar.html", bar_html)

        file = GeneratedFileWithPath(
            os.path.join(curdir, "foo.manifest"),
            b"".join(
                [
                    b"manifest foo/bar.manifest\n",
                    b"manifest bar/baz.manifest\n",
                ]
            ),
        )
        with errors.context("manifest", 6):
            packager.add("foo.manifest", file)
        with errors.context("manifest", 7):
            packager.add("foo/qux.xpt", qux_xpt)

        file = GeneratedFileWithPath(
            os.path.join(curdir, "addon", "chrome.manifest"), b"resource hoge hoge/"
        )
        with errors.context("manifest", 8):
            packager.add("addon/chrome.manifest", file)

        install_rdf = GeneratedFile(b"<RDF></RDF>")
        with errors.context("manifest", 9):
            packager.add("addon/install.rdf", install_rdf)

        with errors.context("manifest", 10):
            packager.add("addon2/install.rdf", install_rdf)
            packager.add(
                "addon2/chrome.manifest", GeneratedFile(b"binary-component addon2.so")
            )

        with errors.context("manifest", 11):
            packager.add("addon3/install.rdf", install_rdf)
            packager.add(
                "addon3/chrome.manifest",
                GeneratedFile(b"manifest components/components.manifest"),
            )
            packager.add(
                "addon3/components/components.manifest",
                GeneratedFile(b"binary-component addon3.so"),
            )

        with errors.context("manifest", 12):
            install_rdf_addon4 = GeneratedFile(
                b"<RDF>\n<...>\n<em:unpack>true</em:unpack>\n<...>\n</RDF>"
            )
            packager.add("addon4/install.rdf", install_rdf_addon4)

        with errors.context("manifest", 13):
            install_rdf_addon5 = GeneratedFile(
                b"<RDF>\n<...>\n<em:unpack>false</em:unpack>\n<...>\n</RDF>"
            )
            packager.add("addon5/install.rdf", install_rdf_addon5)

        with errors.context("manifest", 14):
            install_rdf_addon6 = GeneratedFile(
                b"<RDF>\n<... em:unpack=true>\n<...>\n</RDF>"
            )
            packager.add("addon6/install.rdf", install_rdf_addon6)

        with errors.context("manifest", 15):
            install_rdf_addon7 = GeneratedFile(
                b"<RDF>\n<... em:unpack=false>\n<...>\n</RDF>"
            )
            packager.add("addon7/install.rdf", install_rdf_addon7)

        with errors.context("manifest", 16):
            install_rdf_addon8 = GeneratedFile(
                b'<RDF>\n<... em:unpack="true">\n<...>\n</RDF>'
            )
            packager.add("addon8/install.rdf", install_rdf_addon8)

        with errors.context("manifest", 17):
            install_rdf_addon9 = GeneratedFile(
                b'<RDF>\n<... em:unpack="false">\n<...>\n</RDF>'
            )
            packager.add("addon9/install.rdf", install_rdf_addon9)

        with errors.context("manifest", 18):
            install_rdf_addon10 = GeneratedFile(
                b"<RDF>\n<... em:unpack='true'>\n<...>\n</RDF>"
            )
            packager.add("addon10/install.rdf", install_rdf_addon10)

        with errors.context("manifest", 19):
            install_rdf_addon11 = GeneratedFile(
                b"<RDF>\n<... em:unpack='false'>\n<...>\n</RDF>"
            )
            packager.add("addon11/install.rdf", install_rdf_addon11)

        we_manifest = GeneratedFile(
            b'{"manifest_version": 2, "name": "Test WebExtension", "version": "1.0"}'
        )
        # hybrid and hybrid2 are both bootstrapped extensions with
        # embedded webextensions, they differ in the order in which
        # the manifests are added to the packager.
        with errors.context("manifest", 20):
            packager.add("hybrid/install.rdf", install_rdf)

        with errors.context("manifest", 21):
            packager.add("hybrid/webextension/manifest.json", we_manifest)

        with errors.context("manifest", 22):
            packager.add("hybrid2/webextension/manifest.json", we_manifest)

        with errors.context("manifest", 23):
            packager.add("hybrid2/install.rdf", install_rdf)

        with errors.context("manifest", 24):
            packager.add("webextension/manifest.json", we_manifest)

        non_we_manifest = GeneratedFile(b'{"not a webextension": true}')
        with errors.context("manifest", 25):
            packager.add("nonwebextension/manifest.json", non_we_manifest)

        self.assertEqual(formatter.log, [])

        with errors.context("dummy", 1):
            packager.close()
        self.maxDiff = None
        # The formatter is expected to reorder the manifest entries so that
        # chrome entries appear before the others.
        self.assertEqual(
            formatter.log,
            [
                (("dummy", 1), "add_base", "", False),
                (("dummy", 1), "add_base", "addon", True),
                (("dummy", 1), "add_base", "addon10", "unpacked"),
                (("dummy", 1), "add_base", "addon11", True),
                (("dummy", 1), "add_base", "addon2", "unpacked"),
                (("dummy", 1), "add_base", "addon3", "unpacked"),
                (("dummy", 1), "add_base", "addon4", "unpacked"),
                (("dummy", 1), "add_base", "addon5", True),
                (("dummy", 1), "add_base", "addon6", "unpacked"),
                (("dummy", 1), "add_base", "addon7", True),
                (("dummy", 1), "add_base", "addon8", "unpacked"),
                (("dummy", 1), "add_base", "addon9", True),
                (("dummy", 1), "add_base", "hybrid", True),
                (("dummy", 1), "add_base", "hybrid2", True),
                (("dummy", 1), "add_base", "qux", False),
                (("dummy", 1), "add_base", "webextension", True),
                (
                    (os.path.join(curdir, "foo", "bar.manifest"), 2),
                    "add_manifest",
                    ManifestContent("foo", "bar", "bar/"),
                ),
                (
                    (os.path.join(curdir, "foo", "bar.manifest"), 1),
                    "add_manifest",
                    ManifestResource("foo", "bar", "bar/"),
                ),
                (
                    ("bar/baz.manifest", 1),
                    "add_manifest",
                    ManifestResource("bar", "baz", "baz/"),
                ),
                (
                    ("qux/qux.manifest", 1),
                    "add_manifest",
                    ManifestResource("qux", "qux", "qux/"),
                ),
                (
                    ("qux/qux.manifest", 2),
                    "add_manifest",
                    ManifestBinaryComponent("qux", "qux.so"),
                ),
                (("manifest", 4), "add_interfaces", "foo/bar.xpt", bar_xpt),
                (("manifest", 7), "add_interfaces", "foo/qux.xpt", qux_xpt),
                (
                    (os.path.join(curdir, "addon", "chrome.manifest"), 1),
                    "add_manifest",
                    ManifestResource("addon", "hoge", "hoge/"),
                ),
                (
                    ("addon2/chrome.manifest", 1),
                    "add_manifest",
                    ManifestBinaryComponent("addon2", "addon2.so"),
                ),
                (
                    ("addon3/components/components.manifest", 1),
                    "add_manifest",
                    ManifestBinaryComponent("addon3/components", "addon3.so"),
                ),
                (("manifest", 5), "add", "foo/bar/foo.html", foo_html),
                (("manifest", 5), "add", "foo/bar/bar.html", bar_html),
                (("manifest", 9), "add", "addon/install.rdf", install_rdf),
                (("manifest", 10), "add", "addon2/install.rdf", install_rdf),
                (("manifest", 11), "add", "addon3/install.rdf", install_rdf),
                (("manifest", 12), "add", "addon4/install.rdf", install_rdf_addon4),
                (("manifest", 13), "add", "addon5/install.rdf", install_rdf_addon5),
                (("manifest", 14), "add", "addon6/install.rdf", install_rdf_addon6),
                (("manifest", 15), "add", "addon7/install.rdf", install_rdf_addon7),
                (("manifest", 16), "add", "addon8/install.rdf", install_rdf_addon8),
                (("manifest", 17), "add", "addon9/install.rdf", install_rdf_addon9),
                (("manifest", 18), "add", "addon10/install.rdf", install_rdf_addon10),
                (("manifest", 19), "add", "addon11/install.rdf", install_rdf_addon11),
                (("manifest", 20), "add", "hybrid/install.rdf", install_rdf),
                (
                    ("manifest", 21),
                    "add",
                    "hybrid/webextension/manifest.json",
                    we_manifest,
                ),
                (
                    ("manifest", 22),
                    "add",
                    "hybrid2/webextension/manifest.json",
                    we_manifest,
                ),
                (("manifest", 23), "add", "hybrid2/install.rdf", install_rdf),
                (("manifest", 24), "add", "webextension/manifest.json", we_manifest),
                (
                    ("manifest", 25),
                    "add",
                    "nonwebextension/manifest.json",
                    non_we_manifest,
                ),
            ],
        )

        self.assertEqual(
            packager.get_bases(),
            set(
                [
                    "",
                    "addon",
                    "addon2",
                    "addon3",
                    "addon4",
                    "addon5",
                    "addon6",
                    "addon7",
                    "addon8",
                    "addon9",
                    "addon10",
                    "addon11",
                    "qux",
                    "hybrid",
                    "hybrid2",
                    "webextension",
                ]
            ),
        )
        self.assertEqual(packager.get_bases(addons=False), set(["", "qux"]))

    def test_simple_packager_manifest_consistency(self):
        formatter = MockFormatter()
        # bar/ is detected as an addon because of install.rdf, but top-level
        # includes a manifest inside bar/.
        packager = SimplePackager(formatter)
        packager.add(
            "base.manifest",
            GeneratedFile(
                b"manifest foo/bar.manifest\n" b"manifest bar/baz.manifest\n"
            ),
        )
        packager.add("foo/bar.manifest", GeneratedFile(b"resource bar bar"))
        packager.add("bar/baz.manifest", GeneratedFile(b"resource baz baz"))
        packager.add("bar/install.rdf", GeneratedFile(b""))

        with self.assertRaises(ErrorMessage) as e:
            packager.close()

        self.assertEqual(
            str(e.exception),
            'error: "bar/baz.manifest" is included from "base.manifest", '
            'which is outside "bar"',
        )

        # bar/ is detected as a separate base because of chrome.manifest that
        # is included nowhere, but top-level includes another manifest inside
        # bar/.
        packager = SimplePackager(formatter)
        packager.add(
            "base.manifest",
            GeneratedFile(
                b"manifest foo/bar.manifest\n" b"manifest bar/baz.manifest\n"
            ),
        )
        packager.add("foo/bar.manifest", GeneratedFile(b"resource bar bar"))
        packager.add("bar/baz.manifest", GeneratedFile(b"resource baz baz"))
        packager.add("bar/chrome.manifest", GeneratedFile(b"resource baz baz"))

        with self.assertRaises(ErrorMessage) as e:
            packager.close()

        self.assertEqual(
            str(e.exception),
            'error: "bar/baz.manifest" is included from "base.manifest", '
            'which is outside "bar"',
        )

        # bar/ is detected as a separate base because of chrome.manifest that
        # is included nowhere, but chrome.manifest includes baz.manifest from
        # the same directory. This shouldn't error out.
        packager = SimplePackager(formatter)
        packager.add("base.manifest", GeneratedFile(b"manifest foo/bar.manifest\n"))
        packager.add("foo/bar.manifest", GeneratedFile(b"resource bar bar"))
        packager.add("bar/baz.manifest", GeneratedFile(b"resource baz baz"))
        packager.add("bar/chrome.manifest", GeneratedFile(b"manifest baz.manifest"))
        packager.close()

class TestSimpleManifestSink(unittest.TestCase):
    def test_simple_manifest_parser(self):
        formatter = MockFormatter()
        foobar = GeneratedFile(b"foobar")
        foobaz = GeneratedFile(b"foobaz")
        fooqux = GeneratedFile(b"fooqux")
        foozot = GeneratedFile(b"foozot")
        finder = MockFinder(
            {
                "bin/foo/bar": foobar,
                "bin/foo/baz": foobaz,
                "bin/foo/qux": fooqux,
                "bin/foo/zot": foozot,
                "bin/foo/chrome.manifest": GeneratedFile(b"resource foo foo/"),
                "bin/chrome.manifest": GeneratedFile(b"manifest foo/chrome.manifest"),
            }
        )
        parser = SimpleManifestSink(finder, formatter)
        component0 = Component("component0")
        component1 = Component("component1")
        component2 = Component("component2", destdir="destdir")
        parser.add(component0, "bin/foo/b*")
        parser.add(component1, "bin/foo/qux")
        parser.add(component1, "bin/foo/chrome.manifest")
        parser.add(component2, "bin/foo/zot")
        self.assertRaises(ErrorMessage, parser.add, "component1", "bin/bar")

        self.assertEqual(formatter.log, [])
        parser.close()
        self.assertEqual(
            formatter.log,
            [
                (None, "add_base", "", False),
                (
                    ("foo/chrome.manifest", 1),
                    "add_manifest",
                    ManifestResource("foo", "foo", "foo/"),
                ),
                (None, "add", "foo/bar", foobar),
                (None, "add", "foo/baz", foobaz),
                (None, "add", "foo/qux", fooqux),
                (None, "add", "destdir/foo/zot", foozot),
            ],
        )

        self.assertEqual(
            finder.log,
            [
                "bin/foo/b*",
                "bin/foo/qux",
                "bin/foo/chrome.manifest",
                "bin/foo/zot",
                "bin/bar",
                "bin/chrome.manifest",
            ],
        )

class TestCallDeque(unittest.TestCase):
    def test_call_deque(self):
        class Logger(object):
            def __init__(self):
                self._log = []

            def log(self, str):
                self._log.append(str)

            @staticmethod
            def staticlog(logger, str):
                logger.log(str)

        def do_log(logger, str):
            logger.log(str)

        logger = Logger()
        d = CallDeque()
        d.append(logger.log, "foo")
        d.append(logger.log, "bar")
        d.append(logger.staticlog, logger, "baz")
        d.append(do_log, logger, "qux")
        self.assertEqual(logger._log, [])
        d.execute()
        self.assertEqual(logger._log, ["foo", "bar", "baz", "qux"])

class TestComponent(unittest.TestCase):
    def do_split(self, string, name, options):
        n, o = Component._split_component_and_options(string)
        self.assertEqual(name, n)
        self.assertEqual(options, o)

    def test_component_split_component_and_options(self):
        self.do_split("component", "component", {})
        self.do_split("trailingspace ", "trailingspace", {})
        self.do_split(" leadingspace", "leadingspace", {})
        self.do_split(" trim ", "trim", {})
        self.do_split(' trim key="value"', "trim", {"key": "value"})
        self.do_split(' trim empty=""', "trim", {"empty": ""})
        self.do_split(' trim space=" "', "trim", {"space": " "})
        self.do_split(
            'component key="value"  key2="second" ',
            "component",
            {"key": "value", "key2": "second"},
        )
        self.do_split(
            'trim key="  value with spaces   "  key2="spaces again"',
            "trim",
            {"key": "  value with spaces   ", "key2": "spaces again"},
        )

    def do_split_error(self, string):
        self.assertRaises(ValueError, Component._split_component_and_options, string)

    def test_component_split_component_and_options_errors(self):
        self.do_split_error('"component')
        self.do_split_error('comp"onent')
        self.do_split_error('component"')
        self.do_split_error('"component"')
        self.do_split_error("=component")
        self.do_split_error("comp=onent")
        self.do_split_error("component=")
        self.do_split_error('key="val"')
        self.do_split_error("component key=")
        self.do_split_error('component key="val')
        self.do_split_error('component key=val"')
        self.do_split_error('component key="val" x')
        self.do_split_error('component x key="val"')
        self.do_split_error('component key1="val" x key2="val"')

    def do_from_string(self, string, name, destdir=""):
        component = Component.from_string(string)
        self.assertEqual(name, component.name)
        self.assertEqual(destdir, component.destdir)

    def test_component_from_string(self):
        self.do_from_string("component", "component")
        self.do_from_string("component-with-hyphen", "component-with-hyphen")
        self.do_from_string('component destdir="foo/bar"', "component", "foo/bar")
        self.do_from_string('component destdir="bar spc"', "component", "bar spc")
        self.assertRaises(ErrorMessage, Component.from_string, "")
        self.assertRaises(ErrorMessage, Component.from_string, "component novalue=")
        self.assertRaises(
            ErrorMessage, Component.from_string, "component badoption=badvalue"
        )

if __name__ == "__main__":
    mozunit.main()


import xlrd2
import sys

if len(sys.argv) > 1:
    path = sys.argv[1]
    xl_workbook = xlrd2.open_workbook(path, formatting_info=True)
    defined_names = xl_workbook.name_map
    for sheet in xl_workbook.sheets():
        if sheet.boundsheet_type == xlrd2.biffh.XL_MACROSHEET:
            print(sheet.name)
            for cell in sheet.get_used_cells():
                if cell.formula is not None and len(cell.formula)>0:
                    print("({},{}):\t{},\t{}".format(cell.row, cell.column, cell.formula, cell.value))


import json
import typing

from aiohttp.web_exceptions import (
    HTTPException,
    HTTPUnprocessableEntity,
    HTTPForbidden,
    HTTPUnauthorized,
    HTTPInternalServerError,
    HTTPConflict,
    HTTPNotFound,
    HTTPMethodNotAllowed,
)
from aiohttp.web_middlewares import middleware
from aiohttp_apispec import validation_middleware
from aiohttp_session import get_session

from app.admin.models import Admin
from app.web.utils import error_json_response

if typing.TYPE_CHECKING:
    from app.web.app import Application, Request

@middleware
async def auth_middleware(request: "Request", handler: callable):
    session = await get_session(request)
    print(session)
    if session:
        request.admin = Admin.from_session(session)
    return await handler(request)

HTTP_ERROR_CODES = {
    400: "bad_request",
    401: "unauthorized",
    403: "forbidden",
    404: "not_found",
    405: "not_implemented",
    409: "conflict",
    500: "internal_server_error",
}

@middleware
async def error_handling_middleware(request: "Request", handler):
    try:
        response = await handler(request)
        return response
    except HTTPUnprocessableEntity as e:
        return error_json_response(
            http_status=400,
            status=HTTP_ERROR_CODES[400],
            message=e.reason,
            data=json.loads(e.text),
        )
    except HTTPForbidden as e:
        return error_json_response(
            http_status=403,
            status=HTTP_ERROR_CODES[403],
            message="Provide valid credentials (email/password) for get access",
            data=e.text,
        )
    except HTTPUnauthorized as e:
        return error_json_response(
            http_status=401,
            status=HTTP_ERROR_CODES[401],
            message="You must be authorized for do this action",
            data=e.text,
        )
    except HTTPInternalServerError as e:
        return error_json_response(
            http_status=500,
            status=HTTP_ERROR_CODES[500],
            message=e.text,
        )
    except HTTPConflict as e:
        return error_json_response(
            http_status=409,
            status=HTTP_ERROR_CODES[409],
            message=e.text,
        )
    except HTTPNotFound as e:
        return error_json_response(
            http_status=404,
            status=HTTP_ERROR_CODES[404],
            message=e.text,
        )
    except HTTPMethodNotAllowed as e:
        return error_json_response(
            http_status=405,
            status=HTTP_ERROR_CODES[405],
            message=e.text,
        )

def setup_middlewares(app: "Application"):
    app.middlewares.append(auth_middleware)
    app.middlewares.append(error_handling_middleware)
    app.middlewares.append(validation_middleware)


#NeuronBrain.py
from NeuronBase import NeuronBase
import numpy as np

class NeuronBrain(NeuronBase):
    def __init__(self,network,x,y,z):
        NeuronBase.__init__(self,network)
        self.x = x
        self.y = y
        self.z = z
        self.threshold = 0.5
        self.initWeight = 0
        self.learnVal = 0.5
        self.forgetVal = 0.1
        #self.useless_rate = 0.95
        self.childrenNum = 3
        self.distance = []

    def init_distance(self):
        if self.distance != []:
            return
        distance = np.zeros(self.network.size)
        for ni in range(self.network.size):
            node = self.network.nodeList[ni]
            if (self.x == node.x and self.y == node.y and self.z == node.z):
                distance[ni] = np.inf
            else:
                distance[ni] = (node.x - self.x)**2 + (node.y - self.y)**2 + (node.z - self.z)**2

        distance = 1 / distance
        distance = distance / distance.sum()
        self.distance = distance

    def set_child(self):
        rand = np.random.rand()
        for ni in range(self.network.size):
            rand -= self.distance[ni]
            if(rand <= 0.):
                self.children.append([self.network.nodeList[ni], self.initWeight])
                return

    def init_children(self):
        print(self)
        self.init_distance()
        print(self.distance)
        for ci in range(self.childrenNum):
            self.set_child()

    def learn(self):
        if self.input > self.threshold:
            for child in self.children:
                if child[0].fireFlag:
                    child[1] += self.learnVal
                else:
                    child[1] -= self.forgetVal
        #else:
        #    for child in self.children:
        #        child[1] *= self.useless_rate

        for ci in range(self.childrenNum):
            if self.children[ci][1] < -5:
                del self.children[ci]
                self.set_child()

    def post_fire(self):
        if self.input > self.threshold:# and self.fire_flag == False:
            self.fireFlag = True
            self.output = 1.0
        else:
            self.fireFlag = False
            self.output = 0.0
        self.input = 0.0

    def status(self):
        print("""
--Brain
BrainNode({}, {}, {})
threshold   = {}\
""".format(self.x, self.y, self.z, self.threshold))
        NeuronBase.status(self)

    def __repr__(self):
        s = "({}, {}, {})".format(self.x, self.y, self.z)
        return s


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

from odoo import fields, api, models, _
from odoo.exceptions import UserError

class PurchaseOrder(models.Model):
    _inherit = 'purchase.order'

    other_tax = fields.Float(string="Other Tax", compute="_amount_all")
    amount_tva = fields.Float(string="Amount TVA", compute="_amount_all")

    travel_order_id = fields.Many2one('travel.order', string="Travel Order", readonly=True)

    @api.depends('order_line.price_total', 'order_line.other_tax')
    def _amount_all(self):
        super(PurchaseOrder, self)._amount_all()
        for order in self:
            other_tax = 0.0
            amount_tva = order.amount_total - order.amount_untaxed
            for line in order.order_line:
                other_tax += line.other_tax

            order.update({
                'other_tax' : order.currency_id.round(other_tax),
                'amount_tva' : amount_tva,
                'amount_total' : order.amount_total + order.currency_id.round(other_tax),
            })

class PurchaseOrderLine(models.Model):
    _inherit = 'purchase.order.line'

    other_tax = fields.Float(string="Other Tax")

    @api.depends('product_qty', 'price_unit', 'taxes_id', 'other_tax')
    def _compute_amount(self):
        super(PurchaseOrderLine, self)._compute_amount()
        for line in self:
            line.update({
                'price_total' : line.price_total + line.other_tax,
            })

    def _prepare_account_move_line(self, move=False):
        res = super(PurchaseOrderLine, self)._prepare_account_move_line(move)

        # raise UserError(str(res))
        res.update({'other_tax' : self.other_tax})

        return res


import copy
from typing import List, Tuple

def print_graph(graph):
    for i in range(len(graph)):
        print(graph[i])

def read_and_parse_input(file_name: str):
    with open(file_name, "r") as input_file:
        contents = input_file.readlines()
    for i, content in enumerate(contents):
        content = content.replace("\n", "")
        contents[i] = [char for char in content]
    return contents

def process_point(i: int, j: int, value: str, graph) -> str:
    count = 0
    adjacent = [(1, 0), (0, 1), (1, 1), (-1, 0), (0, -1), (-1, 1), (1, -1), (-1, -1)]
    if value == "L":
        tmp_cntr = 0
        for neighbour in adjacent:
            x_off, y_off = neighbour
            if 0 <= x_off + i < len(graph) and 0 <= y_off + j < len(graph[i]):
                if graph[x_off + i][y_off + j] != "#":
                    count += 1
            else:
                tmp_cntr += 1
        return count == len(adjacent) - tmp_cntr
    elif value == "#":
        for neighbour in adjacent:
            x_off, y_off = neighbour
            if 0 <= x_off + i < len(graph) and 0 <= y_off + j < len(graph[i]):
                if graph[x_off + i][y_off + j] == "#":
                    count += 1
        return count >= 4

def process_point_2(i: int, j: int, graph):
    directions = [(1, 0), (0, 1), (1, 1), (-1, 0), (0, -1), (-1, 1), (1, -1), (-1, -1)]
    tmp_cntr = 0
    hash_cntr = 0
    reg_cntr = 0
    for direction in directions:
        next_ = find_next_point(i, j, direction, graph)
        if next_ == -1:
            tmp_cntr += 1
        elif next_ == "#":
            hash_cntr += 1
        elif next_ != "#":
            reg_cntr += 1
    if graph[i][j] == "L":
        return reg_cntr == len(directions) - tmp_cntr
    if graph[i][j] == "#":
        return hash_cntr >= 5

def find_next_point(i: int, j: int, direction: Tuple[int, int], graph):
    x_off, y_off = i + direction[0], j + direction[1]
    while 0 <= x_off < len(graph) and 0 <= y_off < len(graph[i]):
        if graph[x_off][y_off] != ".":
            return graph[x_off][y_off]
        x_off += direction[0]
        y_off += direction[1]
    return -1

def fill_seats(graph: List[List[str]]) -> List[List[str]]:
    output = copy.deepcopy(graph)
    for i in range(len(graph)):
        for j in range(len(graph[i])):
            if graph[i][j] == "L":
                count = process_point(i, j, graph[i][j], graph)
                output[i][j] = "#" if count else graph[i][j]
            elif graph[i][j] == "#":
                count = process_point(i, j, graph[i][j], graph)
                output[i][j] = "L" if count else graph[i][j]
            else:
                output[i][j] = graph[i][j]
    return output

def fill_seats_2(graph):
    output = copy.deepcopy(graph)
    for i in range(len(graph)):
        for j in range(len(graph[i])):
            if graph[i][j] == "L":
                count = process_point_2(i, j, graph)
                output[i][j] = "#" if count else graph[i][j]
            elif graph[i][j] == "#":
                count = process_point_2(i, j, graph)
                output[i][j] = "L" if count else graph[i][j]
            else:
                output[i][j] = graph[i][j]
    return output

def same_graph(prev, graph):
    for i in range(len(graph)):
        for j in range(len(graph[i])):
            if graph[i][j] != prev[i][j]:
                return False
    return True

def count_occupied(graph):
    count = 0
    for i in range(len(graph)):
        for j in range(len(graph[i])):
            if graph[i][j] == "#":
                count += 1
    return count

if __name__ == "__main__":
    graph = read_and_parse_input("input.txt")
    prev = graph
    while True:
        graph = fill_seats_2(graph)
        if same_graph(prev, graph):
            print(count_occupied(graph))
            break
        prev = graph


# -*- coding: utf-8 -*-
"""
Created on Mon Sep 12 15:56:02 2022

@author: arman hossain

!python excel.py
"""

import sys

from PyQt5.QtWidgets import (
    QApplication, QWidget, QHeaderView
)
from PyQt5.uic import loadUi
import pickle
import os

class Excel(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        loadUi("excel.ui", self)
        self.sortChanged(0)
        self.setWindowTitle("List View")
        self.connect()
        self.initui()
        self.total_data_label.setText(str(len(self.tableWidget.data))+"         ")

    def initui(self):
        header = self.tableWidget.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        self.initCombo()

    def initCombo(self):
        if os.path.exists('./data/2002-2022-vendor-year-count.pickle'):
            self.comboBox.addItems(['All']+list(self.read_data("./data/2002-2022-vendor-year-count.pickle").keys()))

    def read_data(self,filename):
        with open(filename, 'rb') as file:
            obj = pickle.load(file)
            return obj

    def connect(self):
        self.previous_btn.clicked.connect(self.previous_pressed)
        self.next_btn.clicked.connect(self.next_pressed)
        self.plus_btn.clicked.connect(self.current_plus_pressed)
        self.minus_btn.clicked.connect(self.current_minus_pressed)
        # self.current_btn.clicked.connect(self.current_btn_pressed)
        self.tableWidget.horizontalHeader().sortIndicatorChanged.connect(self.sortChanged)
        self.comboBox.activated.connect(self.comboindexchanged)

    def comboindexchanged(self,index):
        vendor = self.comboBox.itemText(index)
        self.tableWidget.filter_dataset(vendor)
        self.tableWidget.goto_page(1)
        self.setbuttontext(1)
        self.total_data_label.setText(str(len(self.tableWidget.data))+"         ")

    def sortChanged(self,index):
        self.tableWidget.sortChanged(index)
        self.tableWidget.goto_page(1)
        self.setbuttontext(1)

    def reload_data(self):
        self.tableWidget.reload_data()
        self.comboBox.setCurrentIndex(0)
        self.tableWidget.goto_page(1)
        self.setbuttontext(1)

    def setbuttontext(self,number):
        if number < 1:
            return
        if number == 1:
            self.previous_btn.setEnabled(False)
        else:
            self.previous_btn.setEnabled(True)
        next = number+self.tableWidget.item_per_page
        pre = number-self.tableWidget.item_per_page
        self.current_btn.setText(str(number))
        self.plus_btn.setText(str(next))
        if pre>0:
            self.minus_btn.setEnabled(True)
            self.minus_btn.setText(str(pre))
        else:
            self.minus_btn.setText(str(0))
            self.minus_btn.setEnabled(False)

    def current_plus_pressed(self):
        self.tableWidget.goto_page(int(self.plus_btn.text()))
        self.setbuttontext(int(self.plus_btn.text()))
    def current_minus_pressed(self):
        self.tableWidget.goto_page(int(self.minus_btn.text()))
        self.setbuttontext(int(self.minus_btn.text()))
    def next_pressed(self):
        self.tableWidget.goto_page_next()
        self.setbuttontext(int(self.current_btn.text())+1)
    def previous_pressed(self):
        self.tableWidget.goto_page_pre()
        self.setbuttontext(int(self.current_btn.text())-1)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Excel()
    win.show()
    sys.exit(app.exec())


"""
Given a string S and a character C, return an array of integers representing the shortest distance from the character C in the string.

Example 1:

Input: S = "loveleetcode", C = 'e'
Output: [3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0]

Note:

S string length is in [1, 10000].
C is a single character, and guaranteed to be in string S.
All letters in S and C are lowercase.
"""

class Solution:
    def shortestToChar(self, S, C):
        """
        :type S: str
        :type C: str
        :rtype: List[int]
        """
        result = [-1 for i in range(len(S))]
        pos = []
        for i in range(len(S)):
            if C == S[i]:
                pos.append(i)
                result[i] == 0

        for i in range(len(result)):
            if result[i] != 0:
                dis = 10000
                for j in pos:
                    if i - j < 0:
                        tmp = -(i-j)
                    else:
                        tmp = i-j
                    if tmp < dis:
                        dis = tmp
                result[i] = dis

        return result


class Board:
# _0_|_1_|_2_
# _3_|_4_|_5_
#  6 | 7 | 8

    def __init__(self,game_name):
        self.current_turn = ''
        self.playerX_pos = []
        self.playerO_pos = []
        self.valid_positions = [0,1,2,3,4,5,6,7,8]
        self.win_conditions = ((0,1,2),
                               (3,4,5),
                               (6,7,8),
                               (0,3,6),
                               (1,4,7),
                               (2,5,8),
                               (0,4,8),
                               (2,4,6))
        self.pos = ['_'] * 6
        for i in range(7,10,1):
            self.pos.append(' ')

    def __str__(self):
       table = ('\n_'+str(self.pos[0])+'_|_'+str(self.pos[1])+'_|_'+str(self.pos[2])+'_')
       table += ('\n_'+str(self.pos[3])+'_|_'+str(self.pos[4])+'_|_'+str(self.pos[5])+'_')
       table += ('\n '+str(self.pos[6])+' | '+str(self.pos[7])+' | '+str(self.pos[8]))
       return table

    def table_positions(self):
       print('_0_|_1_|_2_\n_3_|_4_|_5_\n 6 | 7 | 8  ')

    def reset_game(self,game_name):
        self.pos = ['_'] * 6
        for i in range(7,10,1):
            self.pos.append(' ')

    def check_win(self):
        for each_win in self.win_conditions:
            if all(positions in self.playerX_pos for positions in each_win):
                print('X venceu!')
                return True
            elif all(positions in self.playerO_pos for positions in each_win):
                print('O venceu!')
                return True
        return 0

    def change_pos(self,pos,player):
        if (player=='X'):
            self.pos[pos] = 'X'
            self.playerX_pos.append(pos)
            self.check_win(self)
        elif (player=='O'):
            self.pos[pos] = 'O'
            self.playerO_pos.append(pos)
            self.check_win(self)

    def start_game(self):
        print('\nEssas são as posições do tabuleiro!')
        self.table_positions()
        self.current_turn = input('Quem começa? Digite X ou O: ')
        while (not self.current_turn in ['X','O']):
            self.current_turn = input('Escolha apenas das opções disponíveis (X ou O): ')
        self.reset_game(self)
        if (self.game_flow()):
            print('Fim de jogo!')

    def game_flow(self):
        while (len(self.playerO_pos)+len(self.playerX_pos)) < len(self.pos):
            print('É sua vez, '+str(self.current_turn)+'!')
            valid_entry=False
            pos = int(input('Qual posição quer jogar? '))
            while (valid_entry==False):
                if (pos not in self.valid_positions):
                    pos = int(input('Escolha uma posição válida!'))
                elif ((pos in self.playerX_pos) or (pos in self.playerO_pos)):
                    pos = int(input('Esta posição já foi jogada antes!'))
                else:
                    valid_entry=True
            self.pos[pos] = str(self.current_turn)
            if self.current_turn=='X':
                self.playerX_pos.append(pos)
                self.current_turn='O'
            else:
                self.playerO_pos.append(pos)
                self.current_turn='X'
            print(self)
            if (self.check_win()):
                return 1

game = Board('PrimeiroGameEver')
game.start_game()