import json
from pathlib import Path
from textwrap import dedent, indent
from typing import List, Set

import typer

from back.crud.async_elasticsearch import CrudAsyncElasticsearchBase
from lib.typer import ZetsuBouTyper
from tests.back.utils.test_keyword import get_data

_help = """
Build the documentation.
"""
app = ZetsuBouTyper(name="docs", help=_help)

class CrudAsyncElasticsearchTest(CrudAsyncElasticsearchBase):
    @property
    def fields(self) -> List[str]:
        return ["tags.*"]

    async def get_field_names(self) -> Set[str]:
        return {"tags.language"}

async def get_search_grammar_example():
    docs_indent = "    "
    crud = CrudAsyncElasticsearchTest(is_from_setting_if_none=True)

    examples = "#### Examples\n"
    data = get_data()

    for d in data:
        example = "\n"
        if not d.show_docs:
            continue

        example += f"- {d.docs}\n\n"

        keyword_length = len(d.keywords) - 1
        example += '=== "Input"\n\n'
        first_keyword = ""
        for i, keyword in enumerate(d.keywords):
            keyword_block = ""

            keyword_block += f"""\
            ```sh
            {keyword}
            ```
            """
            keyword_block = dedent(keyword_block)

            if i == 0:
                first_keyword = keyword
            if i != keyword_length:
                keyword_block += "\nor\n\n"

            keyword_block = indent(keyword_block, docs_indent)
            example += keyword_block

        example += '\n=== "Elasticsearch"\n'
        elasticsearch_query = await crud.get_match_query(first_keyword)
        elasticsearch_query_str = json.dumps(
            elasticsearch_query, indent=4, ensure_ascii=False
        )
        elasticsearch_query_str = f"\n\n```json\n{elasticsearch_query_str}\n```\n"

        elasticsearch_query_str = indent(elasticsearch_query_str, docs_indent)

        example += elasticsearch_query_str

        example += "\n"

        examples += example
    return examples

@app.command()
async def print_search_grammar_examples():
    """
    Print examples of search grammar.
    """

    docs = ""

    examples = await get_search_grammar_example()
    docs += examples

    print(docs)


#!/usr/local/bin/python

import numpy as np
import matplotlib
render = True
if render:
    matplotlib.use('pgf')
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
from string import split
import scipy.signal as signal
import pysndfile
import math
import os
import re
import json

def main():
    fig, ax = plt.subplots(nrows=2, sharex=False)

    cmap = plt.get_cmap('viridis')

    sndfile = pysndfile.PySndfile('vault.wav', 'r')
    if sndfile.channels() != 1:
        raise RuntimeError('please only load mono files')
    Fs = sndfile.samplerate()
    signal = sndfile.read_frames()
    NFFT=2048
    pxx, freq, time = mlab.specgram(signal, NFFT=NFFT, noverlap=NFFT/2, Fs=Fs)

    def do_impulse_plot():
        time = np.arange(len(signal)) / float(Fs)
        ax[0].plot(time, signal)

        ax[0].set_xlim([0, 0.1])

        ax[0].set_xlabel('time / s')
        ax[0].set_ylabel('amplitude')

        time = 7.12 / 340.0
        ax[0].axvline(time, linestyle='dotted', color='red')
        ax[0].text(time + 0.0005, -0.5, str.format('{0:.3g} s (earliest possible diffraction time)', time))

    def do_spec_plot():
        Z = 10 * np.log10(pxx)

        vmin = -200
        vmax = np.nanmax(Z)

        im = ax[1].pcolormesh(time, freq, Z, cmap=cmap, vmin=vmin, vmax=vmax, rasterized=True)
        ax[1].set_xlim([0, 1])

        ax[1].set_ylim(20, 20000)
        ax[1].set_yscale('log')

        ax[1].set_xlabel('time / s')
        ax[1].set_ylabel('frequency / Hz')

        cb = fig.colorbar(im)
        cb.set_label('dB')

    do_impulse_plot()
    do_spec_plot()

    plt.suptitle('Early Response in Vault Model')

    plt.tight_layout()
    plt.subplots_adjust(top=0.9)

    plt.show()
    if render:
        plt.savefig('vault_response.svg', bbox_inches='tight', dpi=96, format='svg')

if __name__ == '__main__':
    pgf_with_rc_fonts = {
        'font.family': 'serif',
        'font.serif': [],
        'font.sans-serif': ['Helvetica Neue'],
        'font.monospace': ['Input Mono Condensed'],
        'legend.fontsize': 12,
    }

    matplotlib.rcParams.update(pgf_with_rc_fonts)

    main()


"""
Run chardet on a bunch of documents and see that we get the correct encodings.

:author: Dan Blanchard
:author: Ian Cordasco
"""

from __future__ import with_statement

import textwrap
from difflib import ndiff
from io import open
from os import listdir
from os.path import dirname, isdir, join, realpath, relpath, splitext

try:
    import hypothesis.strategies as st
    from hypothesis import given, assume, settings, Verbosity
    HAVE_HYPOTHESIS = True
except ImportError:
    HAVE_HYPOTHESIS = False
import pytest

import chardet

# TODO: Restore Hungarian encodings (iso-8859-2 and windows-1250) after we
#       retrain model.
MISSING_ENCODINGS = set(['iso-8859-2', 'iso-8859-6', 'windows-1250',
                         'windows-1254', 'windows-1256'])
EXPECTED_FAILURES = set(['tests/iso-8859-7-greek/disabled.gr.xml',
                         'tests/iso-8859-9-turkish/divxplanet.com.xml',
                         'tests/iso-8859-9-turkish/subtitle.srt',
                         'tests/iso-8859-9-turkish/wikitop_tr_ISO-8859-9.txt'])

def gen_test_params():
    """Yields tuples of paths and encodings to use for test_encoding_detection"""
    base_path = relpath(join(dirname(realpath(__file__)), 'tests'))
    for encoding in listdir(base_path):
        path = join(base_path, encoding)
        # Skip files in tests directory
        if not isdir(path):
            continue
        # Remove language suffixes from encoding if pressent
        encoding = encoding.lower()
        for postfix in ['-arabic', '-bulgarian', '-cyrillic', '-greek',
                        '-hebrew', '-hungarian', '-turkish']:
            if encoding.endswith(postfix):
                encoding = encoding.rpartition(postfix)[0]
                break
        # Skip directories for encodings we don't handle yet.
        if encoding in MISSING_ENCODINGS:
            continue
        # Test encoding detection for each file we have of encoding for
        for file_name in listdir(path):
            ext = splitext(file_name)[1].lower()
            if ext not in ['.html', '.txt', '.xml', '.srt']:
                continue
            full_path = join(path, file_name)
            test_case = full_path, encoding
            if full_path in EXPECTED_FAILURES:
                test_case = pytest.mark.xfail(test_case)
            yield test_case

@pytest.mark.parametrize ('file_name, encoding', gen_test_params())
def test_encoding_detection(file_name, encoding):
    with open(file_name, 'rb') as f:
        input_bytes = f.read()
        result = chardet.detect(input_bytes)
        try:
            expected_unicode = input_bytes.decode(encoding)
        except LookupError:
            expected_unicode = ''
        try:
            detected_unicode = input_bytes.decode(result['encoding'])
        except (LookupError, UnicodeDecodeError, TypeError):
            detected_unicode = ''
    if result:
        encoding_match = (result['encoding'] or '').lower() == encoding
    else:
        encoding_match = False
    # Only care about mismatches that would actually result in different
    # behavior when decoding
    if not encoding_match and expected_unicode != detected_unicode:
        wrapped_expected = '\n'.join(textwrap.wrap(expected_unicode, 100)) + '\n'
        wrapped_detected = '\n'.join(textwrap.wrap(detected_unicode, 100)) + '\n'
        diff = ''.join(ndiff(wrapped_expected.splitlines(True),
                             wrapped_detected.splitlines(True)))
    else:
        diff = ''
        encoding_match = True
    assert encoding_match, ("Expected %s, but got %s for %s.  Character "
                            "differences: \n%s" % (encoding,
                                                   result,
                                                   file_name,
                                                   diff))

if HAVE_HYPOTHESIS:
    class JustALengthIssue(Exception):
        pass

    @pytest.mark.xfail
    @given(st.text(min_size=1), st.sampled_from(['ascii', 'utf-8', 'utf-16',
                                                 'utf-32', 'iso-8859-7',
                                                 'iso-8859-8', 'windows-1255']),
           st.randoms())
    @settings(max_examples=200)
    def test_never_fails_to_detect_if_there_is_a_valid_encoding(txt, enc, rnd):
        try:
            data = txt.encode(enc)
        except UnicodeEncodeError:
            assume(False)
        detected = chardet.detect(data)['encoding']
        if detected is None:
            with pytest.raises(JustALengthIssue):
                @given(st.text(), random=rnd)
                @settings(verbosity=Verbosity.quiet, max_shrinks=0, max_examples=50)
                def string_poisons_following_text(suffix):
                    try:
                        extended = (txt + suffix).encode(enc)
                    except UnicodeEncodeError:
                        assume(False)
                    result = chardet.detect(extended)
                    if result and result['encoding'] is not None:
                        raise JustALengthIssue()


import os
file= input("File name? ")

if (file[-3:]==".cs"):
#  print(file[-3:])
#  print("This is a C# Source Code.")
  execu= file[:-3]+".exe"
#  print(execu)
  if(os.path.isfile(execu)):
    os.remove(execu)
  os.system("csc "+file)
  if(os.path.isfile(execu)):
    os.system(execu)
    os.remove(execu)
  else:
    print("Something went wrong.")

#elif (file[-5:]==".java"):
#  print(file[-5:])
#  print("This is a Java Source Code.")
#  execu= file[:-5]
#  print(execu)
#  if(os.path.isfile(execu)):
#    os.remove(execu)
#  os.system("javac "+file)
#  if(os.path.isfile(execu)):
#    os.system("java "+execu)
#    os.remove(execu)
#  else:
#    print("Something went wrong.")

else:
  print("This is another file type.")


# Write a Python program to read a random line from a file.

import random

# open the file in read mode
with open(r"F:\Python By Vishu\Worksheet_3.3_py\vishu.txt", 'r') as file:
    # read all the lines into a list
    lines = file.readlines()

# choose a random line from the list
random_line = random.choice(lines)

# print the random line
print(random_line)

Worksheet_3.3_py/program to read a random line from a file.py


"""
 Author: Hieund
 Company: MobioVN
 Date created: 16/09/2021
"""
import os

from PIL import Image
import io
import numpy as np

from configs import Folder
from src.controller.mtcnn_model import create_model

Model_MTCCN = create_model()

def get_bytes_value(image):
    img_byte_arr = io.BytesIO()
    image.save(img_byte_arr, format='PNG')
    return img_byte_arr.getvalue()

def process_crop_face_image(image):
    img = np.array(image)
    result = Model_MTCCN.detect_faces(img)
    box = result[0].get('box')
    x, y, width, height = box[0], box[1], box[2], box[3]
    image_crop = image.crop((x, y, x+width, y+height))
    return image_crop

def crop_face_image(file):

    try:
        image_bytes = file.file.read()
        decode = io.BytesIO(image_bytes)
        image = Image.open(decode)
        image = process_crop_face_image(image)
    except Exception as e:
        print("crop_face_image error: {}".format(e))
        return "crop face image fail"
    return get_bytes_value(image)

def crop_face_image_2(file):

    try:
        image_bytes = file.file.read()
        decode = io.BytesIO(image_bytes)
        image = Image.open(decode)
        image = process_crop_face_image(image)
        return image
    except Exception as e:
        print("crop_face_image error: {}".format(e))
        return "crop face image fail"

def save_image_manual(file, folder_path, image_name):
    image_bytes = file.file.read()
    decode = io.BytesIO(image_bytes)
    image = Image.open(decode)
    try:
        os.chdir(Folder.local_path)
        os.chdir(folder_path)
        image.save(image_name, 'PNG')
    except Exception as e:
        print("save_image error: {}".format(e))
        return "save_image image fail"

def save_image_crop(image, video_name, image_name):
    try:
        os.chdir(Folder.local_path)
        parent_dir = Folder.data_dir + Folder.crop_directory
        os.chdir(parent_dir)
        os.chdir(video_name)
        image.save(image_name, 'PNG')
    except Exception as e:
        print("save_image error: {}".format(e))
        return "save_image image fail"


class Solution:
    def leastInterval(self, tasks: List[str], n: int) -> int:
        frequencyTable = Counter(tasks)
        que = deque()
        time = 0
        maxHeap = [[-frequencyTable[key], key] for key,value in frequencyTable.items()]

        heapq.heapify(maxHeap)

        while maxHeap or que:

            if maxHeap:
                count, letter = heapq.heappop(maxHeap)
                if count + 1 < 0:
                    que.append([count+1, letter, time+n])
            if que and que[0][2] == time:
                count, letter, releaseTime = que.popleft()
                heapq.heappush(maxHeap, [count, letter])
            time += 1
        return time

#         lookup = Counter(tasks)
#         que = deque()
#         maxHeap = [-cnt for cnt in lookup.values()]
#         heapq.heapify(maxHeap)
#         time = 0

#         while maxHeap or que:
#             time += 1
#             if maxHeap:
#                 task = heapq.heappop(maxHeap)
#                 task += 1
#                 if task:
#                     que.append((task, time+n))

#             if que and que[0][1] == time:
#                 taskToAddToHeap = que.popleft()
#                 heapq.heappush(maxHeap,taskToAddToHeap[0])
#         return time

#     '''
#     1. create hashmap for character frequency
#     2. convert that character frequency count to maxHeap
#         i. We want to always process the most frequent task
#     3. Pop the most frequent task and reduce its count
#         i. add it to the que with the time it can be released
#     4. increment Time by one becuase we are processing a task
#     5. If the task at the head of the que can be processed again. pop it and add it back to the heap
#     6. once all task are processed return the time
#     '''


from datetime import timedelta

from odoo import models, api, fields

class LibraryBookLoan(models.Model):
    _inherit = 'library.book.loan'
    expected_return_date = fields.Date('Due for', required=True)

class LibraryMember(models.Model):
    _inherit = 'library.member'
    loan_duration = fields.Integer('Loan duration',
                                   default=15,
                                   required=True)

class LibraryLoanWizard(models.TransientModel):
    _inherit = 'library.load.wizard'

    @api.multi
    def _prepare_loan(self, book):
        values = super(LibraryLoanWizard, self)._prepare_loan(book)
        loan_duration = self.member_id.loan_duration
        today_str = fields.Date.context_today(self)
        today = fields.Date.from_string(today_str)
        expected = (today +
                    timedelta(days=loan_duration))
        values.update(
            {'expected_return_date': fields.Date.to_string(expected)}
        )
        return values


import torch
import torch.nn as nn

class DVDnet_spatial(nn.Module):
	""" Definition of the spatial denoiser of DVDnet.
	Inputs of forward():
		x: array of input frames of dim [N, C, H, W], (C=3 RGB)
		noise_map: array with noise map of dim [N, C, H, W], C (noise map for each channel)
	"""

	def __init__(self):
		super(DVDnet_spatial, self).__init__()
		self.down_kernel_size = (2, 2)
		self.down_stride = 2
		self.kernel_size = 3
		self.padding = 1
		# RGB image
		self.num_input_channels = 6
		self.middle_features = 96
		self.num_conv_layers = 12
		self.down_input_channels = 12
		self.downsampled_channels = 15
		self.output_features = 12

		self.downscale = nn.Unfold(kernel_size=self.down_kernel_size, stride=self.down_stride)

		layers = []
		layers.append(nn.Conv2d(in_channels=self.downsampled_channels,\
								out_channels=self.middle_features,\
								kernel_size=self.kernel_size,\
								padding=self.padding,\
								bias=False))
		layers.append(nn.ReLU(inplace=True))
		for _ in range(self.num_conv_layers-2):
			layers.append(nn.Conv2d(in_channels=self.middle_features,\
									out_channels=self.middle_features,\
									kernel_size=self.kernel_size,\
									padding=self.padding,\
									bias=False))
			layers.append(nn.BatchNorm2d(self.middle_features))
			layers.append(nn.ReLU(inplace=True))
		layers.append(nn.Conv2d(in_channels=self.middle_features,\
								out_channels=self.output_features,\
								kernel_size=self.kernel_size,\
								padding=self.padding,\
								bias=False))

		self.conv_relu_bn = nn.Sequential(*layers)
		self.pixelshuffle = nn.PixelShuffle(2)
		# Init weights
		self.reset_params()

	@staticmethod
	def weight_init(m):
		if isinstance(m, nn.Conv2d):
			nn.init.kaiming_normal_(m.weight, nonlinearity='relu')

	def reset_params(self):
		for _, m in enumerate(self.modules()):
			self.weight_init(m)

	def forward(self, x, noise_map):

		N, _, H, W = x.size() # compute size of input

		# Downscale input using nn.Unfold
		x1 = self.downscale(x)
		x1 = x1.reshape(N, self.down_input_channels, H//2, W//2)

		# Concat downscaled input with downsampled noise map
		x1 = torch.cat((noise_map[:, :, ::2, ::2], x1), 1)

		# Conv + ReLU + BN
		x1 = self.conv_relu_bn(x1)

		# Upscale back to original resolution
		x1 = self.pixelshuffle(x1)

		# Residual learning
		x = x - x1
		return x

class DVDnet_temporal(nn.Module):
	""" Definition of the temporal denoiser of DVDnet.
	Inputs of constructor:
		num_input_frames: int. number of frames to denoise
	Inputs of forward():
		x: array of input frames of dim [num_input_frames, C, H, W], (C=3 RGB)
		noise_map: array with noise map of dim [1, C, H, W], C (noise map for each channel)
	"""
	def __init__(self, num_input_frames):
		super(DVDnet_temporal, self).__init__()
		self.num_input_frames = num_input_frames
		self.num_input_channels = int((num_input_frames+1)*3) # num_input_frames RGB frames + noisemap
		self.num_feature_maps = 96
		self.num_conv_layers = 4
		self.output_features = 12
		self.down_kernel_size = 5
		self.down_stride = 2
		self.down_padding = 2
		self.conv1x1_kernel_size = 1
		self.conv1x1_stride = 1
		self.conv1x1_padding = 0
		self.kernel_size = 3
		self.stride = 1
		self.padding = 1

		self.down_conv = nn.Sequential(nn.Conv2d(in_channels=self.num_input_channels,\
												out_channels=self.num_feature_maps,\
												kernel_size=self.down_kernel_size,\
												padding=self.down_padding,\
												stride=self.down_stride,\
												bias=False),\
										nn.BatchNorm2d(self.num_feature_maps),\
										nn.ReLU(inplace=True))
		self.conv1x1 = nn.Conv2d(in_channels=self.num_feature_maps,\
											out_channels=self.num_feature_maps,\
											kernel_size=self.conv1x1_kernel_size,\
											padding=self.conv1x1_padding,\
											stride=self.conv1x1_stride,\
											bias=False)
		layers = []
		for _ in range(self.num_conv_layers):
			layers.append(nn.Conv2d(in_channels=self.num_feature_maps,\
									out_channels=self.num_feature_maps,\
									kernel_size=self.kernel_size,\
									padding=self.padding,\
									bias=False))
			layers.append(nn.BatchNorm2d(self.num_feature_maps))
			layers.append(nn.ReLU(inplace=True))

		self.block_conv = nn.Sequential(*layers)
		self.out_conv = nn.Sequential(nn.Conv2d(in_channels=self.num_feature_maps,\
											out_channels=self.num_feature_maps,\
											kernel_size=self.kernel_size,\
											padding=self.padding,\
											stride=self.stride,\
											bias=False),\
										nn.BatchNorm2d(self.num_feature_maps),\
										nn.ReLU(inplace=True),\
										nn.Conv2d(in_channels=self.num_feature_maps,\
											out_channels=self.output_features,\
											kernel_size=self.kernel_size,\
											padding=self.padding,\
											stride=self.stride,\
											bias=False))
		self.pixelshuffle = nn.PixelShuffle(2)
		# Init weights
		self.reset_params()

	@staticmethod
	def weight_init(m):
		if isinstance(m, nn.Conv2d):
			nn.init.kaiming_normal_(m.weight, nonlinearity='relu')

	def reset_params(self):
		for _, m in enumerate(self.modules()):
			self.weight_init(m)

	def forward(self, x, noise_map):
		x1 = torch.cat((noise_map, x), 1)
		x1 = self.down_conv(x1)
		x2 = self.conv1x1(x1)
		x1 = self.block_conv(x1)
		x1 = self.out_conv(x1+x2)
		x1 = self.pixelshuffle(x1)
		return x1


import sys
import os

current_dir = os.path.dirname(__file__)
parent_dir = os.path.abspath(os.path.join(current_dir, ".."))
sys.path.append(parent_dir)

from erbasts.erbast import Erbast
from carvizes.carviz import Carviz
from keygenerator import generateKey
import random
from parameters import parameters

class Group:
    def __init__(self, cell):
        self.cell = cell
        self.animals = {}
        self.prevCells = []
        self.currInCells = []

    def getAnimals(self):
        return self.animals

    def getNumAnimal(self):
        return len(self.animals)

    def getAvSocialAttitude(self):
        socialAtt = 0
        for key in self.animals:
                socialAtt += self.animals[key].getSocialAttitude()
        avSocialAtt = socialAtt/self.getNumAnimal()
        return avSocialAtt

    def getTotalEnergy(self):
        totEnergy = 0
        for key in self.animals:
            totEnergy += self.animals[key].getEnergy()
        return totEnergy

    def addAnimal(self, key, animal):
        self.animals[key] = animal

    def removeAnimal(self, key):
        self.animals.pop(key)

    def kill(self):
        self.animals = {}

    def sortAnimals(self):
        return sorted(self.animals, key = lambda item: self.animals[item].getEnergy())

    def spawns(self):
        if self.getNumAnimal() == 0:
            return 0
        born = []
        dead = []

        for key, animal in self.animals.items():
            isAlive, energy, lifetime = animal.grows()
            if not isAlive:
                dead.append(key)
                max = parameters.getMaxHerd()-1 if isinstance(animal, Erbast) else parameters.getMaxPride()-1
                if self.getNumAnimal() < max and energy > 0:
                    energy1 = random.randint(0,energy)
                    energy2 = energy - energy1
                    lifetime1 = random.randint(0, min(parameters.getMaxLife(), 2*lifetime))
                    lifetime2 = 2*lifetime-lifetime1
                    socialAtt1 = random.uniform(0, min(1, 2*animal.getSocialAttitude()))
                    socialAtt2 = 2*animal.getSocialAttitude()-socialAtt1
                    key1 = generateKey()
                    key2 = generateKey()
                    born.append({'key': key1, 'energy': energy1, 'lifetime': lifetime1, 'socialAttitude': socialAtt1})
                    born.append({'key': key2, 'energy': energy2, 'lifetime': lifetime2, 'socialAttitude': socialAtt2})
        for key in dead:
            self.removeAnimal(key)
        for elm in born:
            if isinstance(animal, Erbast):
                bornAnimal = Erbast(self.cell, elm['energy'], elm['lifetime'], elm['socialAttitude'])
            if isinstance(animal, Carviz):
                bornAnimal = Carviz(self.cell, elm['energy'], elm['lifetime'], elm['socialAttitude'])
            self.addAnimal(elm['key'], bornAnimal)
        return self.getNumAnimal()

    def move(self, targetGroup):
        movingAnimal = []
        groupMoves = random.random() > parameters.getMoveProb()
        if groupMoves:
            targetGroup.currInCells.append(self.cell)
        for key, animal in self.animals.items():
            animalMoves, animalIsStill = animal.willMove()
            max = parameters.getMaxHerd() if isinstance(animal, Erbast) else parameters.getMaxPride()
            if ((groupMoves and animalMoves) or (not groupMoves and not animalIsStill)) and targetGroup.getNumAnimal() < max:
                movingAnimal.append(key)
                animal.moves()
                animal.cell = targetGroup.cell
                targetGroup.addAnimal(key, animal)
        for key in movingAnimal:
            self.removeAnimal(key)
        return


from modules.base_module import RanaModule
from core import geo
from threading import Thread
import math
import time

REROUTE_CHECK_INTERVAL = 5000 # in ms
#in m/s, about 46 km/h - if this speed is reached, the rerouting threshold is multiplied
# by REROUTING_THRESHOLD_MULTIPLIER
INCREASE_REROUTING_THRESHOLD_SPEED = 20
REROUTING_DEFAULT_THRESHOLD = 30
# not enabled at the moment - needs more field testing
REROUTING_THRESHOLD_MULTIPLIER = 1.0
# how many times needs the threshold be crossed to
# trigger rerouting
REROUTING_TRIGGER_COUNT = 3

MAX_CONSECUTIVE_AUTOMATIC_REROUTES = 3
AUTOMATIC_REROUTE_COUNTER_EXPIRATION_TIME = 600 # in seconds

# only import GKT libs if GTK GUI is used
from core import gs

if gs.GUIString == "GTK":
    import pango
    import pangocairo

def getModule(*args, **kwargs):
    return TurnByTurn(*args, **kwargs)

class TurnByTurn(RanaModule):
    """A turn by turn navigation module."""

    def __init__(self, *args, **kwargs):
        RanaModule.__init__(self, *args, **kwargs)
        # initial colors
        self.navigationBoxBackground = (0, 0, 1, 0.3) # very transparent blue
        self.navigationBoxText = (1, 1, 1, 1) # non-transparent white
        self.TBTWorker = None
        self.TBTWorkerEnabled = False
        self.goToInitialState()
        self.automaticRerouteCounter = 0 # counts consecutive automatic reroutes
        self.lastAutomaticRerouteTimestamp = time.time()
        # reroute even though the route was not yet reached (for special cases)
        self.overrideRouteReached = False

    def goToInitialState(self):
        """restore initial state"""
        self.route = None
        self.currentStepIndex = 0
        self.currentStepIndicator = None
        self.espeakFirstAndHalfTrigger = False
        self.espeakFirstTrigger = False
        self.espeakSecondTrigger = False
        self.currentDistance = None
        self.currentStep = None
        self.navigationBoxHidden = False
        self.mRouteLength = 0
        self.locationWatchID = None
        self.onRoute = False
        #rerouting is enabled once the route is reached for the first time
        self.routeReached = False
        self.reroutingThresholdMultiplier = 1.0
        self.reroutingThresholdCrossedCounter = 0

    def firstTime(self):
        icons = self.m.get('icons', None)
        if icons:
            icons.subscribeColorInfo(self, self.colorsChangedCallback)

    def colorsChangedCallback(self, colors):
        self.navigationBoxBackground = colors['navigation_box_background'].getCairoColor()
        self.navigationBoxText = colors['navigation_box_text'].getCairoColor()

    def handleMessage(self, message, messageType, args):
        if message == 'start':
            if messageType == 'ms':
                fromWhere = args
                self.startTBT(fromWhere)
        elif message == 'stop':
            self.stopTBT()
        elif message == 'reroute': # manual rerouting
            # reset automatic reroute counter
            self.automaticRerouteCounter = 0
            self._reroute()
        elif message == "toggleBoxHiding":
            self.log.info("toggling navigation box visibility")
            self.navigationBoxHidden = not self.navigationBoxHidden
        elif message == "switchToPreviousTurn":
            self.switchToPreviousStep()
        elif message == "switchToNextTurn":
            self.switchToNextStep()
        elif message == "showMessageInsideNotification":
            currentStep = self.getCurrentStep()
            if currentStep:
                message = "turn description:\n%s" % currentStep.description
                if self.dmod.hasNotificationSupport():
                    self.dmod.notify(message, 7000)
                    #TODO: add support for modRana notifications once they support line wrapping

    def _rerouteAuto(self):
        """this function is called when automatic rerouting is triggered"""

        # check time from last automatic reroute
        dt = time.time() - self.lastAutomaticRerouteTimestamp
        if dt >= AUTOMATIC_REROUTE_COUNTER_EXPIRATION_TIME:
            # reset the automatic reroute counter
            self.automaticRerouteCounter = 0
            self.log.debug('automatic reroute counter expired, clearing')

        # on some routes, when we are moving away from the start of the route, it
        # is needed to reroute a couple of times before the correct way is found
        # on the other hand there should be a limit on the number of times
        # modRana reroutes in a row
        #
        # SOLUTION:
        # 1. enable automatic rerouting even though the route was not yet reached
        # (as we are moving away from it)
        # 2. do this only a limited number of times (up to 3 times in a row)
        # 3. the counter is reset by manual rerouting, by reaching the route or after 10 minutes

        if self.automaticRerouteCounter < MAX_CONSECUTIVE_AUTOMATIC_REROUTES:
            self.log.debug('faking that route was reached to enable new rerouting')
            self.overrideRouteReached = True
        else:
            self.log.info('tbt: too many consecutive reroutes (%d),', self.automaticRerouteCounter)
            self.log.info('reach the route to enable automatic rerouting')
            self.log.info('or reroute manually')

        # increment the automatic reroute counter & update the timestamp
        self.automaticRerouteCounter += 1
        self.lastAutomaticRerouteTimestamp = time.time()

        # trigger rerouting
        self._reroute()

    def _reroute(self):
        # 1. say rerouting is in progress
        voiceMessage = "rerouting"
        voice = self.m.get('voice', None)
        if voice:
            voice.say(voiceMessage, "en") # make sure rerouting said with english voice
        time.sleep(2) #TODO: improve this
        # 2. get a new route from current position to destination
        self.sendMessage("ms:route:reroute:fromPosToDest")
        # 3. restart routing for to this new route from the closest point
        self.sendMessage("ms:turnByTurn:start:closest")

    def drawMapOverlay(self, cr):
        if self.route:
            # get current step
            currentStep = self.getCurrentStep()
            proj = self.m.get('projection', None)
            # draw the current step indicator circle
            if currentStep and proj:
                (lat, lon) = currentStep.getLL()
                (pointX, pointY) = proj.ll2xy(lat, lon)
                cr.set_source_rgb(1, 0, 0)
                cr.set_line_width(4)
                cr.arc(pointX, pointY, 12, 0, 2.0 * math.pi)
                cr.stroke()
                cr.fill()

    def drawScreenOverlay(self, cr):
        if self.route: # is there something relevant to draw ?

            # get current step
            currentStep = self.getCurrentStep()

            # draw the routing message box

            # we need to have the viewport available
            vport = self.get('viewport', None)
            menus = self.m.get('menu', None)
            if vport and menus:
                (sx, sy, w, h) = vport
                (bx, by, bw, bh) = (w * 0.15, h * 0.20, w * 0.7, h * 0.4)
                buttonStripOffset = 0.25 * bh

                # construct parametric background for the cairo drawn buttons
                background = "generic:;0;;1;5;0"

                if self.navigationBoxHidden:
                    # * show button
                    showButtonWidth = bw * 0.2
                    # the show button uses custom parameters
                    parametricIconName = "center:show;0.1>%s" % background
                    menus.drawButton(cr, bx + (bw - showButtonWidth), by, showButtonWidth, buttonStripOffset, "",
                                     parametricIconName, "turnByTurn:toggleBoxHiding")

                else:
                    # draw the info-box background
                    cr.set_source_rgba(*self.navigationBoxBackground)
                    cr.rectangle(bx, by + buttonStripOffset, bw, bh - buttonStripOffset)
                    cr.fill()

                    # create a layout for our drawing area
                    pg = pangocairo.CairoContext(cr)
                    layout = pg.create_layout()

                    # get the current turn message
                    message = currentStep.description

                    # display current distance to the next point & other unit conversions
                    units = self.m.get('units', None)
                    if units and self.currentDistance:
                        distString = units.m2CurrentUnitString(self.currentDistance, 1, True)
                        if currentStep.distanceFromStart:
                            currentDistString = units.m2CurrentUnitString(currentStep.distanceFromStart, 1, True)
                        else:
                            currentDistString = "?"
                        routeLengthString = units.m2CurrentUnitString(self.mRouteLength, 1, True)
                    else:
                        distString = ""
                        currentDistString = ""
                        routeLengthString = ""

                    # TODO: find why there needs to be a newline on the end
                    message = "%s : %s\n" % (distString, message)

                    border = min(bw / 50.0, bh / 50.0)
                    # compute how much space is actually available for the text
                    usableWidth = bw - 2 * border
                    usableHeight = bh - 6 * border - buttonStripOffset
                    layout.set_width(int(usableWidth * pango.SCALE))
                    layout.set_wrap(pango.WRAP_WORD)
                    layout.set_markup(message)
                    layout.set_font_description(pango.FontDescription("Sans Serif 24")) #TODO: custom font size ?
                    (lw, lh) = layout.get_size()
                    if lw == 0 or lh == 0:
                        # no need to draw a zero area layout
                        return

                    # get coordinates for the area available for text
                    ulX, ulY = (bx + border, by + border + buttonStripOffset)
                    cr.move_to(ulX, ulY)
                    cr.save()
                    if lh > usableHeight: # is the rendered text larger than the usable area ?
                        clipHeight = 0
                        # find last completely visible line
                        cut = False
                        for index in range(0, layout.get_line_count() - 1):
                            lineHeight = layout.get_line(index).get_pixel_extents()[1][3]
                            if clipHeight + lineHeight <= usableHeight:
                                clipHeight = clipHeight + lineHeight
                            else:
                                cut = True # signalize we cut off some lines
                                break

                        textEndY = by + border + clipHeight + buttonStripOffset

                        if cut:
                            # notify the user that a part of the text was cut,
                            # by drawing a red line and a scissors icon

                            # draw the red line
                            cr.set_source_rgb(1, 0, 0)
                            cr.set_line_width(bh * 0.01)
                            cr.move_to(bx, textEndY)
                            cr.line_to(bx + bw, textEndY)
                            cr.stroke()
                            # draw the scissors icon
                            cutSide = bw / 10
                            menus.drawButton(cr, bx + bw, textEndY - cutSide / 2.0, cutSide, cutSide, "",
                                             "center:scissors_right;0>%s" % background,
                                             "turnByTurn:showMessageInsideNotification")
                            #TODO: show the whole message in a notifications after clicking the scissors
                            # (this needs line wrapping support in modRana notifications)

                        # clip out the overflowing part of the text
                        cr.rectangle(ulX, ulY, usableWidth, clipHeight)
                        cr.translate(ulX, ulY)
                        cr.clip()

                    cr.set_source_rgba(*self.navigationBoxText)
                    pg.show_layout(layout)
                    cr.restore()

                    # use the bottom of the infobox to display info
                    (bottomX, bottomY) = (bx, by + bh - 6 * border)
                    if self.routeReached and self._automaticReroutingEnabled():
                        arString = "automatic rerouting enabled"
                    else:
                        arString = "tap this box to reroute"
                    note = "%s/%s, %d/%d    %s" % (
                    currentDistString, routeLengthString, self.currentStepIndex + 1, self.getMaxStepIndex() + 1,
                    arString)
                    menus.drawText(cr, "%s" % note, bottomX, bottomY, bw, 6 * border, 0,
                                   rgbaColor=self.navigationBoxText)
                    # make clickable
                    clickHandler = self.m.get('clickHandler', None)
                    if clickHandler:
                        action = "turnByTurn:reroute"
                        clickHandler.registerXYWH(bx, by + buttonStripOffset, bw, bh - buttonStripOffset, action)

                    # draw the button strip
                    hideButtonWidth = bw * 0.2
                    switchButtonWidth = bw * 0.4

                    # * previous turn button
                    menus.drawButton(cr, bx, by, switchButtonWidth, buttonStripOffset, "",
                                     "center:less;0.1>%s" % background, "turnByTurn:switchToPreviousTurn")
                    # * next turn button
                    menus.drawButton(cr, bx + switchButtonWidth, by, switchButtonWidth, buttonStripOffset, "",
                                     "center:more;0.1>%s" % background, "turnByTurn:switchToNextTurn")
                    # * hide button
                    menus.drawButton(cr, bx + 2 * switchButtonWidth, by, hideButtonWidth, buttonStripOffset, "",
                                     "center:hide;0.1>%s" % background, "turnByTurn:toggleBoxHiding")

    def _automaticReroutingEnabled(self):
        return self.get('reroutingThreshold', REROUTING_DEFAULT_THRESHOLD)

    def sayTurn(self, message, distanceInMeters, forceLanguageCode=False):
        """say a text-to-speech message about a turn
           this basically wraps the simple say method from voice and adds some more information,
           like current distance to the turn
           """
        voice = self.m.get('voice', None)
        units = self.m.get('units', None)

        if voice and units:
            (distString, short, long) = units.humanRound(distanceInMeters)

            if distString == "0":
                distString = ""
            else:
                distString = '
in <emphasis level="strong">' + distString + ' ' + long + '</emphasis>

'
                # TODO: language specific distance strings
            text = distString + message

            #      """ the message can contain unicode, this might cause an exception when printing it
            #      in some systems (SHR-u on Neo, for example)"""
            #      try:
            #        print("saying: %s" % text)
            #        pass
            #      except UnicodeEncodeError:
            #        print("voice: printing the current message to stdout failed do to unicode conversion error")

            if forceLanguageCode:
                espeakLanguageCode = forceLanguageCode
            else:
                # the espeak language code is the first part of this whitespace delimited string
                espeakLanguageCode = self.get('directionsLanguage', 'en en').split(" ")[0]
            return voice.say(text, espeakLanguageCode)

    def getMaxStepIndex(self):
        return self.route.message_point_count - 1

    def getStartingStep(self, which='first'):
        if self.route:
            if which == 'first':
                return self.getStep(0)
            if which == 'closest':
                return self.getClosestStep()

    def getClosestStep(self):
        """get the geographically closest step"""
        proj = self.m.get('projection', None) # we also need the projection module
        pos = self.get('pos', None) # and current position
        if pos and proj:
            (lat1, lon1) = pos
            tempSteps = self.route.message_points
            for step in tempSteps:
                (lat2, lon2) = step.getLL()
                step.currentDistance = geo.distance(lat1, lon1, lat2, lon2) * 1000 # km to m
            closestStep = sorted(tempSteps, key=lambda x: x.currentDistance)[0]

            return closestStep

    def getStep(self, index):
        """return steps for valid index, None otherwise"""
        maxIndex = self.getMaxStepIndex()
        if index > maxIndex or index < -(maxIndex + 1):
            self.log.error("wrong turn index: %d, max index is: %d", index, maxIndex)
            return None
        else:
            return self.route.get_message_point_by_index(index)

    def setStepAsCurrent(self, step):
        """set a given step as current step"""
        mpId = self.route.get_message_point_index(step)
        self._setCurrentStepIndex(mpId)

    def getCurrentStep(self):
        """return current step"""
        return self.route.get_message_point_by_index(self.currentStepIndex)

    def getStepID(self, step):
        return self.route.get_message_point_index(step)

    def getCurrentStepVisitStatus(self):
        """report visit status for  current step"""
        return self.getCurrentStep().visited

    def markCurrentStepAsVisited(self):
        """mark current step as visited"""
        self.getCurrentStep().visited = True

    def switchToPreviousStep(self):
        """switch to previous step and clean up"""
        nextIndex = self.currentStepIndex - 1
        if nextIndex >= 0:
            self._setCurrentStepIndex(nextIndex)
            self.espeakFirstTrigger = False
            self.espeakSecondTrigger = False
            self.log.info("switching to previous step")
        else:
            self.log.info("previous step reached")

    def switchToNextStep(self):
        """switch to next step and clean up"""
        maxIndex = self.getMaxStepIndex()
        nextIndex = self.currentStepIndex + 1
        if nextIndex <= maxIndex:
            self._setCurrentStepIndex(nextIndex)
            self.espeakFirstAndHalfTrigger = False
            self.espeakFirstTrigger = False
            self.espeakSecondTrigger = False
            self.log.info("switching to next step")
        else:
            self.log.info("last step reached")
            self._lastStepReached()

    def _lastStepReached(self):
        """handle all tasks that are needed once the last step is reached"""
        #disable automatic rerouting
        self._stopTBTWorker()
        # automatic rerouting needs to be disabled to prevent rerouting
        # once the destination was reached

    def _setCurrentStepIndex(self, index):
        self.currentStepIndex = index
        self._doNavigationUpdate()

    def enabled(self):
        """return True if enabled, false otherwise"""
        if self.route:
            return True
        else:
            return False

    def startTBT(self, fromWhere='first'):
        """start Turn-by-turn navigation"""

        # clean up any possible previous navigation data
        self.goToInitialState()

        # NOTE: turn and step are used interchangeably in the documentation
        m = self.m.get('route', None)
        if m:
            route = m.get_current_directions()
            if route: # is the route nonempty ?
                self.route = route
                # get route in radians for automatic rerouting
                self.radiansRoute = route.get_points_lle_radians(drop_elevation=True)
                # start rerouting watch
                self._startTBTWorker()

                # show the warning message
                self.sendMessage('ml:notification:m:use at own risk, watch for cliffs, etc.;3')
                # for some reason the combined distance does not account for the last step
                self.mRouteLength = route.length

                # some statistics
                metersPerSecSpeed = self.get('metersPerSecSpeed', None)
                dt = m.route_lookup_duration
                self.log.info("route lookup took: %f s" % dt)
                if dt and metersPerSecSpeed:
                    dm = dt * metersPerSecSpeed
                    self.log.info("distance traveled during lookup: %f m" % dm)
                    # the duration of the road lookup and other variables are currently not used
                # in the heuristics but might be added later to make the heuristics more robust

                # now we decide if we use the closest turn, or the next one,
                # as we might be already past it and on our way to the next turn
                cs = self.getClosestStep() # get geographically closest step
                pos = self.get('pos', None) # get current position
                pReachedDist = int(self.get('pointReachedDistance', 30)) # get the trigger distance
                nextTurnId = self.getStepID(cs) + 1
                nextStep = self.getStep(nextTurnId)
                # check if we have all the data needed for our heuristics
                self.log.info("trying to guess correct step to start navigation")
                if nextStep and pos and pReachedDist:
                    (lat, lon) = pos
                    (csLat, csLon) = cs.getLL()
                    (nsLat, nsLon) = nextStep.getLL()
                    pos2nextStep = geo.distance(lat, lon, nsLat, nsLon) * 1000
                    pos2currentStep = geo.distance(lat, lon, csLat, csLon) * 1000
                    currentStep2nextStep = geo.distance(csLat, csLon, nsLat, nsLon) * 1000
                    #          self.log.debug("pos",(lat,lon))
                    #          self.log.debug("cs",(csLat,csLon))
                    #          self.log.debug("ns",(nsLat,nsLon))
                    self.log.debug("position to next turn: %f m" % pos2nextStep)
                    self.log.debug("position to current turn: %f m" % pos2currentStep)
                    self.log.debug("current turn to next turn: %f m" % currentStep2nextStep)
                    self.log.debug("turn reached trigger distance: %f m" % pReachedDist)

                    if pos2currentStep > pReachedDist:
                        #this means we are out of the "capture circle" of the closest step

                        # what is more distant, the closest or the next step ?
                        if pos2nextStep < currentStep2nextStep:
                            # we are mostly probably already past the closest step,
                            # so we switch to the next step at once
                            self.log.debug("already past closest turn, switching to next turn")
                            self.setStepAsCurrent(nextStep)
                            # we play the message for the next step,
                            # with current distance to this step,
                            # to assure there is some voice output immediately after
                            # getting a new route or rerouting"""
                            plaintextMessage = nextStep.ssmlMessage
                            self.sayTurn(plaintextMessage, pos2nextStep)
                        else:
                            # we have probably not yet reached the closest step,
                            # so we start navigation from it
                            self.log.debug("closest turn not yet reached")
                            self.setStepAsCurrent(cs)

                    else:
                        # we are inside the  "capture circle" of the closest step,
                        # this means the navigation will trigger the voice message by itself
                        # and correctly switch to next step
                        # -> no need to switch to next step from here
                        self.log.debug("inside reach distance of closest turn")
                        self.setStepAsCurrent(cs)

                else:
                    # we dont have some of the data, that is needed to decide
                    # if we start the navigation from the closest step of from the step that is after it
                    # -> we just start from the closest step
                    self.log.debug("not enough data to decide, using closest turn")
                    self.setStepAsCurrent(cs)
        self._doNavigationUpdate() # run a first time navigation update
        self.locationWatchID = self.watch('locationUpdated', self.locationUpdateCB)
        self.log.info("started and ready")

    def stopTBT(self):
        """stop Turn-by-turn navigation"""
        # remove location watch
        if self.locationWatchID:
            self.removeWatch(self.locationWatchID)
            # cleanup
        self.goToInitialState()
        self._stopTBTWorker()
        self.log.info("stopped")

    def locationUpdateCB(self, key, newValue, oldValue):
        """position changed, do a tbt navigation update"""
        if key == "locationUpdated": # just to be sure
            self._doNavigationUpdate()
        else:
            self.log.error("invalid key: %r", key)

    def _doNavigationUpdate(self):
        """do a navigation update"""
        # make sure there really are some steps
        if not self.route:
            self.log.error("no route")
            return
        pos = self.get('pos', None)
        if pos is None:
            self.log.error("skipping update, invalid position")
            return

        # get/compute/update necessary the values
        (lat1, lon1) = pos
        currentStep = self.getCurrentStep()
        lat2, lon2 = currentStep.getLL()
        currentDistance = geo.distance(lat1, lon1, lat2, lon2) * 1000 # km to m
        self.currentDistance = currentDistance # update current distance

        # use some sane minimum distance
        distance = int(self.get('minAnnounceDistance', 100))

        # GHK: make distance speed-sensitive
        #
        # I came up with this formula after a lot of experimentation with
        # gnuplot.  The idea is to give the user some simple parameters to
        # adjust yet let him have a lot of control.  There are five
        # parameters in the equation:
        #
        # lowSpeed	Speed below which the pre-announcement time is constant.
        # lowTime	Announcement time at and below lowSpeed.
        # highSpeed	Speed above which the announcement time is constant.
        # highTime	Announcement time at and above highSpeed.
        # power	Exponential power used in the formula; good values are 0.5-5
        #
        # The speeds are in m/s.  Obviously highXXX must be greater than lowXXX.
        # If power is 1.0, announcement times increase linearly above lowSpeed.
        # If power < 1.0, times rise rapidly just above lowSpeed and more
        # gradually approaching highSpeed.  If power > 1.0, times rise
        # gradually at first and rapidly near highSpeed.  I like power > 1.0.
        #
        # The reasoning is that at high speeds you are probably on a
        # motorway/freeway and will need extra time to get into the proper
        # lane to take your exit.  That reasoning is pretty harmless on a
        # high-speed two-lane road, but it breaks down if you are stuck in
        # heavy traffic on a four-lane freeway (like in Los Angeles
        # where I live) because you might need quite a while to work your
        # way across the traffic even though you're creeping along.  But I
        # don't know a good way to detect whether you're on a multi-lane road,
        # I chose speed as an acceptable proxy.
        #
        # Regardless of speed, we always warn a certain distance ahead (see
        # "distance" above).  That distance comes from the value in the current
        # step of the directions.
        #
        # BTW, if you want to use gnuplot to play with the curves, try:
        # max(a,b) = a > b ? a : b
        # min(a,b) = a  mps speed > point reached distance
            # also enlarge the rerouting threshold as it looks like it needs to be larger
            # when moving at high speed to prevent unnecessary rerouting
            if metersPerSecSpeed > pointReachedDistance * 0.75:
                pointReachedDistance = metersPerSecSpeed * 2
            #        self.log.debug("tbt: enlarging point reached distance to: %1.2f m due to large speed (%1.2f m/s)". (pointReachedDistance, metersPerSecSpeed)

            if metersPerSecSpeed > INCREASE_REROUTING_THRESHOLD_SPEED:
                self.reroutingThresholdMultiplier = REROUTING_THRESHOLD_MULTIPLIER
            else:
                self.reroutingThresholdMultiplier = 1.0

            # speed & time based triggering
            lowSpeed = float(self.get('minAnnounceSpeed', 13.89))
            highSpeed = float(self.get('maxAnnounceSpeed', 27.78))
            highSpeed = max(highSpeed, lowSpeed + 0.1)
            lowTime = int(self.get('minAnnounceTime', 10))
            highTime = int(self.get('maxAnnounceTime', 60))
            highTime = max(highTime, lowTime)
            power = float(self.get('announcePower', 2.0))
            warnTime = (max(lowSpeed, metersPerSecSpeed) - lowSpeed) ** power \
                       * (highTime - lowTime) / (highSpeed - lowSpeed) ** power \
                       + lowTime
            warnTime = min(highTime, warnTime)
            distance = max(distance, warnTime * metersPerSecSpeed)

            if self.get('debugTbT', False):
                self.log.debug("#####")
                self.log.debug("min/max announce time: %d/%d s", lowTime, highTime)
                self.log.debug("trigger distance: %1.2f m (%1.2f s warning)", distance, distance / float(metersPerSecSpeed))
                self.log.debug("current distance: %1.2f m", currentDistance)
                self.log.debug("current speed: %1.2f m/s (%1.2f km/h)", metersPerSecSpeed, metersPerSecSpeed * 3.6)
                self.log.debug("point reached distance: %f m", pointReachedDistance)
                self.log.debug("1. triggered=%r, 1.5. triggered=%r, 2. triggered=%r",
                               self.espeakFirstTrigger, self.espeakFirstAndHalfTrigger, self.espeakSecondTrigger)
                if warnTime > 30:
                    self.log.debug("optional (20 s) trigger distance: %1.2f", 20.0 * metersPerSecSpeed)

            if currentDistance <= pointReachedDistance:
                # this means we reached the point"""
                if self.espeakSecondTrigger == False:
                    self.log.debug("triggering espeak nr. 2")
                    # say the message without distance
                    plaintextMessage = currentStep.ssmlMessage
                    # consider turn said even if it was skipped (ignore errors)
                    self.sayTurn(plaintextMessage, 0)
                    self.markCurrentStepAsVisited() # mark this point as visited
                    self.espeakFirstTrigger = True # everything has been said, again :D
                    self.espeakSecondTrigger = True # everything has been said, again :D
                self.switchToNextStep() # switch to next step
            else:
                if currentDistance <= distance:
                    # this means we reached an optimal distance for saying the message"""
                    if self.espeakFirstTrigger == False:
                        self.log.debug("triggering espeak nr. 1")
                        plaintextMessage = currentStep.ssmlMessage
                        if self.sayTurn(plaintextMessage, currentDistance):
                            self.espeakFirstTrigger = True # first message done
                if self.espeakFirstAndHalfTrigger == False and warnTime > 30:
                    if currentDistance <= (20.0 * metersPerSecSpeed):
                        # in case that the warning time gets too big, add an intermediate warning at 20 seconds
                        # NOTE: this means it is said after the first trigger
                        plaintextMessage = currentStep.ssmlMessage
                        if self.sayTurn(plaintextMessage, currentDistance):
                            self.espeakFirstAndHalfTrigger = True # intermediate message done

            ## automatic rerouting ##

            # is automatic rerouting enabled from options
            # enabled == threshold that is not not None
            if self._automaticReroutingEnabled():
                # rerouting is enabled only once the route is reached for the first time
                if self.onRoute and not self.routeReached:
                    self.routeReached = True
                    self.automaticRerouteCounter = 0
                    self.log.info('route reached, rerouting enabled')

                # did the TBT worker detect that the rerouting threshold was reached ?
                if self._reroutingConditionsMet():
                    # test if enough consecutive divergence point were recorded
                    if self.reroutingThresholdCrossedCounter >= REROUTING_TRIGGER_COUNT:
                        # reset the routeReached override
                        self.overrideRouteReached = False
                        # trigger rerouting
                        self._rerouteAuto()
                else:
                    # reset the counter
                    self.reroutingThresholdCrossedCounter = 0

    def _reroutingConditionsMet(self):
        return (self.routeReached or self.overrideRouteReached) and not self.onRoute

    def _followingRoute(self):
        """are we still following the route or is rerouting needed"""
        start1 = time.clock()
        pos = self.get('pos', None)
        proj = self.m.get('projection', None)
        if pos and proj:
            pLat, pLon = pos
            # we use Radians to get rid of radian conversion overhead for
            # the geographic distance computation method
            radiansLL = self.radiansRoute
            pLat = geo.radians(pLat)
            pLon = geo.radians(pLon)
            if len(radiansLL) == 0:
                self.log.error("Divergence: can't follow a zero point route")
                return False
            elif len(radiansLL) == 1: # 1 point route
                aLat, aLon = radiansLL[0]
                minDistance = geo.distanceApproxRadians(pLat, pLon, aLat, aLon)
            else: # 2+ points route
                aLat, aLon = radiansLL[0]
                bLat, bLon = radiansLL[1]
                minDistance = geo.distancePointToLineRadians(pLat, pLon, aLat, aLon, bLat, bLon)
                aLat, aLon = bLat, bLon
                for point in radiansLL[1:]:
                    bLat, bLon = point
                    dist = geo.distancePointToLineRadians(pLat, pLon, aLat, aLon, bLat, bLon)
                    if dist < minDistance:
                        minDistance = dist
                    aLat, aLon = bLat, bLon
                # the multiplier tries to compensate for high speed movement
            threshold = float(
                self.get('reroutingThreshold', REROUTING_DEFAULT_THRESHOLD)) * self.reroutingThresholdMultiplier
            self.log.debug("Divergence from route: %1.2f/%1.2f m computed in %1.0f ms",
            minDistance * 1000, float(threshold), (1000 * (time.clock() - start1)))
            return minDistance * 1000 < threshold

    def _startTBTWorker(self):
        self.log.info("starting worker thread")
        startThread = True
        if not self.TBTWorker: # reuse previous thread or start new one
            self.TBTWorkerEnabled = True
            t = Thread(target=self._TBTWorker)
            t.daemon = True
            t.start()
            self.TBTWorker = t
        else:
            self.log.info("reusing worker thread")

    def _stopTBTWorker(self):
        self.TBTWorkerEnabled = False
        self.TBTWorker = None

    def _TBTWorker(self):
        """this function is run in its own thread and check if
        we are following the current route"""
        self.log.info("TBTWorker: started")
        while self.route and self.TBTWorkerEnabled:
            # first make sure automatic rerouting is enabled
            # eq. reroutingThreshold != None
            if self._automaticReroutingEnabled():
            # check if we are still following the route
            #        self.log.debug('TBTWorker: checking divergence from route')
                self.onRoute = self._followingRoute()
                if self._reroutingConditionsMet():
                    self.log.info('TBTWorker: divergence detected')
                    # switch to quick updates
                    for i in range(0, REROUTING_TRIGGER_COUNT + 1):
                        time.sleep(1)
                        onRoute = self._followingRoute()
                        if onRoute: # divergence stopped
                            self.onRoute = onRoute
                            self.log.info('TBTWorker: false alarm')
                            break
                        else: # still diverging from current route
                            self.onRoute = onRoute
                            # increase divergence counter
                            self.reroutingThresholdCrossedCounter += 1
                            self.log.debug('TBTWorker: increasing divergence counter (%d)',
                                           self.reroutingThresholdCrossedCounter)
            time.sleep(REROUTE_CHECK_INTERVAL / 1000.0)
        self.log.info("TBTWorker: shutting down")

    def shutdown(self):
        # cleanup
        self.stopTBT()


def elefantes(n):
    if n <= 1:
        return ''
    elif n == 2:
        return elefantes(n-1) +\
               'Um elefante incomoda muita gente\n' +\
               '{} elefantes {}muito mais\n'.format(n, incomodam(n))
    else:
        return elefantes(n - 1) +\
               '{} elefantes incomodam muita gente\n'.format(n-1) +\
               '{} elefantes {}muito mais\n'.format(n, incomodam(n))

def incomodam(n):
    return n * 'incomodam '


import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
import shutil
import zipfile
import subprocess

TOKEN = "asdasd"
UPLOAD_FOLDER = 'upload_dir'
ALLOWED_EXTENSIONS = {'zip', 'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route("/kill_server")
def killserver():
    token = request.headers.get('token')
    if token != TOKEN:
        return "failed token check"
    command = "cd server_build;sudo docker-compose down"
    result = subprocess.run(command, shell=True)
    return str(result.returncode)

@app.route("/start_server")
def startserver():
    token = request.headers.get('token')
    if token != TOKEN:
        return "failed token check"
    command = "cd server_build;sudo docker-compose build;sudo docker-compose up &"
    result = subprocess.run(command, shell=True)
    return str(result.returncode)

def DeleteAllFilesInDirection(dirpath):
    directory = dirpath

    # List the contents of the directory
    for item in os.listdir(directory):
        # Construct the full path to the item
        item_path = os.path.join(directory, item)

        # Check if the item is a file or a directory
        if os.path.isfile(item_path):
            # Delete the file
            os.remove(item_path)
        elif os.path.isdir(item_path):
            # Delete the directory and its contents
            shutil.rmtree(item_path)

def UnzipTheFile(zip_file):
    # Replace this with the path to the directory where you want to save the unzipped files
    output_directory = 'server_build'

    # Open the zip file
    with zipfile.ZipFile(UPLOAD_FOLDER + "/" + zip_file, 'r') as z:
        # Extract the files to the output directory
        z.extractall(output_directory)

@app.route('/upload_new_build', methods=['GET', 'POST'])
def upload_file():
    token = request.headers.get('token')
    if token != TOKEN:
        return "failed token check"
    if request.method == 'POST':
        DeleteAllFilesInDirection(UPLOAD_FOLDER)
        DeleteAllFilesInDirection("server_build")
        # check if the post request has the file part
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        # If the user does not select a file, the browser submits an
        # empty file without a filename.
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            UnzipTheFile(filename)
            return "file accepted"
    return '''
    <!doctype html>
    <title>Upload new File</title>

Upload new File

    <form method=post enctype=multipart/form-data>
      <input type=file name=file>
      <input type=submit value=Upload>
    </form>
    '''

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=443, ssl_context='adhoc')
    # app.run(host="0.0.0.0", port=80)


#! /usr/local/bin/python3 -u

import os, sys
import csv
import json
import pyasn
from collections import defaultdict

from collections import namedtuple
DnetEntry = namedtuple('DnetEntry',['asn','bgp','s24'])

#vp_dir = '/data/workspace/data/test/test/vp_measurements/annotated/all'
vp_dir = '/data/workspace/data/4_19_2019/train/vp_measurements/annotated/all'
ipasnfile = '/data/workspace/bgpdumps/ipasn20181203.dat'
#target_prefix = '209.58.192.0/19'
#target_prefix = '88.176.0.0/12'
target_prefix = '180.69.0.0/16'

ipasn = pyasn.pyasn(ipasnfile)

def s24_of(target_ip):
    octets = target_ip.split('.')
    return ".".join(octets[:3]) + ".0/24"

def dnets_of(target_ip):
    try:
        return DnetEntry(*(ipasn.lookup(target_ip)), s24_of(target_ip))
    except:
        return DnetEntry('','','')

measurements_to_target_prefix_by_vp = defaultdict(list)
for vpcsv in os.listdir(vp_dir):
    vpname = vpcsv.replace('.csv','')
    print("opening file {}...".format(os.path.join(vp_dir, vpcsv)))
    with open(os.path.join(vp_dir, vpcsv), 'r') as f:
        next(f)
        r = csv.reader(f, delimiter=',')
        for measurement in r:
            #if dnets_of(measurement[0]).bgp == target_prefix:
            #    measurements_to_target_prefix_by_vp[vpcsv].append(measurement)
            #    print(measurement)
            if measurement[1] == target_prefix:
                measurements_to_target_prefix_by_vp[vpname].append(measurement)
                print(measurement)

with open('./gather_measurements_to_prefix.json', 'w') as f:
    json.dump(measurements_to_target_prefix_by_vp, f)


import numpy as np

def dec(num, base, l):
     dig = np.array([0 for i in range(l)])
     quo = num
     div = base**(l-1)
     for i in range(l):
             dig[i] = quo//div
             quo    = quo%div
             div = div//base
             #dig[0] is the digit of highest place value
     return dig

a = np.zeros(3**4)

downcount =0
upcount   =0
for i in range(3**4):
	num = dec(i,3,4)
	count = [0 for j in range(3)]
	for j in range(4):
		if num[j] == 0:
			count[0] +=1
		if num[j] == 1:
			count[1] +=1
		if num[j] == 2:
			count[2] +=1

	if (count[0] == 2) and (count[1] == 1) and (count[2] ==1):
		downcount += 1

	if (count[2] == 2) and (count[1] == 1) and (count[0] ==1):
		upcount += 1

wf = np.zeros((2,3,3,3,3))

for i in range(3**4):
	num = dec(i,3,4)
	count = [0 for j in range(3)]
	for j in range(4):
		if num[j] == 0:
			count[0] +=1
		if num[j] == 1:
			count[1] +=1
		if num[j] == 2:
			count[2] +=1

	if (count[0] == 2) and (count[1] == 1) and (count[2] ==1):
		index = [0] +list(num)
		wf[tuple(index)] = 1./np.sqrt(downcount)

	if (count[2] == 2) and (count[1] == 1) and (count[0] ==1):
		index = [1] +list(num)
		wf[tuple(index)] = 1./np.sqrt(upcount)

f = open("Tensor2.dat",'w+')
for i0 in range(2):
	for i in range(3**4):
		num = dec(i,3,4)
		index = [i0]+list(num)
		if (wf[tuple(index)]) != 0:
			f.write(str(i0)+'\t'+str(num[0]) + '\t' + str(num[1]) + '\t' + str(num[2]) + '\t' + str(num[3]) + '\t' +str(wf[tuple(index)]) + '\n')

f.close()


import os,sys
import socket
import termios
import tty
from datetime import datetime
from modules.table_init import *
from modules.db_conn import session

def interactive_shell(channel, login_user, share_user, server_ip):
    import select
    oldtty = termios.tcgetattr(sys.stdin)
    try:
        tty.setraw(sys.stdin.fileno())
        tty.setcbreak(sys.stdin.fileno())
        channel.settimeout(0.0)

        cmd = ''

        tab_key = False
        while True:
            r, w, e = select.select([channel, sys.stdin], [], [])
            if channel in r:
                try:
                    x = channel.recv(1024).decode()
                    if tab_key:
                        if x not in ('\t','\r\n'):
                            cmd += x
                        tab_key = False
                    if len(x) == 0:
                        sys.stdout.write('\r\n*** EOF\r\n')
                        break
                    sys.stdout.write(x)
                    sys.stdout.flush()
                except socket.timeout:
                    pass
            if sys.stdin in r:
                x = sys.stdin.read(1)
                if '\r' != x:
                    cmd +=x
                if '\r' == x and len(cmd) > 0:
                    add_log = Cmd_log(login_user=login_user,
                            share_user=share_user,
                            server_ip=server_ip,
                            shell_command=cmd,
datetime=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
                    session.add(add_log)
                    session.commit()
                    cmd = ''
                if '\t' == x:
                    tab_key = True
                channel.send(x)
    finally:
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)


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

def bfs(i, j):
    global n, size, ans
    visited = [[0] * n for _ in range(n)]
    q = deque()
    q.append((i, j, 0))
    grid[i][j] = 0
    visited[i][j] = True
    tmp = 0
    while q:
        i, j, t = q.popleft()
        if tmp:
            if t >= tmp:
                break
        for dire in dires:
            ni, nj = i+dire[0], j+dire[1]
            if 0 <= ni < n and 0 <= nj < n and not visited[ni][nj]:
                if not grid[ni][nj] or grid[ni][nj]==size:
                    visited[ni][nj]=True
                    q.append((ni, nj, t+1))
                elif grid[ni][nj] < size:
                    visited[ni][nj]=True
                    check.append((ni, nj))
                    tmp = t+1
    ans += tmp

n = int(input())
grid = [list(map(int, input().strip().split())) for _ in range(n)]
dires = [(-1, 0), (0, -1), (0, 1), (1, 0)]
for i in range(n):
    for j in range(n):
        if grid[i][j]==9:
            check = [(i, j)]

ans = 0
size = 2
eat = -1
while check:
    check.sort()
    si, sj = check[0][0], check[0][1]
    eat += 1
    grid[si][sj] = 0
    check = []
    if eat == size:
        size += 1
        eat = 0
    bfs(si, sj)
print(ans)


try:
	from zcrmsdk.src.com.zoho.crm.api.exception import SDKException
	from zcrmsdk.src.com.zoho.crm.api.util import Constants
	from zcrmsdk.src.com.zoho.crm.api.share_records.response_handler import ResponseHandler
except Exception:
	from ..exception import SDKException
	from ..util import Constants
	from .response_handler import ResponseHandler

class ResponseWrapper(ResponseHandler):
	def __init__(self):
		"""Creates an instance of ResponseWrapper"""
		super().__init__()

		self.__share = None
		self.__shareable_user = None
		self.__key_modified = dict()

	def get_share(self):
		"""
		The method to get the share

		Returns:
			list: An instance of list
		"""

		return self.__share

	def set_share(self, share):
		"""
		The method to set the value to share

		Parameters:
			share (list) : An instance of list
		"""

		if share is not None and not isinstance(share, list):
			raise SDKException(Constants.DATA_TYPE_ERROR, 'KEY: share EXPECTED TYPE: list', None, None)

		self.__share = share
		self.__key_modified['share'] = 1

	def get_shareable_user(self):
		"""
		The method to get the shareable_user

		Returns:
			list: An instance of list
		"""

		return self.__shareable_user

	def set_shareable_user(self, shareable_user):
		"""
		The method to set the value to shareable_user

		Parameters:
			shareable_user (list) : An instance of list
		"""

		if shareable_user is not None and not isinstance(shareable_user, list):
			raise SDKException(Constants.DATA_TYPE_ERROR, 'KEY: shareable_user EXPECTED TYPE: list', None, None)

		self.__shareable_user = shareable_user
		self.__key_modified['shareable_user'] = 1

	def is_key_modified(self, key):
		"""
		The method to check if the user has modified the given key

		Parameters:
			key (string) : A string representing the key

		Returns:
			int: An int representing the modification
		"""

		if key is not None and not isinstance(key, str):
			raise SDKException(Constants.DATA_TYPE_ERROR, 'KEY: key EXPECTED TYPE: str', None, None)

		if key in self.__key_modified:
			return self.__key_modified.get(key)

		return None

	def set_key_modified(self, key, modification):
		"""
		The method to mark the given key as modified

		Parameters:
			key (string) : A string representing the key
			modification (int) : An int representing the modification
		"""

		if key is not None and not isinstance(key, str):
			raise SDKException(Constants.DATA_TYPE_ERROR, 'KEY: key EXPECTED TYPE: str', None, None)

		if modification is not None and not isinstance(modification, int):
			raise SDKException(Constants.DATA_TYPE_ERROR, 'KEY: modification EXPECTED TYPE: int', None, None)

		self.__key_modified[key] = modification


import json

from django.test import TestCase

from tally_ho.apps.tally.models.sub_constituency import SubConstituency
from tally_ho.libs.tests.test_base import create_tally, create_ballot
from tally_ho.libs.utils.memcache import MemCache
from tally_ho.libs.utils.query_set_helpers import BulkCreateManager
from tally_ho.libs.utils.query_set_helpers import BulkUpdateManyToManyManager
from tally_ho.libs.tests.fixtures.sub_con_data import (
    sub_cons
)

class TestBulkUpdateManyToManyManager(TestCase):
    def setUp(self):
        self.tally = create_tally()
        ballot = create_ballot(self.tally)
        self.many_to_many_fields = { 'ballots': [ballot] }
        self.objects = []
        for sub_con_data in sub_cons:
            self.objects.append(SubConstituency(
                tally=self.tally,
                **sub_con_data
            ))
        # Bulk create sub cons
        manager = BulkCreateManager(
            objs_count=len(sub_cons),
        )
        for obj in self.objects:
            manager.add(obj)
        self.cache_key = 'test_cache_key'
        self.memcache_client = MemCache()
        self.memcache_client.delete(self.cache_key)

    def test_bulk_create(self):
        manager = BulkUpdateManyToManyManager(
            instances_count=len(sub_cons),
            cache_instances_count=True,
            cache_key=self.cache_key,
            memcache_client=self.memcache_client
        )

        # Add objects to the manager
        for obj in self.objects:
            manager.add({
                'instance': obj,
                'many_to_many_fields': self.many_to_many_fields,
            })
        # Ensure all sub con objects have been assigned a ballot
        self.assertEqual(
            SubConstituency.objects.filter(tally=self.tally).values(
                'ballots').count(),
            len(sub_cons))

        # Ensure cache is updated with the correct count
        memcache_data, _ = self.memcache_client.get(self.cache_key)
        cached_data = json.loads(memcache_data)
        self.assertEqual(
            cached_data.get('elements_processed'), len(sub_cons))
        self.assertTrue(cached_data.get('done'))

    def test_no_cache(self):
        manager = BulkUpdateManyToManyManager(instances_count=len(sub_cons))

        # Add objects to the manager
        for obj in self.objects:
            manager.add({
                'instance': obj,
                'many_to_many_fields': self.many_to_many_fields,
            })

        # Call the done method to create the remaining objects
        manager.done()

        # Ensure all sub con objects have been assigned a ballot
        self.assertEqual(
            SubConstituency.objects.filter(tally=self.tally).values(
                'ballots').count(),
            len(sub_cons))

    def test_chunk_size(self):
        manager = BulkUpdateManyToManyManager(chunk_size=5)

        # Add objects to the manager
        for obj in self.objects:
            manager.add({
                'instance': obj,
                'many_to_many_fields': self.many_to_many_fields,
            })

        # Call the done method to create the remaining objects
        manager.done()

        # Ensure all sub con objects have been assigned a ballot
        self.assertEqual(
            SubConstituency.objects.filter(tally=self.tally).values(
                'ballots').count(),
            len(sub_cons))


import pygame as pg

from data.colors import WHITE
from gui.long_button import LongButton
from gui.slider import Slider
import data.languages.english as eng
import data.languages.russian as rus

TEXTS = {
    'quit_button':
        {
            'English': eng.OPTIONSWINDOW_QUIT_BUTTON,
            'Russian': rus.OPTIONSWINDOW_QUIT_BUTTON
        },
    'labels':
        {
            'Russian': (
                rus.OPTIONSWINDOW_CAPTION,
                rus.OPTIONSWINDOW_LABEL_MUSIC,
                rus.OPTIONSWINDOW_LABEL_SOUND
            ),
            'English': (
                eng.OPTIONSWINDOW_CAPTION,
                eng.OPTIONSWINDOW_LABEL_MUSIC,
                eng.OPTIONSWINDOW_LABEL_SOUND
            )
        }
}

class OptionsWindow:
    def __init__(self):
        self.sound_slider = Slider(500, 600)
        self.music_slider = Slider(500, 400)
        self.caption = None
        self.label_music = None
        self.label_sound = None
        self.quit_button = None
        self.set_language("English")

    def set_language(self, language):
        self.set_labels(*TEXTS['labels'][language])
        self.quit_button = LongButton(944, 832, False, TEXTS['quit_button'][language])

    def set_labels(self, caption, label_1, label_2):
        pg.font.init()
        font = pg.font.SysFont('Calibri', 56, True)
        self.caption = font.render(caption, True, WHITE)
        self.label_music = font.render(label_1, True, WHITE)
        self.label_sound = font.render(label_2, True, WHITE)

    def handle(self, e_type, sounds) -> bool:
        game_running = True
        self.sound_slider.handle(e_type)
        self.music_slider.handle(e_type)
        self.update_mixer(sounds)
        if self.quit_button.cursor_on_button():
            game_running = False
        return game_running

    def update_mixer(self, sounds):
        if self.sound_slider.clicked:
            for sound in sounds.values():
                sound.set_volume(self.sound_slider.value)
        if self.music_slider.clicked:
            pg.mixer.music.set_volume(self.music_slider.value)

    def update(self, sounds):
        self.quit_button.update_color()
        self.sound_slider.update()
        self.music_slider.update()
        self.update_mixer(sounds)

    def draw(self, screen):
        screen.blit(self.caption, (560, 176))
        screen.blit(self.label_music, (240, 375))
        screen.blit(self.label_sound, (240, 575))

        self.quit_button.draw(screen)
        self.sound_slider.draw(screen)
        self.music_slider.draw(screen)


import os
from PIL import Image
import numpy as np
from tqdm import tqdm
import cv2 as cv

def convert_JCRT_images(input_dir, output_dir):
    file_names = os.listdir(input_dir)
    # file_names = [item for item in file_names if item[:2] == "JP"]
    print("image number: {0:}".format(len(file_names)))

    for file_name in file_names:
        input_file_name = os.path.join(input_dir,file_name)
        output_file_name = os.path.join(input_dir,file_name)
        # output_file_name = os.path.join(output_dir, output_file_name)

        shape = (2048, 2048) # matrix size
        dtype = np.dtype('>u2') # big-endian unsigned integer (16bit)

        # Reading.
        # fid = open(input_file_name, 'rb')
        # data = np.fromfile(fid, dtype)
        data=cv.imread(input_file_name)
        data = cv.resize(data,shape)

        # Rescale intensity to 0-255
        data[data > 4096] = 4096
        data = data * 255.0 / 4096 #data.max()
        data = np.asarray(data, np.uint8)

        # Reshape to 256x256
        img = Image.fromarray(data)
        img = img.resize((256, 256), Image.BILINEAR)
        img.save(output_file_name)
        print(file_name, data.min(), data.max(), data.mean(), data.std())

def convert_JCRT_labels(input_dir, output_dir):
    # organs      = ['heart']
    # sub_folders = ['fold1', 'fold2']

        image_folder = input_dir
        image_names  = os.listdir(image_folder)
        # image_names  = [item for item in image_names if item[:2] == 'JP']
        for image_name in image_names:
            print(image_name[:-4])
            label_list = []
            image_folder = input_dir
            image_full_name = os.path.join(image_folder, image_name)
            img = Image.open(image_full_name)
            img = img.resize((256,256), Image.NEAREST)
            img = np.asarray(img)
            label_list.append(img)
            label = np.asarray(label_list, np.uint8)
            label = np.max(label, axis = 0)
            label = Image.fromarray(label)
            output_full_name = image_name[:-4] + ".png"
            output_full_name = os.path.join(input_dir, output_full_name)
            label.save(output_full_name)

if __name__ == "__main__":
    JSRT_root  = "/home/yangbaoqi/desktop/code/PyMIC_examples-main/segmentation/JSRT/picture/data"
    input_image_dir  = JSRT_root + "/image"
    output_image_dir = JSRT_root + "/newimg"
    convert_JCRT_images(input_image_dir, output_image_dir)

    input_label_dir  = JSRT_root + "/label"
    output_label_dir = JSRT_root + "/newgts"
    convert_JCRT_labels(input_label_dir, output_label_dir)


BSMQ_OF_OPENEXIST = 0x00000001
BSMQ_OF_CREATENEW = 0x00000002
BSMQ_OF_OPENMULTI = 0x00000004

BSMQ_OT_COMMONMQ = 0x01
BSMQ_OT_PRIORITYMQ = 0x02
BSMQ_OT_TEMPMQ = 0x04
BSMQ_OT_ENCRYPT = 0x08
BSMQ_OT_INDEXRECORD = 0x10

BS_MQ_MAXNAME = 100
BS_MQ_MAXPWD = 20

# 表示最多支持多少个优先级
BS_MQ_MAXPRIORITY = 9
# 普通优先级
BS_MQ_COMMONPRIORITY = (BS_MQ_MAXPRIORITY / 2 + 1)

BS_MQ_MAXRECORDID = 30


from typing import List, Optional
from enum import Enum

from pydantic import BaseModel, Field, NonNegativeFloat

class PipelineRunStatus(str, Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"

class TaskRun(BaseModel):
    duration: Optional[NonNegativeFloat] = 0
    """Task duration in milliseconds"""
    has_output: bool = False
    """True if the task generated an output"""
    status: Optional[PipelineRunStatus] = PipelineRunStatus.PENDING
    task_id: str

    class Config:
        from_attributes = True

class NotificationRule(BaseModel):
    channels: List[str]
    pipeline_status: List[PipelineRunStatus] = Field(
        default_factory=lambda: [PipelineRunStatus.FAILED]
    )


from PyQt6.QtWidgets import QWidget, QLabel, QApplication
from PyQt6.QtCore import Qt
from backend.weather import WeatherData
import sys
import datetime

class CityDisplay(QWidget):
    def __init__(self, weather_data: WeatherData = None) -> None:
        super().__init__()

        self.wd = weather_data if weather_data != None else WeatherData()
        # self.wd.get_weather()
        self.wd.get_city()
        self.name = self.wd.city.split(",")[:3]

        self.label = QLabel(self)
        self.label.setText("".join(self.name))
        self.label.setAlignment(Qt.AlignmentFlag.AlignLeft)
        self.label.setStyleSheet("border: 2px solid black; padding: 4px;")

if __name__ == "__main__":
    app = QApplication(sys.argv)

    widget = CityDisplay()
    widget.show()

    sys.exit(app.exec())


'''
Created on 08.07.2013

@author: vau
'''
import time
import json
import uuid
import lemon
import core
import scheduler.default_tasks as tasks

MASK    = 'schedule_'
MAIN    = 'items'

CHECK_INTERVAL  = 0.1
STORE_INTERVAL  = 1

SECONDS = 1
MINUTES = 60*SECONDS
HOURS   = 60*MINUTES
DAYS    = 24*HOURS

class Scheduler(lemon.BaseAgentLemon):
    '''
    classdocs
    '''

    def __init__(self, _logger, _config, _info):
        '''
        Constructor
        '''
        self._storage   = None
        self._taskManager   = None
        self._schedule  = {}
        self._removed_from_schedule = []
        self._scheduleModified  = False
        lemon.BaseAgentLemon.__init__(self, _logger, _config, _info)

    def run(self):

        self._storage       = core.getCoreInstance().getInstance('STORAGE')
        self._taskManager   = core.getCoreInstance().getInstance('TASK_MANAGER')
        self._logger.info('Scheduler started')
        self._loadStorage()
        self._setReady()
        it  = 0
        while self._running:
            self._process()
            time.sleep(CHECK_INTERVAL)
            it += CHECK_INTERVAL
            if it > STORE_INTERVAL :
                it = 0
                self._store_schedule()

    def add(self, func_type, name='default', start_time=None, interval = 5*MINUTES,  kwargs=None, revision=0):
        schtask = {}
        if start_time is None:
            start_time  = time.time()
        schtask['__id'] = str(uuid.uuid4())
        schtask['name'] = name
        schtask['start_time']   = start_time
        schtask['last_time']    = start_time - interval
        schtask['interval']     = interval
        schtask['task']         = {'func': func_type, 'args': kwargs}
        schtask['__revision']   = revision
        self._add_to_schedule(schtask['__id'], schtask)
        self._store(schtask['__id'], schtask)

    def remove(self, name):
        removed = None
        for k, v in self._schedule.items():
            if v['name'] == name:
                print("REMOVING: "+str(v['name']))
                removed = k
        if removed:
            self._remove_from_schedule(removed)

    def getScheduledTask(self, name=None):
        if name is None:
            return self._schedule
        for v in self._schedule.values():
            if v['name']    == name:
                return v

    def getSchedule(self):
        for v in self._schedule.values():
            yield v

    def getNotInitiatedDefaultTasks(self):
        for taskName, task in tasks.tasks.items():
            if self.getScheduledTask(taskName) is None:
                yield task

    def _add_to_schedule(self, _key, _schtask):
        self._schedule[_key] = _schtask
        self._scheduleModified  = True

    def _remove_from_schedule(self, _key):
        self._schedule.pop(_key)
        self._removed_from_schedule.append(_key)

    def _store(self, key, obj):
        try:
            self._storage.writeItem(MASK + str(key), json.dumps(obj))
            self._store_schedule()
        except Exception as e:
            self._logger.error('Error occured in _store while storing {0}: {1}'.format(str(key), str(e)))

    def _loadStorage(self):
        try:
            items   = self._storage.readStr(MASK + MAIN)
            if items is not None:
                headers   = json.loads(items)
                for key in headers:
                    item    = json.loads(self._storage.readStr(MASK + key))
                    self._add_to_schedule(key, item)
                self._logger.info('schedule loaded')
        except Exception as e:
            self._logger.error('Error occured in _loadStorage: {0}'.format(str(e)))

    def _process(self):
        timestamp   = time.time()
        keys    = list(self._schedule.keys())
        remove_list = []
        for k in keys:
            if self._schedule[k]['interval'] == 0:
                self._startTask(k, self._schedule[k]['task'])
                self._logger.info('scheduled task {0} started'.format(str(k)))
                remove_list.append(k)
            elif self._schedule[k]['last_time'] + self._schedule[k]['interval'] < timestamp:
                self._startTask(k, self._schedule[k]['task'])
                self._logger.info('scheduled task {0} started'.format(str(k)))
                self._schedule[k]['last_time']  = time.time()
        for remove_name in remove_list:
            self._remove_from_schedule(remove_name)

    def _store_schedule(self):
        if self._scheduleModified:
            self._storage.writeItem(MASK + MAIN, json.dumps(list(self._schedule.keys())))
            for key in self._removed_from_schedule:
                self._storage.deleteItem(MASK+key)
            self._removed_from_schedule = []
            self._scheduleModified = False

    def _startTask(self, key, task):
        self._taskManager.new_task(task['func'], task['args'])
        self._logger.info('task {0} successfully send to task manager'.format(str(key)))


#!python3.7
from app import app
import time

def write(message):
    try:
        log_file = open(app.config["LOG_FILE"], "a")
    except:
        raise
    message = time.strftime(" [%H:%M:%S] ", time.gmtime()) + message
    print("")
    print(message)
    print("")
    log_file.write(message)
    log_file.write("\n")
    log_file.close()


import fixtures
import os
import shutil
import time

from camera_app.ubuntu_system_tests.helpers import file_system as fs
from camera_app.ubuntu_system_tests.helpers import sqlite

DEFAULT_STORE_ROOT = os.path.expanduser('~/.tmp_backup')

class BackupRestoreFixture(fixtures.Fixture):
    """Generic fixture class to backup and restore a specific directory."""

    def __init__(self, backup_dir, storage_root_dir=DEFAULT_STORE_ROOT,
                 start_clean=True):
        """
        :param backup_dir: Directory to be backed up.
        :param storage_root_dir: Root directoty to use as backup.
        :param start_clean: Whether to clean the backup directory.
        """
        if not os.path.exists(storage_root_dir):
            os.makedirs(storage_root_dir)
        self.backup_dir = backup_dir
        self.storage_dir = fixtures.TempDir(storage_root_dir)
        self.start_clean = start_clean

    def setUp(self):
        """Backup the required directory and register restore actions."""
        super().setUp()
        self.useFixture(self.storage_dir)
        self.addCleanup(self._restore_directory)
        shutil.rmtree(self.storage_dir.path)
        if os.path.exists(self.backup_dir):
            if self.start_clean:
                fs.move_folder_contents(self.backup_dir, self.storage_dir.path)
            else:
                shutil.copytree(self.backup_dir, self.storage_dir.path)

    def _restore_directory(self):
        """Move the backup data back to original location."""
        if os.path.exists(self.backup_dir):
            fs.clean_dir(self.backup_dir)
        if os.path.exists(self.storage_dir.path):
            fs.move_folder_contents(self.storage_dir.path, self.backup_dir)

class BackupRestoreRequestAccessFixture(fixtures.Fixture):
    """Fill the access requests for the an app by adding the answer in the
    its db and restoring the original data after the test execution."""

    REQUESTS_SCHEMA = 'ApplicationId, Feature, Timestamp, Answer'

    def __init__(self, db, app_id, feature, answer):
        """ Create a Fixture
        :param db: the path to the db
        :param app_id: the application id as it appears in the db
        :param feature: the feature as it appears in the db
        :param answer: True to allow access, False to deny access
        """
        self.db = db
        self.app_id = app_id
        self.feature = feature
        self.timestamp = int(str(time.time()).replace('.', ''))
        self.answer = int(answer)

    def setUp(self):
        super().setUp()

        # Get the initial request access state
        initial_state = self.get_access_request()

        # Fill the db with the desired answer
        self.fill_access_request(self.app_id, self.feature, self.timestamp,
                                 self.answer)

        # Restore the initial access state
        self.clean_request(initial_state)

    def clean_request(self, state):
        """ Restore this request in case there was an initial state, otherwise
        delete the access request when there wasn't an initial state
        """
        if state:
            self.addCleanup(self.fill_access_request, *state)
        else:
            self.addCleanup(self.delete_access_request)

    def fill_access_request(self, app_id, feature, timestamp, answer):
        """ Complete the db with the desired state to allow/deny the access
        to the app_id from the camera app
        """
        cmd = "INSERT OR REPLACE INTO requests (Id, {schema}) VALUES " \
              "((SELECT Id FROM requests WHERE ApplicationId = '{app_id}'), " \
              "'{app_id}', {feature}, {timestamp}, {answer});".\
            format(schema=self.REQUESTS_SCHEMA, app_id=app_id,
                   feature=feature, timestamp=timestamp, answer=answer)
        sqlite.execute(self.db, cmd)

    def delete_access_request(self):
        """ Delete the current state  """
        cmd = "DELETE FROM requests WHERE ApplicationId = '{app_id}' AND " \
              "Feature = {feature}".format(app_id=self.app_id,
                                           feature=self.feature)
        sqlite.execute(self.db, cmd)

    def get_access_request(self):
        """ Retrieve the first access request in the db for the current
        application id and feature
        :return: a list with the values following the table structure
        """
        cmd = "SELECT {schema} FROM requests WHERE ApplicationId = " \
              "'{app_id}' AND Feature = {feature}".\
            format(schema=self.REQUESTS_SCHEMA, app_id=self.app_id,
                   feature=self.feature)
        return sqlite.query_one(self.db, cmd)


import csv
import os
import sys
from tkinter import *
from idk import *

w = Tk()
w.title("Minecraft")
mf = Frame(w)
mf.grid(column=0, row=0, sticky=(N, W, E, S))
w.columnconfigure(0, weight=1)
w.rowconfigure(0, weight=1)

def start(*args):
    global username, usernamestr
    usernamestr = username.get()
    with open("username.txt", "w") as f:
        f.write(usernamestr)
    # with open("leaderboard.csv", "a", newline='') as file:
    #     writer = csv.DictWriter(file, fieldnames=fields)
    #     writer.writerow({'name': usernamestr})

    os.system('python main.py')

def exit(*args):
    quit(10)

def records(*args):
    os.system('python records.py')

st = Button(mf, text="Старт", command=start)
st.grid(column=1, row=1, sticky=(E, W))

ex = Button(mf, text="Выйти", command=exit)
ex.grid(column=1, row=2, sticky=(E, W))

username = StringVar()
username_e = Entry(mf, width=40, textvariable=username)
username_e.grid(column=2, row=1, sticky=(W, E))

ex = Button(mf, text="Рейтинг", command=records)
ex.grid(column=2, row=2, sticky=(E, W))

# sys.stdout.write(str(username))

w.mainloop()


import numpy as np
from numpy import asarray
from PIL import Image
import zipfile
import os

def segmentation(board):

    BORDER_SIZE = 3
    card_shape = (150,150)

    board = np.array(board)

    cards = []

    """border_matrix = np.empty([card_shape[0] + BORDER_SIZE , card_shape[1] + BORDER_SIZE])

    for x in range(card_shape[0] + BORDER_SIZE):
        for y in range(card_shape[1] + BORDER_SIZE):
            if min(x,y) < BORDER_SIZE or min(card_shape[0] - x -1,card_shape[1] - y -1) < BORDER_SIZE:
                border_matrix[x,y] = 1
            else:
                border_matrix[x,y] = 0

    number_border_pixel = border_matrix.sum()
    """

    vector = np.array([0 for i in range(card_shape[0] + 2*BORDER_SIZE)], dtype=float)
    vector[0:BORDER_SIZE] = 1/(2*BORDER_SIZE)
    vector[-BORDER_SIZE:] = 1/(2*BORDER_SIZE)

    img_board = Image.fromarray(np.array(board))
    grayscale_board = np.array(img_board.convert('L'))

    """print(grayscale_board[30,30])
    img = Image.fromarray(grayscale_board)
    img.show()"""
    means = []
    for column in range(0,board.shape[0] - card_shape[0] - 2*BORDER_SIZE):
        for row in range(0,board.shape[1] - card_shape[1] - 2*BORDER_SIZE ):
            subArray = grayscale_board[column:column+card_shape[0]+ 2*BORDER_SIZE,row:row+card_shape[1]+ 2*BORDER_SIZE]
            mean = np.average((np.dot(vector,subArray)+np.dot(subArray,vector))/2)
            means.append(mean)
            if mean <=20:
                cards.append(board[column + BORDER_SIZE:column + BORDER_SIZE + card_shape[0],
                                   row + BORDER_SIZE:row + BORDER_SIZE + card_shape[1]])
    return cards

def applyThreshold(image1,threshold):
    formatted_card = np.copy(image1)
    for x,column in enumerate(image1):
        for y,pixel in enumerate(column):
            formatted_card[x,y] = 0 if pixel < threshold else 255
    return formatted_card

def imageComparison(image1, image2):

    img1 = Image.fromarray(np.array(image1))
    grayscale_image1 = np.array(img1.convert('L'))
    #grayscale_image1 = applyThreshold(grayscale_image1,128)

    img2 = Image.fromarray(np.array(image2))
    grayscale_image2 = np.array(img2.convert('L'))
    #grayscale_image2 = applyThreshold(grayscale_image2,128)

    average_distance = np.mean(np.square(np.absolute(grayscale_image1 - grayscale_image2)))

    return average_distance < 20

def detection(board):
    background = Image.open("background.png")
    arrayBackground = asarray(background)

    cards = segmentation(board)

    return [card for card in cards if not imageComparison(background,card)]

"""
image = Image.open('board.jpg')
faceup = detection(image)

print(str(len(faceup)) + " cards face up")
for card in faceup:
    img = Image.fromarray(np.array(card))
    img.show()
    s
def zipped(image_array):
    zipf = zipfile.ZipFile('Name.zip','w', zipfile.ZIP_DEFLATED)
    for image in image_array:
        zipf.write(image.tobytes())
    zipf.close()
    return zipf

"""