from __future__ import annotations

import calendar
import datetime
from multiprocessing import Pool
from typing import TYPE_CHECKING

from absl import logging
import numpy as np
import polars as pl
import xarray as xr

from scs.utils import (
    decompress_and_delete_bz2,
    delete_all_files_in_folder,
    download_and_unpack,
    gen_months_in_range,
    get_files_in_directory,
)

if TYPE_CHECKING:
    from pathlib import Path

URLS: dict[str, list[str]] = {
    "WS_080m": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/converted/hourly/2D/WS_080/WS_080m.2D.",
        ".nc4",
    ],
    "WS_100m": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/converted/hourly/2D/WS_100/WS_100m.2D.",
        ".nc4",
    ],
    "WS_125m": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/converted/hourly/2D/WS_125/WS_125m.2D.",
        ".nc4",
    ],
    "WS_150m": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/converted/hourly/2D/WS_150/WS_150m.2D.",
        ".nc4",
    ],
    "ASWDIFD_S": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/hourly/2D/ASWDIFD_S/ASWDIFD_S.2D.",
        ".grb.bz2",
    ],
    "ASWDIR_S": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/hourly/2D/ASWDIR_S/ASWDIR_S.2D.",
        ".grb.bz2",
    ],
    "ATHD_S": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/hourly/2D/ATHD_S/ATHD_S.2D.",
        ".grb.bz2",
    ],
    "CLCT": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/hourly/2D/CLCT/CLCT.2D.",
        ".grb.bz2",
    ],
    "T_2M": [
        "https://opendata.dwd.de/climate_environment/REA/COSMO_REA6/hourly/2D/T_2M/T_2M.2D.",
        ".grb.bz2",
    ],
}

MAPPING: dict[str, str] = {
    "WS_080m": "wind_speed",
    "WS_100m": "wind_speed",
    "WS_125m": "wind_speed",
    "WS_150m": "wind_speed",
    "ASWDIFD_S": "ASWDIFD_S",
    "ASWDIR_S": "ASWDIR_S",
    "ATHD_S": "ATHD_S",
    "CLCT": "tcc",
    "T_2M": "t2m",
}

def obtain_and_preprocess_weather_data(
    downsample: int,
    mask_path: str,
) -> None:
    raw_weather_directory = "data/raw_data/weather_data"
    delete_all_files_in_folder(raw_weather_directory)
    months = gen_months_in_range((2005, 12), (2019, 8))
    mask = np.load(mask_path)[::downsample, ::downsample]
    colnames = gen_weather_variable_colnames(mask)
    for month in months:
        logging.info(f"Downloading data for month: {month}")
        with Pool(9) as p:
            p.starmap(
                download_and_unpack,
                [(month.join(url), raw_weather_directory) for _, url in URLS.items()],
            )
        data = preprocess_weather_month(
            raw_weather_directory, mask, downsample, month, colnames
        )
        out_path = f"data/preprocessed_data/weather_data/{month}.csv"
        data.write_csv(out_path)
        delete_all_files_in_folder(raw_weather_directory)
        logging.info(f"Wrote preprocessed dataset for month {month} to: {out_path}")

def gen_weather_variable_colnames(mask: np.ndarray) -> dict[str, list[str]]:
    n_elements = np.sum(mask)
    colnames = {}
    for key in MAPPING:
        colnames[key] = [f"{key}_{n}" for n in range(n_elements)]
    return colnames

def preprocess_weather_month(
    directory: str,
    mask: np.ndarray,
    downsample: int,
    month: str,
    colnames: dict[str, list[str]],
) -> pl.DataFrame:
    files = get_files_in_directory(directory)
    data = {}
    for file in files:
        if file.suffix == ".bz2":
            file = decompress_and_delete_bz2(file)
        elif file.suffix == ".idx":
            continue
        logging.info(f"Processing file: {file}")
        name = file.name.split(".")[0]
        values = _read_weather_data_to_xarray(file)[MAPPING[name]].values
        # Obtain a grid of every 'downsample'th entry and store the masked
        # values as a vector in the dictionary.
        data[name] = values[:, ::downsample, ::downsample][:, mask]
        if np.any(np.isnan(data[name])):
            data[name] = np.nan_to_num(data[name])
            logging.info(f"Replaced NaN values with zeros in: {file}")
    dframes = [pl.from_dict(_gen_weather_timecodes(month))]
    dframes += [
        pl.from_numpy(data[key], schema=colnames[key], orient="row") for key in URLS
    ]
    return pl.concat(dframes, how="horizontal")

def _read_weather_data_to_xarray(filepath: Path) -> xr.Dataset:
    if filepath.suffix[:3] == ".nc":
        data = xr.open_dataset(filepath)
    elif filepath.suffix == ".grb":
        data = xr.open_dataset(filepath, engine="cfgrib")
    else:
        raise TypeError(
            f"Can only read data of type '.nc*' and '.grb'; "
            f"received: {filepath.suffix}"
        )
    return data

def _gen_weather_timecodes(year_month: str) -> dict[str, list[str]]:
    year = int(year_month[:4])
    month = int(year_month[4:])
    start = datetime.datetime(year, month, 1, 0, 0)
    # Determine the number of days in the month
    _, num_days = calendar.monthrange(year, month)
    num_hours = num_days * 24
    timestamps = [start + datetime.timedelta(hours=i) for i in range(num_hours)]
    return {
        "timestamp": [t.strftime("%Y-%m-%dT%H:%M+00:00") for t in timestamps],
    }


"""Prepare a config file for the COVID-19 pipeline"""

import sys
from pathlib import Path
import shutil
import numpy as np
import argparse
import yaml

def maybe_delete_dir(path):
    dirpath = Path(path)
    if dirpath.exists():
        shutil.rmtree(dirpath)

def maybe_make_dir(path):
    dirpath = Path(path)
    dirpath.mkdir(exist_ok=True)

parser = argparse.ArgumentParser()
parser.add_argument(
    "-o",
    "--output",
    type=str,
    default="stdout",
    help="Output file. If unspecified or `stdout`, writes to stdout.",
)
parser.add_argument(
    "--inference-period",
    type=np.datetime64,
    nargs=2,
    help="Date range [low high)",
    metavar="ISO6801",
)
parser.add_argument("--reported-cases", type=str, help="Path to case file")
parser.add_argument("--commute-volume", type=str, help="Path to commute volume file")
parser.add_argument(
    "--case-date-type",
    type=str,
    help="Case date type (specimen | report)",
    choices=["specimen", "report"],
)
parser.add_argument("--pillar", type=str, help="Pillar", choices=["both", "1", "2"])
parser.add_argument("--results-dir", type=str, help="Results directory")
parser.add_argument("--delete", type=bool, default=False, help="Delete an existing results dir before writing")
parser.add_argument("config_template", type=str, help="Config file template")

args = parser.parse_args()
template_file = args.config_template
output_file = args.output

with open(template_file, "r") as f:
    config = yaml.load(f, Loader=yaml.FullLoader)

for key in ["reported_cases", "commute_volume", "case_date_type", "pillar"]:
    val = getattr(args, key)
    if val is not None:
        config["data"][key] = val

if args.inference_period is not None:
    config["Global"]["inference_period"] = [str(x) for x in args.inference_period]

for key in ["results_dir"]:
    val = getattr(args, key)
    if val is not None:
        config["output"][key] = val

if args.delete is True:
    maybe_delete_dir(config["output"]["results_dir"])
maybe_make_dir(config["output"]["results_dir"])

if args.output == "stdout":
    print(yaml.dump(config))
else:
    with open(args.output, "w") as f:
        yaml.dump(config, f)
    print(args.output)

sys.exit(0)


#!/usr/bin/python3
"""utf-8 validation"""

def validUTF8(data):
    """
    UTF-8 validation function that checks if the input list of integers
    represents a valid UTF-8 sequence.

    :param data: A list of integers representing bytes in a UTF-8 sequence.
    :return: True if the input is a valid UTF-8 sequence, False otherwise.
    """

    def is_continuation_byte(byte):
        # Helper function to check if the byte is a continuation byte
        # (starts with '10').
        return 128 <= byte <= 191

    if len(data) == 0:
        # If the input list is empty, it is considered a valid UTF-8 sequence.
        return True

    if not isinstance(data, list):
        # Ensure that the input data is a list.
        return False

    count = 0
    for each in data:
        # Loop through each element in the input list.

        if not isinstance(each, int):
            # Check if each element is a valid 8-bit unsigned integer
            # (0 to 255).
            # If not, it is not a valid UTF-8 sequence.
            return False

        # Consider only the last 8 bits of the integer.
        each = each % 256

        if each < 128:
            # Single-byte UTF-8 character (0xxxxxxx).
            count = 0
        elif each >> 5 == 0b110:
            # Two-byte UTF-8 character (110xxxxx 10xxxxxx).
            count = 1
        elif each >> 4 == 0b1110:
            # Three-byte UTF-8 character (1110xxxx 10xxxxxx 10xxxxxx).
            count = 2
        elif each >> 3 == 0b11110:
            # Four-byte UTF-8 character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx).
            count = 3
        else:
            # Invalid UTF-8 encoding pattern.
            return False

        for j in range(count):
            # Loop to check continuation bytes for multi-byte characters.
            if len(data) > j + 1:
                next_byte = data[j + 1]

                if not is_continuation_byte(next_byte):
                    # If the continuation byte doesn't start with '10',
                    # it is not a valid UTF-8 sequence.
                    return False
            else:
                # If there is no continuation byte available,
                # it is not a valid UTF-8 sequence.
                return False

    return True


from flask import Flask, render_template
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('client request')
def test_message(message):
    print('Server has received a request.')
    print('Request recived: {}'.format(message))
    emit('server response', {'data_of_server': 'This is a certificate!'})
    print('Server has send a certification to client.')

@socketio.on('my event')
def terminal_response(message):
    print('Terminal recived: {}'.format(message))
    emit('my response', {'data': 'Yeah!'})

if __name__ == '__main__':
    socketio.run(app)


import unittest
from AffineCipher.AffineCipher import AffineCipher
from parameterized import parameterized, parameterized_class
from nose.tools import assert_equal, assert_raises

class AffineParameterizedPackage(unittest.TestCase):

    def setUp(self):
        self.tmp = AffineCipher()

    @parameterized.expand([
        ("a", 1, 3, "d"),
        ("z", 1, 3, "c"),
        ("abc", 3, 12, "mps"),
        ("veni vidi", 3, 12, "xyzk xkvk"),
        ("the quick brown fox jumps over the lazy dog", 3, 12, "rhy iuksq plcaz bcd nuwfo cxyl rhy tmjg vce"),
    ])
    def test_one_parameterized(self, text, a, b, result):
        self.assertEqual(self.tmp.affine_cipher(text, a, b), result)

    def tearDown(self):
        self.temp = None

@parameterized([
    ("a", 1, 3, "d"),
    ("z", 1, 3, "c"),
    ("abc", 3, 12, "mps"),
    ("veni vidi", 3, 12, "xyzk xkvk"),
    ("the quick brown fox jumps over the lazy dog", 3, 12, "rhy iuksq plcaz bcd nuwfo cxyl rhy tmjg vce"),
])
def test_affine_encode_outside_class(text, a, b, result):
    r = AffineCipher()
    assert_equal(r.affine_cipher(text, a, b), result)

@parameterized_class(('text', 'a', 'b', 'result'), [
    ("a", 1, 3, "d"),
    ("z", 1, 3, "c"),
    ("abc", 3, 12, "mps"),
    ("veni vidi", 3, 12, "xyzk xkvk"),
    ("the quick brown fox jumps over the lazy dog", 3, 12, "rhy iuksq plcaz bcd nuwfo cxyl rhy tmjg vce"),
])
class AffineParameterizedPackage2(unittest.TestCase):

    def setUp(self):
        self.tmp = AffineCipher()

    def test_one_parameterized(self):
        self.assertEqual(self.tmp.affine_cipher(self.text, self.a, self.b), self.result)

    def tearDown(self):
        self.temp = None

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


# -*- coding: utf-8 -*-
'''Modulis, kuriame aprasytas metodas surenkantis komanda ir jos argumentus, priklausomai,
nuo komandos tipo ir jos patterno apibrezto texsyntax modulyje.

Naudojimas: collect_full_command(pozicija,stringas)
pozicija -- komandos pradzia reiskianti metacharas "\\"
stringas -- parsinamo failo turinys

Return: (charu_skaicius,komanda,argumentu listas, originalus_tekstas)'''

import string, sys, os

try:
    if __IPYTHON__:
        if sys.platform=='win32':
            os.chdir('d:/Luko/vtexparser/')
        else:
            sys.path.append('/home/lukas/vtexparser/')
except:
    pass

# LaTeX'o sintakse apibrezta
# kitame modulyje
import latexsyntax

              ########################################
              #### PARSINIMO ERRORU APIBREZIMAI   ####
              ## tam, kad butu galima loginti visus ##
              ## netikusius parsinimo meginimus     ##

class ParseError(Exception):
    '''Motininis parsinimo Erroras'''
    def __init__(self,Msg,Poz):
        self.msg=Msg
        self.poz=Poz
    def __str__(self):
        return self.msg

class MatchError(ParseError):
    '''Erroras atsirandanti, kai
    ieskoma nesuporuoto skirtuko.'''
    def __init__(self,Msg,Poz):
        super().__init__(Msg,Poz)

class EOSError(ParseError):
    '''Erroras atsirandanti, kai
    ieskoma ten kur baigesi stringas.'''
    def __init__(self,Msg,Poz):
        super().__init__(Msg,Poz)

class AlgError(ParseError):
    '''Erroras atsirandantis
    del blogai parasyto algoritmo.'''
    def __init__(self,Msg,Poz):
        super().__init__(Msg,Poz)

def context(poz,String,End=False,Range=50,Tag=False,Delim=False):
    '''Grazina eilutes konteksta apie esama
    symboli (symboliu seka).'''
    if Delim:
        delim=Delim
    else:
        delim=''
    if Tag:
        ltag=delim+'<'+Tag+'@-->'+delim
        rtag=delim+'<--@'+Tag+'>'+delim
    else:
        delim=''
        ltag=delim+'@-->>'
        rtag='<<@--'+delim
    if not End:

        End=poz
    else: End=End-1
    if poz<=Range: before=poz
    else: before=Range

    if len(String)-End<=Range: after=len(String)-End
    else: after=Range
    if Tag:
        return (ltag+String[poz:End+1]+rtag)
    else:
        if poz==0:
            return (ltag+String[poz:End+1]+rtag+String[End+1:End+after])
        else:
            return (String[poz-before:poz]+ltag+String[poz:End+1]+rtag\
                    +String[End+1:End+after])

              ########################################
              ####         PARSINIMO METU         ####
              ##     INICIALIZUOJAMI OBJEKTAI       ##

              ########################################
              ####      OBJEKTU KOMPONENTAI       ####

class Opening:
    '''Skirtukai atidanatys reiskini'''
    def __init__(self,Tipas,Name,Body):
        self.Type=Tipas
        self.name=Name
        self.body=Body
    def show_self(self):
        print('▼----------------------['+self.Type+':'+repr(self.body)+']')

class Closing(Opening):
    def __init__(self,Tipas,Name,Body):
        super().__init__(Tipas,Name,Body)
    def show_self(self):
       print('▲----------------------['+self.Type+':'+repr(self.body)+']')

              ########################################
              ####         PATYS OBJEKTAI         ####

class ParseObject():
    '''Universalus objektas parsinime.'''
    def __init__(self,tipas):
        self.body=''                      # skriptinio pavidalo kunas
        self.Type=tipas

class FruitfullObject(ParseObject):
    '''Objektas turintis vidine struktura, sudaryta
    is kitu objektu. Jis taip pat savyje turi opening
    ir closing objektus.'''
    def __init__(self,tipas):
        super().__init__(tipas)
        self.kids=[]             # vidine struktura
        # butinas atidarantis reiskinys
        self.opening=Opening('PRADZIA','PRADZIA','PRADZIA')
        self.closing=Closing('PRADZIA','PRADZIA','PRADZIA')
        self.address=[]
    def show_self(self):
        print('  '*len(self.address),end='')
        self.opening.show_self()
        print('  '*len(self.address),end='')
        print('[stack:'+str([i['opening'] for i in self.stack])+']')
        for i in self.kids:
            i.show_self()
        print('  '*len(self.address),end='')
        self.closing.show_self()

class Block(ParseObject):
        def __init__(self,tipas):
                super().__init__(tipas)
                self.kids=[]
                self.opening=Opening('PRADZIA','PRADZIA','PRADZIA')
                self.closing=Closing('PRADZIA','PRADZIA','PRADZIA')
                self.address=[]

class SimpleStructure(ParseObject):
    def __init__(self,tipas):
        super().__init__(tipas)
        self.fulltext=''
        self.address=[]
    def show_self(self):
        print('  '*len(self.address),end='')
        print('['+self.Type+':'+repr(self.fulltext)+']')

class Command(ParseObject):
    '''Komanda su argumentais.
    syntax--sintakse kurioje inicializuota komanda
    name--komandos scriptine reprezentacija'''
    def __init__(self,tipas,name,syntax,address):
        self.Type=tipas
        self.name=name
        self.syntax=syntax
        self.address=address
        self.args=[]
    def show_self(self):
        print('  '*len(self.address),end='')
        print(self.name,'<--Komanda:',self.Type)
        for i,arg in enumerate(self.args):
            print('  '*len(self.address),end='')
            print('♣'+'-'*10,str(i+1)+'-as argumentas')
            arg.show_self()
            print('  '*len(self.address),end='')
            print('♣'+'-'*20)

              ########################################
              ####   IPRASTI METODAI NAUDOJAMI    ####
              ##         PARSINIMO PROCESE          ##

def escaped(poz,String,syntax='T'):
    '''Patikriname ar esamas charas
    nera escapintas.
    Parasyta, numatant escape charo
    sintakses pasikeitimo galimybe.'''
    # DEBUGING :: jei syntakseje neapibreztas escape charas
    try:
        ESC_CH=latexsyntax.SYNTAX[syntax]['escape']
    except KeyError:
        return False
    # :::
    if poz==0: return False
    if not (String[poz-1] in ESC_CH.keys()):
        return False
    # DEBUGING :: PATIKRINAME AR NEBUVO SINTAKSES KEITIMO
    elif ESC_CH[String[poz-1]]:
        raise AlgError(
            "Pakeista escape charu sintakse "\
            "ir nenurodytas elgsenos tipas!!!:"\
            "\n{}\nEscape charu sarasas"\
            ":\n{}".format(context(poz-1,String),
                           ESC_CH),poz-1)
    # :::
    else:
        # suskaiciuojam kiek yra
        # vienas po kito einanciu backslashu
        # pries esama chara
        slashes=0
        i=poz-1
        while (String[i] in ESC_CH.keys()):
            slashes+=1
            if i==0: break
            i-=1
        if not slashes%2:return False
        else: return True

def metachar(poz,String,syntax='T'):
    '''Jei charas yra metacharu sarase,
    tai patikrinam ar jis neeskeipintas.'''
    META_CH=latexsyntax.SYNTAX[syntax]['metach']
    keys=META_CH.keys()
    # print("\nmetacharai:",META_CH,'\nsymbolis:',String[poz])
    if not (String[poz] in keys):
        return False
    if poz==0:
        return True
    if escaped(poz,String,syntax):
        return False
    else: return True

def metachar_greedy(poz,String):
    '''Jei esamas charas nera metacharas
    ismeta parsingo errora.

    Naudoti ten kur butinai reikalingas metachar'''
    if metachar(poz,String): return True
    else:
        raise AlgError(
            'Sis simbolis nera metacharas:'\
            '\n{}'.format(context(poz,String)),poz)

def EOS(poz,String):
    '''Tikrinama ar esamas charas
    nera eilutes pabaiga.'''
    return poz>=len(String)-1

def skip_whitespace(poz,String,WHITES=latexsyntax.WHITESPACE):
    '''Praleidziam visus whitespace, kurie
    yra ne newline.
    Grazinamas whitespacu sekos ilgis.'''
    # DEBUGING :::
    if (not (String[poz] in WHITES)) or escaped(poz,String):
        raise AlgError(
            'Tai nera whitespaceas:"\
            "\n{}'.format(context(poz,String)),poz)
    # :::
    i=poz
    while String[i] in WHITES:
        if EOS(i,String):
            # paliekam viena whitespace
            # kitoms funkcijoms
            return i-poz
        i+=1
    return i-poz

              ########################################
              ####   INLINE KOMENTARU SURINKIMO   ####
              ##            MECHANIZMAS             ##

def is_start_of_comment(i,String,syntax):
    '''Patikriname ar esamas charas yra
    inline komentaro pradzia. Jei taip grazina:
    (chara kuris isjungs komentara, opciju rinkini).
    Opciju rinkinys yra reikalingas tam, nes galima
    perapibrezti komentara taip, kad sutikus isjungiamaji
    symboli, nebus surinkti sekantys whitespace.
    Taigi, raide 'w' nurodo, kad reikes surinkti whitespace.'''
    COMMENT=latexsyntax.SYNTAX[syntax]['icomment']
    if (String[i] in COMMENT.keys()) and metachar(i,String):
        return COMMENT[String[i]]
    else: return False

def skip_icomment(poz,String,syntax):
    '''Nuskaitomas komentaras ir grazinamas jo ilgis.
    Skaitoma tada, kai komentaro jungiklis yra metachar'''
    COMMENT=latexsyntax.SYNTAX[syntax]['icomment']
    if is_start_of_comment(poz,String,syntax):
        cstart=String[poz]
        cend=is_start_of_comment(poz,String,syntax)[0]
        cprop=is_start_of_comment(poz,String,syntax)[1]
    else:
        raise AlgError('Tai nera komentaro "\
          "jungiklis!:\n{}'.format(context(poz,String)),poz)
    MULTILINE=True
    i=poz
    while MULTILINE:
        while String[i]!=cend:
            # jei komentaras uzbaigtu faila
            if EOS(i,String):
                raise EOSError(
                    "Komentaras uzbaigia teksta.\n"\
                    "Tikriausiai buvo ieskoma komandos argumento."\
                    "Kitiems atvejams skip_comment naudoti, su try!!!\n"\
                    "{}".format(context(i,String)),i)
            i+=1
        i+=1
        if String[i]==cstart: continue
        # Jei isjungigklis surenka visus trailing whitespace
        elif ('w' in cprop) and  (String[i] in latexsyntax.WHITESPACE):
                i+=skip_whitespace(i,String)
                # jei paskutinis white charas buvo string pabaiga
                if EOS(i,String):
                    raise EOSError(
                    "Whitespace seka uzbaigia teksta.\n"\
                    "Tikriausiai buvo ieskoma komandos argumento."\
                    "Kitiems atvejams skip_comment naudoti, su try!!!"
                    "\n{}".format(context(i,String)),i)
                # SURENKAMA KOMENTARU SEKA
                if String[i]==cstart: continue
                else:
                    return i-poz
        else: return i-poz

                #################################################
                ######    KELIONE IKI KOMANDOS ARGUMENTO ########
                #### Preliudija i komandu surinkimus         ####
                #### taciau pirma bus surenkami enviromentu  ####
                #### pavadinimai                             ####

def is_start_of_cmd(poz,String,syntax='T'):
    '''Patikrinama ar esamas charas yra komandos pradzia.'''
    START_OF_CMD=latexsyntax.SYNTAX[syntax]['cmd_start']
    COMMAND_CHARS=latexsyntax.SYNTAX[syntax]['cmd_chars']
    if not (String[poz] in START_OF_CMD.keys()):
        return False
    else:
        if metachar(poz,String): return True
        else: return False

def skip_command_name(poz,String,syntax='T'):
    '''Padavus esama aktyvu chara ir jo pozicija
    grazinamas komandos pavadinimo ilgis.'''
    START_OF_CMD=latexsyntax.SYNTAX[syntax]['cmd_start']
    COMMAND_CHARS=latexsyntax.SYNTAX[syntax]['cmd_chars']
    # patikriname ar esamas charas yra komandos
    # pradzios metacharas
    char=String[poz]
    if not is_start_of_cmd(poz,String):
        raise AlgError("Tai nera komanda aktyvuojantis simbolis:"\
                       "\n{}".format(context(i,String)),poz)

    if START_OF_CMD[char]:
        raise AlgError(
                      "Pakeista komandos aktyvavimo sintakse "\
                      "ir nenumatyta elgsena!!!:"\
                      "\n{}Komanda aktyvuojanciu charu sarasas"\
                      ":\n{}".format(context(poz,String),
                                      START_OF_CMD),poz)
    # Jei netycia parsinama eilute uzsibaigtu
    # komanda aktyvuojanciu symboliu
    if EOS(poz,String):
        raise ParseError(
            'Parsinama eilute baigiasi ten kur turetu prasideti'\
            'komandos pradzia:\n{}'.format(context(poz,String)),poz)
    # jei komanda susideda is simbolio
    if not (String[poz+1] in COMMAND_CHARS-{'*'}):
        return 2
    i=poz+1
    while String[i] in COMMAND_CHARS:
        if EOS(i,String):
            # jei netycia komanda uzbaigtu parsinama stringa
            raise EOSError("Renkant komanda buvo pasiektas teksto  "\
                           "galas.\nPries parsinant gale "\
                           "idekite papildoma newline, arba naudokite"\
                           "try:\n".format(context(i,String),i))
        i+=1
    return i-poz

def is_strict_switch(poz,String,syntax='T'):
    '''Patikrina ar esamas reiskinys yra atidarantis
    grieztas switchas. Jei taip grazina jo ilgi.'''
    switches=latexsyntax.SYNTAX[syntax]['switches'].keys()
    k=skip_command_name(poz,String,syntax)
    if String[poz:poz+k] in switches:
       return k
    else: return False

def skip_till_argument(poz,String,syntax='T'):
    '''Praleidzia visus, nereiksmingus
    charus iki sekancio argumento.
    Tarp komandos ir argumento galimi tik
    iprastiniai komentarai % ir whitespacai.
    Taip pat, dar neprasidejus komentarui
    yra galimas 1-as newline.'''
    BEGIN_OF_ARG=latexsyntax.SYNTAX[syntax]['arg_beg']
    i=poz
    if String[poz] in BEGIN_OF_ARG:
        return 0
    if String[i] in latexsyntax.WHITESPACE:
        i+=skip_whitespace(i,String)
    # po komandos su whitespace galimas tik vienas newline
    if String[i]=='\n':
        i+=1
    while not (String[i] in BEGIN_OF_ARG):
        if is_start_of_comment(i,String,syntax):
            i+=skip_icomment(i,String,syntax)
        elif String[i] in latexsyntax.WHITESPACE:
            i+=skip_whitespace(i,String)
        else: raise AlgError(
                "Nenumatytas charas tarp argumentu:\n"\
                "{}".format(context(i,String)),i)
        if EOS(i,String):
            raise EOSError(
                "Parsinamas tekstas baigiasi "\
                "komanda, kuri turi tureti argumenta:"\
                "\n{}".format(context(i,String)),i)
    return i-poz

def is_start_of_env(poz,String,syntax='T'):
    '''Patikrinama ar esama komanda yra env
    pradza'''
    i=poz
    ENV_SWITCH=latexsyntax.SYNTAX[syntax]['env_switch']
    k=skip_command_name(i,String)
    if (String[i:i+k] in ENV_SWITCH.keys()):
        return True
    else:
        return False

def is_end_of_env(poz,String,syntax='T'):
    '''Patikrinama ar esama komanda yra env
    pabaiga'''
    i=poz
    ENV_SWITCH=latexsyntax.SYNTAX[syntax]['env_switch']
    k=skip_command_name(i,String)
    if (String[i:i+k] in ENV_SWITCH.values()):
        return True
    else:
        return False

def collect_enviroment_name(poz,String,syntax='T'):
    '''Surenkamas ir grazinamas enviromento
    pavadinimas. Grazinama:
      (ilgis nuo switch pabaigos iki arg pabaigos,
      env_pavadinimas).'''
    ENV_SWITCH=latexsyntax.SYNTAX[syntax]['env_switch']
    METABRACES=latexsyntax.SYNTAX[syntax]['mbraces']
    COMMENT=latexsyntax.SYNTAX[syntax]['icomment']
    if not is_start_of_cmd(poz,String):
        raise AlgError("Cia ne enviromento pradzia--"\
                       "net ne komandos pradzia\n"\
                       "{}".format(context(poz,String)),i)
    i=poz
    k=skip_command_name(i,String)
    if not ((String[i:i+k] in ENV_SWITCH.keys())\
        or (String[i:i+k] in ENV_SWITCH.values())):
        raise AlgError("Cia ne enviromento pradzia"\
                       "{}".format(context(poz,String)),i)
    i+=k
    k=skip_till_argument(i,String)
    if not (String[i+k] in METABRACES.keys()):
        raise AlgError(
            "Envromento pavadinimas turi "\
            "buti apskliausti metaskliaustais!!!\n"\
            "{}".format(context(i,String)),i)
    i+=k
    left=String[i]
    right=METABRACES[String[i]][0]
    braces=[1,0]
    i+=1
    arg=''
    while braces[0]!=braces[1]:
        if String[i]==left:
                braces[0]+=1; i+=1
                continue
        elif String[i]==right:
            braces[1]+=1; i+=1
            continue
        elif is_start_of_comment(i,String,syntax):
             k=skip_comment(i,String,syntax)
             i+=k
             continue
        arg+=String[i]
        i+=1
    return i-poz, arg

              ########################################
              ####  APLINKU UZSIDARYMO TIKRINIMO  ####
              ##            MECHANIZMAI             ##
              #    Aptikus, nauja aplinka, reikia    #
              # nustatyti, jos uzsidarymo mechanizma #

def check_matching_env(poz,String,syntax,opening):
    '''Tikrinama ar esamas reiskinys, yra
    enviromento uzdarymas. Opening -- nurodomas
    enviromento pavadinimas.'''
    if not is_start_of_cmd(poz,String,syntax):
        return False
    if is_end_of_env(poz,String,syntax):
        if collect_enviroment_name(poz,String,syntax)[1]!=opening:
            return False
        else:
            return collect_enviroment_name(poz,String,syntax)[0]

def check_matching_switch(poz,String,syntax,switch):
    '''Tikrina ar esamas reiskinys yra griezto switcho
    uzdarymas.'''
    METACH=latexsyntax.SYNTAX[syntax]['metach']
    closing=latexsyntax.SYNTAX[syntax]['switches'][switch]['closing']
    if not is_start_of_cmd(poz,String,syntax):
        return False
    else:
        k=skip_command_name(poz,String,syntax)
        if String[poz:poz+k]==closing:
            return k
        else: return False

def check_matching_delim(poz,String,syntax='T',opening='{'):
    '''Tikrina ar esmas charas yra uzdarantis esamo
    objekto parsinima vienazenklis skirtukas.'''
    # DEBUGINIMUI :: istrinti po to, kai bus pilnai pratestuotas
    openings=latexsyntax.SYNTAX[syntax]['delims'].keys()
    if not (opening in openings):
        raise AlgError("Syntakseje \'{}\' neapibreztas"\
                       "skirtukas \'{}\'!\n Kontextas:\n"\
                       "{}".format(syntax,opening,context(poz,String)),poz)

    # :::
    closing=latexsyntax.SYNTAX[syntax]['delims'][opening]['closing']
    if String[poz]!=closing:
        return False
    # Jei esamas charas atitinka uzdarancio symbolio apibrezima
    # dar patikrinamos, kitos butinos savybes
    properties=latexsyntax.SYNTAX[syntax]['delims'][opening]['properties']
    if properties:
        if 'meta' in properties:
            # PROBLEMA: \\end{verbatim}
            #       antras \ nesiskaito eskeipintas
            #       ir ji reiktu traktuoti, kaip metachar
            if metachar(poz,String,syntax):
                return 1
            else:
                return False
    # DEBUGINIMUI ::
    if escaped(poz,String,syntax):
        raise AlgError("Sis charas turejo buti surinktas "\
                       "kaip komanda:\n{}".format(context(poz,String)),
                       poz)
    # :::
    return True

def check_if_multichar(poz,String,syntax):
    '''Kai kurie aktyvus symboliai, gali sudaryti
    kombinacijas, pakeiciancias ju prasme. Butina tai
    pagauti is anksto!
    pvz.: $-->$$.'''
    if EOS(poz,String):
        raise ParseError("Esamas aktyvus charas uzbaigia parsinama eilute:"\
                         "\n{}".format(context(poz,String)),poz)
    char=String[poz]
    MULTICHAR=latexsyntax.SYNTAX[syntax]['delims'][char]['multichar']
    if String[poz:poz+2] in MULTICHAR:
        return String[poz:poz+2]
    else:
        return False

def check_matching_multichar_delim(poz,String,syntax,opening):
    '''Sutikus  skirtuka, ar komanda, kuris turi opcija 'rpt'
    (si opcija, reiskia, jog galimas ilgesnis  reiskinys,
    turintis kirtinga prasme), tikrinama, ar tai nera tas
    ilgesnis reiskinys.
    Pvz: sutikus $, tikrinama ar ne $$'''
    MULTICHAR_DELIMS=latexsyntax.SYNTAX[syntax]['mch_delims']
    closing=MULTICHAR_DELIMS[opening]['closing']
    properties=MULTICHAR_DELIMS[opening]['properties']
    if properties:
        if 'meta' in properties:
            if not metachar(poz,String,syntax):
                return False
    if String[poz]!=closing[0]:
        return False
    else:
        if String[poz:poz+len(closing)]==closing:
            return len(closing)

def identify_opening(opening,syntax='T'):
    '''Parenka parsinamo reiskinio
    uzdarymo mechanizma atpazystanti metoda.
    Grazina funkcija, kuria bus tikrinama.
    Parenkama funkcija grazina:
    (a) uzdarancio reiskinio ilgi
    (b) spec zinute, jeigu tokia yra'''
    DELIMS=latexsyntax.SYNTAX[syntax]['delims']
    MCH_DELIMS=latexsyntax.SYNTAX[syntax]['mch_delims']
    SWITCHES=latexsyntax.SYNTAX[syntax]['switches']
    ENVIROMENTS=latexsyntax.SYNTAX[syntax]['enviroments']
    # Blokas: tabuliaro skirtukas (\\) row skirtukas & item skirtukas \\item
    BLOCKS=''
    if opening in DELIMS.keys():
        return lambda poz, String:\
           check_matching_delim(poz,String,syntax,opening), 'delimeter'
    if opening in MCH_DELIMS.keys():
        return lambda poz, String:\
           check_matching_multichar_delim(poz,String,syntax,opening), 'multichar_delimeter'
    elif opening in ENVIROMENTS.keys():
        return lambda poz, String:\
           check_matching_env(poz,String,syntax,opening), 'enviroment'
    elif opening in SWITCHES.keys():
        return lambda poz, String:\
           check_matching_switch(poz,String,syntax,opening), 'switch'
    else:
        raise AlgError("Reiskinys, kurio uzdarymo ieskoma "\
             "yra neapibreztas."
             "\n{}".format(opening),0)

              ########################################
              ####  PAPRASTOS STRUKTUROS OBJEKTU  ####
              ##       SURINKIMO  MECHANIZMAI       ##

def skip_text(poz,String,syntax):
    '''Surenkamas visas tekstas, kuris
    nera aktyvuotas aktyviais simboliais.'''
    i=poz
    while not metachar(i,String,syntax):
        if EOS(i,String):
            break
        i+=1
    return i-poz

def parse_icomment(poz,String,syntax):
    "inicializuoja komentara"
    k=skip_icomment(poz,String,syntax)
    return k

              ########################################
              ####            KOMANDOS            ####
              ##       SURINKIMO  MECHANIZMAI       ##

def collect_argument(poz,String,syntax,address,new_stack):
    '''Surenka argumenta priklausomai nuo to,
    koks jo tipas. Sis metodas pats atpazysta argumento tipa,
    istirdamas pirmaji argumento symboli.
    Grazina argumento objekta ir jo ilgi.'''
    print("Pradedamas surinkineti argumentas")
    print("Esamas charas",String[poz])
    print("Argumentui priskiriamas adresas",address)
    # symboliai, kurie gali buti argumento pradzios
    arg_beg=latexsyntax.SYNTAX[syntax]['arg_beg']
    if not (String[poz] in arg_beg):
        raise ParseError("Cia turetu buti argumento pradzia, "\
                         "taciau symbolis neatitinka argumento"\
                         "pradzios apibrezimo:{}\n"\
                         "{}".format(arg_beg,context(poz,String)),poz)
    braces=latexsyntax.SYNTAX[syntax]['mbraces']
    if String[poz] in braces.keys():
        print("Sis argumentas turi vidine struktura")
        Object, lenght=parse_wraped(poz,String,syntax,String[poz],1,
                                    address,new_stack)
        Object.Type='arg_complex'
        return Object, lenght
    cmd_start=latexsyntax.SYNTAX[syntax]['cmd_start']
    if String[poz] in cmd_start.keys():
        print("Sis argumentas yra komandos tipo")
        Argumentas, lenght=collect_command(poz,String,syntax,address,new_stack)
        Argumentas.body=String[poz:poz+lenght]
        Argumentas.Type='arg_cmd'
        return Argumentas, lenght
    else:
        print("Sis argumentas yra tiesiog symbolis")
        Argumentas=ParseObject('symbol')
        Argumentas.body=String[poz]
        Argumentas.address=new_address
        Argumentas.Type='arg_symb'
        return Argumentas, 1

def collect_optional_argument(poz,String,syntax):
    '''Surenka opcionalu argumenta.
    Grazina paprastos strukturos objekta.'''
    delims=latexsyntax.SYNTAX[syntax]['odelims']
    if not String[poz] in delims.keys():
        raise AlgError("Esamas symbolis nera opcionalaus"\
                       "argumento pradzia:"\
                       "\n{}".format(context(poz,String)),poz)
    left=String[poz]
    right=delims[String[poz]]
    braces=[1,0]
    i=poz+1
    while braces[0]!=braces[1]:
        if String[i]==left: braces[0]+=1
        elif String[i]==right: braces[1]+=1
        if  EOS(i,String):
            raise MatchError(
                'Nerasta skliausto pora!:\n{}'.format(
                context(poz,String)),poz)
        i+=1
    Opcionalus_argumentas=SimpleStructure('opt_arg')
    Opcionalus_argumentas.fulltext=String[poz:i]
    return Opcionalus_argumentas, i-poz

oarg, ilg=collect_optional_argument(1,' [aaaa[aaaaaa]aaaaa]   ','T')

def skip_braced(poz,String,
                meta=True,
                verb=False,
                COMMENT_SYNTAX=latexsyntax.COMMENT,
                METACHARACTERS=latexsyntax.METACHARACTERS):
        '''Grazina apskliausto reiskinio ilgi.
        Jei meta=True, tai renka tik aktyvius skliaustus,
        jei ne tai ieskos esamo skliausto poros.

        Jei verb==True, tai is sintakses bus trumpam ismesti
        komentaro charai ir tarp skliaustu esancius % traktuos
        kaip simbolius.'''
        if len(COMMENT_SYNTAX)!=1:
            raise AlgError(
                "Komentaro sintakses apibrezime yra daugiau"\
                "negu vienas simbolis:\n"\
                "{}\n{}".format(COMMENT_SYNTAX,context(i,String)),i)
        COMMENT_SYNTAX=latexsyntax.COMMENT
        if meta:
            DELIMETERS=latexsyntax.ARG_DELIMS
        else:
            DELIMETERS=latexsyntax.BRACES
        # jei apskliaustas reiskinys yra
        # verbatimine aplinka, ir procento zenklas nereiskia
        # komentaro pradzios
        if verb:
            del COMMENT_SYNTAX['%']
        i=poz
        char=String[poz]
        if (char in latexsyntax.DELIMETERS.keys()) and metachar(poz,String):
            left=String[poz]
            right=latexsyntax.ARG_DELIMS[left]
        else:
            raise AlgError("Tai nera argumento skirtukas:"\
                           "\n{}".format(context(i,String)),i)
        if EOS(i,String):
            raise EOSError(
                "Tekstas baigiasi, ten kur "\
                "turetu buti skliaudziamas argumentas!".format(
                    context(i,String)),i)
        i+=1
        braces=[1,0]
        while not braces[0]==braces[1]:
            if String[i] in COMMENT_SYNTAX.keys() and metachar(i,String):
                try:
                    i+=skip_comment(i,String)
                except EOSError:
                    raise MatchError(
                        'Nerasta skliausto pora!:\n{}'.format(
                            context(poz,String)),poz)
            if (String[i] in (left+right)) and metachar(i,String):
                if String[i]==left:
                    braces[0]+=1
                elif String[i]==right:
                    braces[1]+=1
            if braces[0]==braces[1]: break
            if  EOS(i,String):
                raise MatchError(
                    'Nerasta skliausto pora!:\n{}'.format(
                        context(poz,String)),poz)
            i+=1
        return i-poz+1

def collect_command(poz,String,syntax,address,new_stack):
    '''Surenka komanda, su jos argumentais, jei komandos
    argumentas yra verb tipo tai netikriname, komentaru buvimo
    ir pasiimame iki uzdarancio skliausto.
    Grazinamas komandos tipo objektas!'''
    print("\n\nPradedu komandos surinkima")
    argument_nr=0
    i=poz
    ilg=skip_command_name(poz,String,syntax)
    Komandos_pav=String[i:i+ilg]
    commands=latexsyntax.SYNTAX[syntax]['commands']
    pattern=commands[Komandos_pav]['pattern']
    Type=commands[Komandos_pav]['type']
    i+=ilg
    print('\n\n\n>>>Pradedu_komandos_su_zinomu_paternu_surinkima')
    print("KOMANDA:",Komandos_pav)
    print("ESAMA_POZICIJA:", context(i,String))
    print("Paternas:",pattern)
    print("Sios komandos adresas",address)
    # susirenkam zvaigzdute
    # ji atsiskiria nuo komandos kaip ir argumentas
    if Komandos_pav[-1:]!='*':
        print("ieskom zvaigzdutes")
        ilg=skip_till_argument(i,String)
        print("Tiriam:",context(i,String))
        if String[i+ilg]=='*':
            Komandos_pav=Komandos_pav+'*'
            i+=ilg+1
            print("surinkau komanda su zvaigzdute\n"\
            "dabartine mano pozicija:{}".format(
                context(i,String)))
            print("KOMANDA_SU_ZV:",Komandos_pav)
        else:
            pass
    # Inicijuojamas komandos tipo objektas
    command=Command(Type,Komandos_pav,syntax,address)
    print("Pradedu rinkti argumentus:\n",context(i,String))
    print("Komandos_Paternas:",pattern)
    if not pattern:
        args=None
    else:
        print("Si komanda turi paterna!!!")
        print("ESAME:",context(i,String))
        for nr,k in enumerate(pattern):
            # jei argumentas pagrindinis
            # 1 ir didzioji raide reprezentuoja pagrindini argumenta
            if  (type(k)==int and k==1) or (type(k)==str and  k.isupper()):
                # jei argumento syntakse nenurodyta
                if type(k)==int:
                    inner_syntax=syntax
                else:
                    inner_syntax=k
                print("ieskom pagrindinio argumento:\n",
                      context(i,String))
                ilg=skip_till_argument(i,String,syntax)
                i+=ilg
                print("pagrindinio argumento pradzia:\n",
                      context(i,String))
                arg_address=address+[argument_nr]
                argument_nr+=1
                print("Pagrindiniam argumentui perduodamas adresas:",
                      arg_address)
                argument, lenght=collect_argument(i,String,inner_syntax,
                                                  arg_address,new_stack)
                argument.address.append(arg_address)
                argument.lenght=lenght
                command.args.append(argument)
                i+=lenght
            # jei argumentas opcionalus
            else:
                print("Pradedamas surinkineti opcionalus argumentas")
                odelims=latexsyntax.SYNTAX[syntax]['odelims']
                ilg=skip_till_argument(i,String)
                if String[i+ilg] in odelims.keys():
                    print("Rastas opcionalus argumentas")
                    print("opcionalus:",context(i,String))
                    arg_address=address+[argument_nr]
                    argument_nr+=1
                    argument, lenght=collect_optional_argument(i,String,syntax)
                    argument.address.append(arg_address)
                    argument.lenght=lenght
                    command.args.append(argument)
                    i+=lenght
                else:
                    pass
    print("Komanda baigta parsinti taske:\n",context(i,String))
    command.fulltext=String[poz:i]
    return command, i-poz

           ###############################################
             ######       PARSINIMO PROCESAS      #####
                ####################################
                    ############################

              ########################################
              ####  PARSINIMO METODAI IR JU TIPAI ####
              #   Kiekvienoje syntakseje, aktyvus    #
              #    symboliai siejasi su metodais,    #
              #   Kiekvienas metodas turi savo tipa, #
              # i kuri atsizvelgus iskvieciamas atit-#
              # kamas algoritmas ir sukuriamas ati-  #
              # tinkamas objektas                    #

METHODS={
    # metodus sarase yra irasyti triju tipu objektai
    # simple_strc -- do_the_right_thing aptikes toki
    #       objekta, panaudoja metoda tokiam objektui
    #       surinkti
    'icomment':{
        'parse_type':'simple_str',
        'type':'comment',
        'method':parse_icomment
        },
    # wraped_up -- objektai reikalaujantys gilesnio parsinimo
    # ir turintys vienokius ar kitokius skirtukus
    'mbraces':{
        'parse_type':'inner_parse',
        'opening':'{',
        'syntax':'O',   # O reiskia isorine sintakse
        'type':'braced'
        },
    'math':{
        'parse_type':'inner_parse',
        'syntax':'M',
        'opening':'multichar',
        'type':'math'
        },
    'switch':{
        'parse_type':'inner_parse'
        },
    'tcommand':{
        'parse_type':'command'},
    'mcommand':{
        'parse_type':'command'},
    # verbatimo aplinkose komandos surenkamos kaip tekstiniai
    # elementai
    'vcommand':{
        'parse_type':'vcommand'}}

def parse(String, syntax='T', checking=None, address=[],stack=[]):
    '''Grazinama:
    1) =parse objektas=,
    2)=objekto ilgis=.
    3) =objekta uzdarancio skirtuko ilgis=
    4)=Spec zinute kuri bus interpretuojama isoriniame lygmenyje='''
    ParseObject=FruitfullObject('MAIN')
    ParseObject.stack=stack
    # jei esamas reiskinys yra gilesnis
    print('\n\n>>>',address,"ISIJUNGIA PARSINIMO MECHANIZMAS")
    print('>>>VIDINE_SYNTAKSE:',syntax)
    if checking:
        checkas=checking
    else:
        checkas=lambda x,y: False
    elem=0
    i=0
    while True:
        # Patikrinama ar esamas symbolis nera skriptinio teksto pabaiga
        if EOS(i,String):
            ParseObject.fulltext=String
            print("****PARSINIMO PABAIGA****",address)
            return ParseObject
        try:
            if checkas(i,String):
                # grazinamas objektas,
                # jo skriptinis ilgis
                # ji uzdarancio reiskinio ilgis
                #
                return ParseObject, i, checkas(i,String)
            else:
                # address -- esamo objekto adresas
                # ParseObject -- sio parsinimo metu kuriamas objektas
                #    jo lipdymas slepiasi funkcijoje do_the_right_thing
                # elem -- vidinio reiskinio numeris, naudojamas nauju adresu
                #    kurimui
                # checking -- esamos grupes uzbaigimo tikrinimo mechanizmas
                k, message=do_the_right_thing(i,String,syntax,ParseObject,
                                     address,elem,checking,stack)
                elem+=1
                i+=k
        except EOSError:
            print("Pasibaige nebaigus")

def do_the_right_thing(poz,String,syntax,Father,address,elem,
                       checking,old_stack):
    '''Jei esamas charas yra metacharas,
    apibreztoje syntakseje, kreipiasi i kita
    algoritma, kuris priklausomai nuo esamo,
    konteksto ir metacharui priskirtos reiksmes
    grazina parsinimo metoda, tipa.

    Inicializuojant nauja elementa turi buti perduodamas
    tevelio adresas, kad ji butu galima ijungti i jo vidine struktura'''
    print("DO_THE_RIGHT_THING:",'>>'+String[poz]+'<<')
    print("Isorinis addresas",address)
    print("Sis elementas isoriniame reiskinyje yra",elem)
    new_address=address+[elem]
    # sukuriamas tuscias stack elementas
    # kuriame bus saugojami tikrinimo mechanizmai
    new_stack=list(old_stack)
    print("Sukurtas naujas adresas",new_address)
    METACHARS=latexsyntax.SYNTAX[syntax]['metach']
    # jei esamas symbolis yra metacharas esamoje syntakseje
    if metachar(poz,String,syntax):
        char=String[poz]
        # istraukiamas metodo pavadinimas susijes su metacharu
        method=latexsyntax.SYNTAX[syntax]['metach'][char]
        print("Su charu sisijes metodas",method)
        # is metodo istraukiamas busimo objekto parsinimo tipas
        parse_type=METHODS[method]['parse_type']
        ##############################
        # jei esamas metacharas yra skirtukas
        ##############################
        if parse_type=='inner_parse':
            print("Esamas metacharas yra skirtukas")
            opening=METHODS[method]['opening']
            # jei atidarantis reiskinys turi ir kitokiu kombinaciuju
            if opening=='multichar':
                if check_if_multichar(poz,String,syntax):
                    delim=check_if_multichar(poz,String,syntax)
                    print("sis skirtukas yra symboliu kombinacija", delim)
                else:
                    print("sis skirtukas yra vieno symbolio")
                    delim=String[poz]
            else: delim=String[poz]
            # Nustatome syntakse
            inner_syntax=METHODS[method]['syntax']
            # jei vidine syntakse lygi isorinei
            if inner_syntax == 'O':
                inner_syntax=syntax
            # ISKVIEVIAMAS METODAS PARSINANTIS ISSKIRTA REISKINI,
            # PERDUODAMAS ISORINIO REISKINIO ADRESAS,
            # ATIDARANCIO SKIRTUKO ILGIS
            # VIDINIO REISKINIO NUMATOMA SINTAKSE
            Object, lenght=parse_wraped(poz,String,inner_syntax,delim,
                                        len(delim),new_address,new_stack)
            Father.kids.append(Object)
            return lenght, None

        ##############################
        # jei esamas metacharas reiskia komandos pradzia
        ##############################
        elif parse_type=='command':
            ####################
            ## jei esama komanda yra grieztas switchas
            if is_strict_switch(poz,String,syntax):
                print("Esamas metacharas yra switchas")
                k=is_strict_switch(poz,String,syntax)
                switch=String[poz:poz+k]
                inner_syntax=latexsyntax.SYNTAX[syntax]['switches']\
                  [switch]['content']
                if inner_syntax == 'O':
                    inner_syntax=syntax
                Object, lenght=parse_wraped(poz,String,inner_syntax,switch,
                                    len(switch),new_address,new_stack)
                Father.kids.append(Object)
                return lenght, None

            ####################
            ## jei esama komanda yra enviromento pradzia
            elif is_start_of_env(poz,String,syntax):
                print("Esamas metacharas yra enviromento pradzia")
                lenght, env_name=collect_enviroment_name(poz,String,syntax)
                opening=String[poz:poz+lenght]
                inner_syntax=latexsyntax.SYNTAX[syntax]['enviroments']\
                  [env_name]['content']
                if inner_syntax == 'O':
                    inner_syntax=syntax
                Object, lenght=parse_wraped(poz,String,inner_syntax,env_name,
                                    lenght,new_address,new_stack)
                Object.opening.formated='\\begin{'+env_name+'}'
                Object.closing.formated='\\end{'+env_name+'}'
                Father.kids.append(Object)
                return lenght, None

            ####################
            ## jei tai nei enviromento nei switch tipo komanda
            else:
                # TODO: SUKISTI VISKA I COLLECT_COMMAND METODA
                print("Esamas metacharas yra komandos pradzia")
                k=skip_command_name(poz,String,syntax)
                commands=latexsyntax.SYNTAX[syntax]['commands']
                command=String[poz:poz+k]
                # jei tai zinoma komanda
                if command in commands.keys():
                    print("Si komanda yra aprasyta syntakseje")
                    pattern=commands[command]['pattern']
                    Type=commands[command]['type']
                    print("perduodamas_adresas:",new_address)
                    Object,lenght=collect_command(poz,String,syntax,
                                                  new_address,new_stack)
                    Father.kids.append(Object)
                    return lenght, None

                # jei tai nezinoma komanda, surenkamas jos
                # skriptinis pavadinimas ir inicializuojama
                # nezinoma komanda
                else:
                    print("Si komanda yra nezinoma")
                    Object=Command('unknown',String[poz:poz+k],
                                   syntax,new_address)
                    Object.body=String[poz:poz+k]
                    Object.lenght=k
                    print("Sios komandos kunas:",Object.body)
                    Father.kids.append(Object)
                    return k, None

        elif parse_type=='vcommand':
            print("Radau komanda verbatimineje aplinkoje!")
            k=skip_command_name(poz,String,syntax)
            print("Jos ilgis",k)
            command=String[poz:poz+k]
            print("Komanda:",command)
            Object=SimpleStructure("verbatim_text")
            Object.fulltext=String[poz:poz+k]
            Object.lenght=k
            Object.address=new_address
            Father.kids.append(Object)
            return k, None
        ##############################
        ### jei tai struktura, kurios turinys paprastai surenkamas
        elif parse_type=='simple_str':
            Method=METHODS[method]['method']
            Type=METHODS[method]['type']
            k=Method(poz,String,syntax)
            Object=SimpleStructure(Type)
            Object.fulltext=String[poz:poz+k]
            Object.lenght=k
            Object.address=new_address
            print("SUKURTAS PAPRASTOS STRUKTUROS OBJEKTAS:",
                  '>>'+Object.body+'<<')
            Father.kids.append(Object)
            return Object.lenght, None
    else:
        k=skip_text(poz,String,syntax)
        Object=SimpleStructure("text")
        Object.fulltext=String[poz:poz+k]
        Object.lenght=k
        Object.address=new_address
        Father.kids.append(Object)
        print("SUKURTAS TEKSTO OBJEKTAS:",'>>'+Object.body+'<<')
        return Object.lenght, None

def parse_wraped(poz,String,syntax,opening,len,address,new_stack):
    '''Metodas suparsinantis isskirta reiskini.
    Jam inicializuoti perduodamas atidarantis reiskinys
    Grazinamas objektas su visa vidine struktursada ir jo ilgis!'''
    print("\nParsinu_apgaubta:",context(poz,String))
    print("Atidarantis_reiskinys:",opening)
    print("Naujo_elemento_adresas:",address)
    Tikrinimo_mechanizmas, skirtuko_tipas = identify_opening(opening, syntax)
    new_stack.append({
            'function':Tikrinimo_mechanizmas,
            'type':skirtuko_tipas,
            'opening':opening,
            'poz':poz})
    print("Skirtuko_tipas:",skirtuko_tipas)
    # Sukuriamas atidarancio skirtuko objektas
    Atidarantis_skirtukas=Opening(skirtuko_tipas,opening,String[poz:poz+len])
    # Kreipiamasi i parse funkcija
    Objektas, lenght, closing_len = parse(String[poz+len:],
                                          syntax,Tikrinimo_mechanizmas,
                                          address,new_stack)
    k=lenght
    print("\nVidinio reiskinio ilgis:",lenght)
    print("Vidinis_reiskinys:",'>>'+String[poz+len:poz+len+lenght]+'<<')
    print("Uzdarantis reiskinys:",String[poz+len+lenght:poz+len+lenght+closing_len])
    print("Viso reiskinio ilgis:",len+lenght+closing_len)
    # print("apgaubtas_baigesi:",String[poz+k+closing_len:])
    Uzdarantis_skirtukas=Closing(skirtuko_tipas,opening,String[poz+len+k:poz+len+k+closing_len])
    Objektas.lenght=len+k+closing_len
    Objektas.address=address
    Objektas.body=String[poz+len:poz+len+k]
    Objektas.opening=Atidarantis_skirtukas
    Objektas.closing=Uzdarantis_skirtukas
    return Objektas, Objektas.lenght

# Blokas:
#  Jo elementai gali buti gilios ir paprastos strukturos objektai.
#  Pvz: Tabularo turinys:
#      - row (eilute, kuri reikalauja atskiro parsinimo)
#        eilutes yra atskirtos tam tikrais symboliais
#        arba komandomis
#        [eilute:a & b & \multicolumn{2}{l}{c+d)\\]
#      - komanda (\hline,\ccline{3-4},\cline{2})
#        Komandos turincios bloko pabaigos reiksme
#        turi buti murodytos

def parse_block(pos,String,syntax,opening,len,address,checking):
    '''Bloku yra laikomi strukturos elementai, kuriu
    pradzia yra tam tikras reiskinys, o pabaiga yra
    kito reiskinio pradzia arba esamos grupes
    pabaiga.
    Kartu yra perduodamas esamos grupes tikrinimo
    mechanizmas.'''

# test=''' { \\begin{equation}
#     \\[ apacia \\]  pries
#     \\iffalse {sito \\[nereikia\\] $parsinti$ } \\fi
#      po
#      \\end
#      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#      {equation}
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#      { $cia mtm$  { ir t.t  {   $ { kalno virsus  } $ }}}} $$ {a+b}{c+d} $$ $ x+y$ \\begin
#     {equation}  aaa \\begin%
#     {verbatim}   bbb \\end {verbatim}  aaaa  \\end{equation}
#      '''

testas='''
\\documentclass[12pt]{article}

\\begin{document}
\\section                  *
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    {Gilus parsinimas}%+++++
%----------------------------
Parse medis teoriskai gali buti begalinis
\\begin{equation}
%%%%%%%%%%%%% $
\\frac{ \\mbox{arg\,max $f(\\mbox{sup $x$})$}}
{\\mbox{denominator as $ x+\\iffalse \\alpha + \\beta \\fi y$}}
\end{equation}

TeX\'iniai skliaustai yra ypatingos svarbos
{kiekvienas reiskinys {skliaustuose {susirenka isorines {savybes
{ir gali {tureti tik savo individualias}}}}}}.

Butinos parsinimo salygos:
\\begin{itemize}
\\item visi \TeX{}'iniai skliaustai turi buti suporuoti
\\end{itemize}

tebunie taip \\mbox{vidinis argumentas}  $ pirmoji matematika $
% tai yra komentaras
\\begin
%%%%%%%%%%%%
{equation}
%%%%%%%%%%%%
c+b+d
\\mbox{tekstas matematikoje $x+y\\mbox{ tai $$ z \\times{aaaa} x $$  $a$$b$tekstas} $}
\\end  {equation}
teksto pabaiga
\\iffalse   $ {     \\begin       \\fi \\[ display matematika \\iffalse \\] \\fi \\]
\\end{document}
'''

with open('test.tex','rt') as failas:
    test=failas.read()

print()
print()
objektas=parse(test,'T')
objektas.show_self()

def prasuk_objekta(objektas):
    for i in objektas.kids:
        if type(i)==FruitfullObject:
            print('   '*len(i.address), i.opening.body)
            prasuk_objekta(i)
            print('   '*len(i.address), i.closing.body)
        else:
            print('   '*len(i.address),'['+i.tipas+':'+i.body+']')

# prasuk_objekta(objektas)

def skip_inline_verbatim(poz,String):
    '''Verbatimine aplinka neturi aktyviu charu
    vienintelis aktyvus charas yra verbatimo esamas
    skirtukas.'''
    i=poz
    k=skip_command_name(poz,String)
    if String[i:i+k]!='\\verb':
        raise AlgError(
            "Cia ne inline verbatimo pradzia:\n"\
            "{}".format(context(i,String)),i)
    i+=k
    sym=String[i]; i+=1
    while String[i]!=sym:
        i+=1
        if EOS(i,String):
            raise EOSError("Renkant inline verbatima buvo "\
                         "pasiektas teksto galas.:\n"\
                         "{}".format(context(poz,String),poz),poz)
    i+=1
    return i-poz


import os

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from cocktails.models import Drink, Ingredient
from django.http import HttpResponseNotAllowed
from .forms import AddDrink
from django.http import Http404
from django.contrib import messages

@login_required()
def dashboard(request):
    drinksUser = Drink.objects.filter(owner=request.user)
    ingredients = Ingredient.objects.all()
    return render(request, 'dashboard.html', {'drinksUser': drinksUser, 'ingredients': ingredients})

@login_required()
def create(request):
    if request.method == 'GET':
        available_ingredients = Ingredient.objects.all()
        return render(request, 'create.html', {'form': AddDrink(), 'ingredients': available_ingredients})

    elif request.method == 'POST':
        form = AddDrink(request.POST, request.FILES)
        if form.is_valid():
            drink = form.save(commit=False)
            if 'image' in request.FILES:
                drink.image = request.FILES['image']

            drink.owner = request.user

            drink.save()  # Zapisz drinka do bazy danych

            selected_ingredients = []
            # Obsłuż składniki
            for key, value in request.POST.items():
                if key.startswith('ingredient_'):
                    ingredient_id = int(key.split('_')[1])

                    selected_ingredients.append(ingredient_id)

                    post_data_list = list(request.POST.items())
                    for key, value in post_data_list:
                        print(f'Klucz: {key}, Wartość: {value}')

                    # Sprawdź, czy użytkownik wprowadził nowy składnik
                    if key.startswith('new_ingredient'):
                        new_ingredient_name = request.POST.get('new_ingredient')
                        new_ingredient_amount = request.POST.get('new_ingredient_amount')
                        new_ingredient_unit = request.POST.get('new_ingredient_unit')

                        if new_ingredient_name:
                            # Utwórz nowy składnik
                            new_ingredient = Ingredient(
                                name=new_ingredient_name,
                                amount=new_ingredient_amount,
                                unit=new_ingredient_unit,
                            )
                            new_ingredient.save()
                            selected_ingredients.append(new_ingredient.id)

            # Przypisz składniki do drinka
            drink.ingredients.set(selected_ingredients)
            return redirect('dashboard')

        else:
            error = 'Coś poszło nie tak!'
            return render(request, 'create.html', {'form': form, 'error': error})
    else:
        return HttpResponseNotAllowed(permitted_methods=['GET', 'POST'])

@login_required()
def delete_drink(request, postId):
    try:
        drink = Drink.objects.get(pk=postId)
        os.remove(drink.image.path)
        os.remove(drink.thumbnail.path)

        drink.delete()

        messages.success(request, 'Drink został usunięty z twojej listy')

        return redirect('dashboard')

    except Drink.DoesNotExist:
        raise Http404("Wpis nie istnieje")


from mxnet.gluon.loss import Loss,_apply_weighting, _reshape_like

class SoftmaxCrossEntropyLossMask(Loss):
    def __init__(self, end_idx, axis=-1, sparse_label=True, from_logits=False, weight=None,
                 batch_axis=0, **kwargs):
        super(SoftmaxCrossEntropyLossMask, self).__init__(weight, batch_axis, **kwargs)
        self._axis = axis
        self._sparse_label = sparse_label
        self._from_logits = from_logits
        self.end_idx = end_idx

    def hybrid_forward(self, F, pred, label, sample_weight=None):
        #각 label 문장의 마지막 문자('END') 인덱스 정보 추출
        label = F.cast(label, dtype='float32')
        label_sent_length = F.argmax(F.where(label == self.end_idx, F.ones_like(label), F.zeros_like(label)), axis=1)

        if not self._from_logits:
            pred = F.log_softmax(pred, self._axis)
        if self._sparse_label:
            loss = -F.pick(pred, label, axis=self._axis, keepdims=True)
        else:
            label = _reshape_like(F, label, pred)
            loss = -F.sum(pred*label, axis=self._axis, keepdims=True)
        loss = _apply_weighting(F, loss, self._weight, sample_weight)
        #(N, 30, val)
        #길이를 초과하는 영역에 대해서 0로 loss 마스킹을 수행함
        loss = F.transpose(loss, (1,0, 2))
        loss = F.SequenceMask(loss, sequence_length=label_sent_length + 1, use_sequence_length=True)
        loss = F.transpose(loss, (1,0, 2))
        return F.sum(loss, axis=self._batch_axis, exclude=True)/(label_sent_length + 1)


import json
import logging
import sys
from jira import JIRA
from pathlib import Path

import config

class JiraRestApi:
    def __init__(self):
        creds_file = str(Path.home()) + '/.ssh/jira-creds.json'
        if Path(creds_file).exists():
            jira_creds = json.loads(open(creds_file).read())
        else:
            sys.exit('Unable to locate jira-creds.json')

        self.jira = JIRA(server=jira_creds['url'],
                         # Self-Hosted Jira (e.g. Server): the PAT token
                         token_auth=jira_creds['apitoken'],
                         )

    # Text field search returns tickets containing text, not exact matches. i.e.
    # Search of "AWS JDK" in component field returns any ticket contains either word in the field
    # Search of ""AWS JDK"" returns any ticket contains the phrase
    # Hence, an extra comparison is necessary to ensure the right tickets are
    # picked up.
    def search_related_issues(
            self, jira_proj_key, bd_comp, bd_comp_ver, bd_proj):
        related_issues = []
        search_str = (f'project={jira_proj_key} and BD_COMPONENT~"\\"{bd_comp}\\"" and BD_COMP_VERSION~"'
                      f'{bd_comp_ver}" and BD_PROJECT~"{bd_proj}"')
        issues = self.jira.search_issues(search_str)
        for issue in issues:
            if (getattr(issue.fields, config.JIRA["BD_COMPONENT"]) == bd_comp):
                related_issues.append(issue)
        return related_issues

    def search_issue(self, jira_proj_key, bd_comp,
                     bd_comp_ver, bd_proj, bd_proj_ver):
        search_str = (f'project={jira_proj_key} and BD_COMPONENT~"\\"{bd_comp}\\"" and BD_COMP_VERSION~"'
                      f'{bd_comp_ver}" and BD_PROJECT~"{bd_proj}" and BD_PROJ_VERSION~"{bd_proj_ver}"')
        issues = self.jira.search_issues(search_str)
        for issue in issues:
            if (getattr(issue.fields, config.JIRA["BD_COMPONENT"]) == bd_comp) and (getattr(
                    issue.fields, config.JIRA["BD_COMP_VERSION"]) == bd_comp_ver) and (getattr(issue.fields, config.JIRA["BD_PROJ_VERSION"]) == bd_proj_ver):
                return issue

        return None

    def new_issue(self, project, issue_dict):
        cves = ','.join(issue_dict['cves_list'])
        issue_fields = {
            'project': project,
            'summary': f'{issue_dict["summary"]}',
            'description': '',
            'issuetype': {'name': config.JIRA['issue_type']},
            'components': [{'name': f'{issue_dict["cb_component"]}'}],
            config.JIRA['BD_DETAIL']: f'{issue_dict["detail"]}',
            config.JIRA['BD_COMPONENT']: f'{issue_dict["component_name"]}',
            config.JIRA['BD_COMP_VERSION']: f'{issue_dict["version"]}',
            config.JIRA['BD_PROJECT']: f'{issue_dict["project_name"]}',
            config.JIRA['BD_PROJ_VERSION']: f'{issue_dict["project_version"]}',
            config.JIRA['BD_SEVERITY']: f'{issue_dict["severity"]}',
            config.JIRA['BD_CVES']: f'{cves}',
            config.JIRA['BD_LAST_UPDATE']: f'{issue_dict["date"]}'
        }
        return self.jira.create_issue(fields=issue_fields)

    def update_issue(self, issue, issue_dict):
        issue_fields = {
            config.JIRA['BD_DETAIL']: f'{issue_dict["detail"]}',
            config.JIRA['BD_LAST_UPDATE']: f'{issue_dict["date"]}'
        }
        if 'severity' in issue_dict.keys():
            issue_fields[config.JIRA['BD_SEVERITY']
                         ] = f'{issue_dict["severity"]}'
        if 'cves_list' in issue_dict.keys():
            cves = ','.join(issue_dict['cves_list'])
            issue_fields[config.JIRA['BD_CVES']] = f'{cves}'

        return issue.update(fields=issue_fields)

    def transition_issue(self, issue, transition, bd_update_date):
        self.jira.transition_issue(issue, transition)
        issue_fields = {
            config.JIRA['BD_LAST_UPDATE']: f'{bd_update_date}'
        }
        issue.update(fields=issue_fields)

    def create_issue_link(self, src_key, dest_key):
        self.jira.create_issue_link('relates to', src_key, dest_key)


from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

from app import settings
from home import views

urlpatterns = patterns('',
    url(r'^$', views.login, name='login'),
    url(r'^home$', views.home, name='home'),
    url(r'^profile', views.profile, name='profile'),
    # url(r'^battle', views.battle, name='battle'),
    url(r'^battle/', include('battle.urls', namespace='battle')),

    url(r'^tweet', views.tweet, name='tweet'),
    url(r'^query', views.query, name='query'),
    url(r'^media/photo', views.media_photo, name='media_photo'),
    url(r'^media/video', views.media_video, name='media_video'),
    url(r'^media/inspector', views.media_inspector, name='media_inspector'),
    url(r'^media', views.media_video, name='media_video'),
    url(r'^logout$', views.logout, name='logout'),
    url('', include('social.apps.django_app.urls', namespace='social')),

    url(r'^admin/', admin.site.urls),
)

urlpatterns += patterns('', (r'^static/(.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}), )


import socket
from time import sleep
import GlobalConstants
import struct

HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 10001        # The port used by the server

#this sender works in Read Print mode
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:

    #this gets a response, but it's an error in the log. Bad bytes!
    #concatMessage = GlobalConstants.StartTransmissionCharacter + "F6" + GlobalConstants.EndTransmissionCharacter

    #This seems to sort of correct- gets "Received SEND_DYNAMIC_DATA_RP1_REMOTE  $6 [24 36 ]" in the log
    concatMessage = GlobalConstants.StartTransmissionCharacter + GlobalConstants.GetSystemStatus + GlobalConstants.EndTransmissionCharacter

    concatMessage = GlobalConstants.StartTransmissionCharacter + "\xf6" + GlobalConstants.EndTransmissionCharacter
    encodedMessage = concatMessage.encode('charmap')

    s.connect((HOST, PORT))

    while True:
        #data = s.recv(1024)
        #print(data)
        print('sending command...')
        sleep(1)
        s.sendall(encodedMessage)

        #recv = s.recv(1024)

        #print(recv)

#Ignition code:
# import socket
# from time import sleep
# #import GlobalConstants

# HOST = '127.0.0.1'  # The server's hostname or IP address
# PORT = 10002        # The port used by the server

# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# s.connect((HOST, PORT))
# print 'waiting...'
# while True:
# 	data = s.recv(1024)
# 	#print data
# 	converted = str(data).decode('charmap')
# 	print converted
#system.util.sendMessage('Edge', 'TcpTest', {'Message':converted})


import cgi
import json
import logging
import re
import shutil
import sys
import uuid
from dataclasses import dataclass
from enum import Enum
from getpass import getuser
from hashlib import md5
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from os import path
from queue import Queue
from typing import Dict, List, Tuple, Union
from urllib import parse

import harvester.browser as browserModule

from .expiring_queue import ExpiringQueue

domain_pattern = re.compile(
    r'^(?:[a-zA-Z0-9]'  # First character of the domain
    r'(?:[a-zA-Z0-9-_]{0,61}[A-Za-z0-9])?\.)'  # Sub domain + hostname
    r'+[A-Za-z0-9][A-Za-z0-9-_]{0,61}'  # First 61 characters of the gTLD
    r'[A-Za-z]$'  # Last character of the gTLD
)

# md5 hashes the return of getnode or the logged in user to keep loggin anonymous
user_id = md5((hex(uuid.getnode()) if uuid.getnode() == uuid.getnode()
               else getuser()).encode()).hexdigest()
session_id = uuid.uuid4()

log = logging.getLogger('harvester')
sh = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter(
    '%(name)s(%(levelname)s) [%(timestamp)s] [%(address)s] %(message)s')
sh.setFormatter(formatter)
log.addHandler(sh)

class DomainInvalidException(Exception):
    pass

class CaptchaKindEnum(Enum):
    HCAPTCHA = 'hcaptcha'
    RECAPTCHA_V2 = 'recaptcha-v2'
    RECAPTCHA_V3 = 'recaptcha-v3'

@dataclass
class MITMRecord:
    kind: CaptchaKindEnum
    sitekey: str
    data_action: str
    tokens: 'ExpiringQueue[str]' = ExpiringQueue(110)

# support for pyarmor/pyinstaller
__dir__ = path.join(getattr(sys, '_MEIPASS'), 'harvester', 'server') if getattr(
    sys, '_MEIPASS', None) else path.abspath(path.dirname(__file__))

def ProxyHTTPRequestHandlerWrapper(domain_cache: Dict[str, MITMRecord] = {}, do_not_track=False):
    class ProxyHTTPRequestHandler(BaseHTTPRequestHandler):
        config: MITMRecord
        domain: str

        def _load_template(self, file: str, **args: Dict[str, Union[str, int]]):
            with open(path.join(__dir__, 'templates', file), 'r', encoding='utf-8') as f:
                template = f.read()
            for k, v in args.items():
                template = template.replace('{{ ' + k + ' }}', str(v))
            return template

        def _render_template(self, file: str, **args: Dict[str, Union[str, int]]):
            self.wfile.write(self._load_template(file, **args).encode('utf-8'))

        def _find_config(self):
            self.domain = self.headers.get('host', None)
            self.config = domain_cache.get(self.domain, None)
            if not self.config:
                self.domain, path = self.path.strip('/').split('/', 1)
                self.path = '/' + path
                self.config = domain_cache.get(self.domain, None)
                if not self.config:
                    self.send_error(404, 'Not intercepted',
                                    'This either happend because you are trying to solve captchas on localhost or you didn\'t configure the'
                                    ' harvester to harvest on the domain you are trying to access the harvester through.')
                    return False
            return True

        def _simple_headers(self, code: int, content_type: str):
            self.send_response(code)
            self.send_header('Content-Type', content_type)
            self.end_headers()

        def do_CONNECT(self):
            self.send_error(
                500, "Yuck! hTtPs", 'Make sure to use http:// not https:// when accessing the host though the proxy server')

        def do_GET(self):
            if self.path == '/favicon.ico':
                self._simple_headers(200, 'image/png')
                shutil.copyfileobj(
                    open(path.join(__dir__, 'icon.png'), 'rb'), self.wfile)
            elif self.path == '/style.css':
                self._simple_headers(200, 'text/css')
                shutil.copyfileobj(
                    open(path.join(__dir__, 'style.css'), 'rb'), self.wfile)
            elif self.path == '/domains':
                self._simple_headers(200, 'text/html')
                domain_list = ''
                for domain in domain_cache.keys():
                    domain_list += f'
{domain}
'
                self._render_template('domains.html', domain_list=domain_list)
            else:
                self.handel_request('GET')

        def do_POST(self):
            self.handel_request('POST')

        def handel_request(self, method: str):
            if self._find_config():
                host, port = self.server.server_address
                if self.path == '/':
                    ga_config = dict(
                        do_not_track=str(do_not_track).lower(),
                        captcha=self.config.kind.value,
                        domain=self.domain,
                        sitekey=self.config.sitekey,
                        user_id=user_id,
                        session_id=session_id,
                        post_token_submit='false',
                        token_submit_success='0'
                    )
                    if method == 'POST':
                        ga_config['post_token_submit'] = 'true'
                        form = cgi.FieldStorage(
                            fp=self.rfile,
                            headers=self.headers,
                            environ={
                                'REQUEST_METHOD': 'POST',
                                'CONTENT_TYPE': self.headers['Content-Type'],
                            }
                        )
                        token = form.getvalue(
                            'h-captcha-response') or form.getvalue('g-recaptcha-response')
                        if token:
                            ga_config['token_submit_success'] = '1'
                            self.config.tokens.put(token)
                    self._simple_headers(200, 'text/html; charset=utf-8')

                    html_config = dict(
                        domain=self.domain,
                        sitekey=self.config.sitekey,
                        server=f"http://{host}:{port}")

                    html_config['script.ga.js'] = self._load_template(
                        'ga.chunk.html', **ga_config)

                    if self.config.kind == CaptchaKindEnum.RECAPTCHA_V3:
                        html_config['action'] = self.config.data_action

                    self._render_template(
                        self.config.kind.value + '.html', **html_config)
                elif self.path.startswith('/tokens'):
                    self._simple_headers(200, 'text/json; charset=utf-8')
                    self.wfile.write(
                        json.dumps(self.config.tokens.to_list()).encode('utf-8'))
                elif self.path.startswith('/token'):
                    if self.config.tokens.empty():
                        self.send_error(
                            418, "I am a teapot and I have no tokens right now", 'Any attempt to brew coffee with a teapot should result in the error code "418 I\'m a teapot"')
                    else:
                        self._simple_headers(200, 'text/plain; charset=utf-8')
                        self.wfile.write(
                            self.config.tokens.get().encode('utf-8'))

        def log_error(self, format, *args):
            log.error(format % args, extra={
                'timestamp': self.log_date_time_string(),
                'address': self.address_string()
            })

        def log_message(self, format, *args):
            log.info(format % args, extra={
                'timestamp': self.log_date_time_string(),
                'address': self.address_string()
            })
    return ProxyHTTPRequestHandler

class Harvester(object):
    def __init__(self, host='127.0.0.1', port=5000, do_not_track=False):
        self.domain_cache: Dict[str, MITMRecord] = {}
        self.httpd = ThreadingHTTPServer(
            (host, port), ProxyHTTPRequestHandlerWrapper(self.domain_cache, do_not_track))

    def serve(self):
        try:
            self.httpd.serve_forever()
        except KeyboardInterrupt:
            pass
        finally:
            self.httpd.shutdown()

    def launch_browser(self, browser: Union[browserModule.BrowserEnum, str] = browserModule.BrowserEnum.CHROME,
                       restart: bool = False, width: int = 400, height: int = 580, args: List[str] = [],
                       extensions: str = None, verbose: bool = False):
        return browserModule.launch(list(self.domain_cache.keys()),
                                    self.httpd.server_address, browser, restart, width, height, args, extensions, verbose)

    def get_token_queue(self, domain):
        return self.domain_cache[domain].tokens

    def _intercept(self, domain: str, sitekey: str, captcha_kind: CaptchaKindEnum, action: str = None):
        if not domain_pattern.match(domain):
            raise DomainInvalidException(
                'You must only give a domain, not a whole URL.')
        ret = self.domain_cache[domain] = MITMRecord(
            captcha_kind, sitekey, action)
        return ret.tokens

    def intercept_recaptcha_v2(self, domain: str, sitekey: str):
        return self._intercept(domain, sitekey, CaptchaKindEnum.RECAPTCHA_V2, None)

    def intercept_recaptcha_v3(self, domain: str, sitekey: str, action: str = None):
        return self._intercept(domain, sitekey,
                               CaptchaKindEnum.RECAPTCHA_V3, action=action)

    def intercept_hcaptcha(self, domain: str, sitekey: str):
        return self._intercept(domain, sitekey, CaptchaKindEnum.HCAPTCHA, None)


from typing import Set, MutableMapping, Tuple, Any, NoReturn

from sqlalchemy.orm import Session

from .base_fixture import BaseFixture

class Loader:
    def __init__(self, session: Session):
        self.session = session
        self._fixtures: MutableMapping[str, BaseFixture] = dict()
        self._pending: Set[str] = set()

    def add(self, fixture: BaseFixture) -> NoReturn:
        self._fixtures[fixture.key] = fixture
        self._pending.add(fixture.key)

    def load(self, pending: Set[str] = None, circular: Tuple[str, Any] = None) -> NoReturn:
        if pending is None:
            pending = self._pending.copy()

        if circular is None:
            circular = tuple()

        while pending:
            key = pending.pop()

            if key not in self._fixtures:
                raise Exception("no fixture for key: '{}'".format(key))

            fixture = self._fixtures[key]

            if key in circular:
                continue
                # raise Exception("circular reference to: '{}', path: '{}'".format(key, "', '".join(circular)))

            dependencies = self._pending & fixture.dependencies
            if dependencies:
                self.load(dependencies, (key, *circular))

            if key in self._pending:
                fixture.load()
                self._pending.remove(key)


import os
import pickle
import warnings
import numpy as np
from SilenceEliminator import SilenceEliminator
from FeaturesExtractor import FeaturesExtractor

warnings.filterwarnings("ignore")

# paths to training data & to speaker models
modelpath = "SpeakerModels/"
testpath  = "TestingData"

# collect all Gaussian mixture model paths & load the GMMs
db = {}
for fname in [fname for fname in os.listdir(modelpath) if fname.endswith('.gmm')]:
    speaker     = fname.split('.')[0]
    model       = pickle.load( open(os.path.join(modelpath, fname), 'rb'))
    db[speaker] = model

file_paths = []
# file_paths = [os.path.join(testpath, fname) for fname in os.listdir('TestingData')]
# get file paths
for root, dirs, files in os.walk(testpath):
    for file in files:
        file_paths.append( os.path.join(root, file))

error, total_sample = 0, 0

print("+=======================================================+")
# read the test directory and get the list of test audio files
for path in file_paths[:]:
    if os.path.basename(path).split('_')[0] in db.keys():
        features_extractor = FeaturesExtractor()
        silence_eliminator = SilenceEliminator()

        silence_eliminated_wave_file_path ="temp-" + os.path.basename(path).split('.')[0] + ".wav"
        audio, duration_string = silence_eliminator.ffmpeg_silence_eliminator(path, silence_eliminated_wave_file_path)
        vector                 = features_extractor.accelerated_get_features_vector(path, audio, 8000)

        if vector.shape != (0,):
            print(vector.shape)
            total_sample      += 1
            log_likelihood     = {}
            m                  = {}
            for speaker, model in db.items():
                gmm                     = model
                scores                  = np.array(gmm.score(vector))
                log_likelihood[speaker] = round(scores.sum(), 3)
                m[speaker]              = scores

            max_log_likelihood = max(log_likelihood.values())
            keys, values       = list(log_likelihood.keys()), list(log_likelihood.values())
            winner             = keys[values.index(max_log_likelihood)]

            checker_name = os.path.basename(path).split("_")[0]
            if winner != checker_name:
                error += 1

        print("+-------------------------------------------------------+")
        print("Processed filemame : %10s" % os.path.basename(path))
        print("Expected speaker   : %10s" % os.path.basename(path).split("_")[0])
        print("Identified speaker : %10s" % winner)
        print("+=======================================================+")

accuracy = ((total_sample - error) / total_sample) * 100
print(" %10s || %7s  " % ("THE ACCURACY   ", round(accuracy, 3)))
print("+=======================================================+")


def all_construct(target,word_bank=[],memo={}):
    """ returns all combinations of target from the words of the word bank """
    #base case

    if (target == ""):
        return [[]] #returns an empty double array/list

    #memoization case check
    if target in memo:
        return memo[target]

    result=[]

    for word in word_bank:
        #slice out the suffix to work on recursively
        if(word == target[:len(word)]):
            suffix=target[len(word):]
            suffix_ways=all_construct(suffix,word_bank) #ways in which suffix can be combined
            target_ways=list(map(lambda way:[word]+way,suffix_ways))
            #ways in which target can be combined using suffix ways i.e. add the edge word to the front of every suffix_ways lists

            #now add that to the final result
            result+=target_ways

    memo[target]=result
    return result

def main():
    memo={}

    print(all_construct("hello", ["he", "l", "o"],memo))
    print(all_construct("rajamati", ["s", "raj", "amat", "raja", "ma", "i", "t"],memo))

if __name__ == "__main__":
    main()


from urllib.request import Request, urlopen
import PySimpleGUI as sg
from els import els
import os
import minecraft
import shutil
import csv
import datetime
import sys

#自前でjarファイルを持っていたときに読み込む関数
def minecraft_server_local_jar_file():
    minecraft_local_jar_yes_no = sg.popup_yes_no("Jarファイル手動読み込み\n\nインストールのときにプログラムを書いたとき最新のサーバーバージョンにするようにしていますが\n最新のバージョンではない・入れたいバージョンがない場合があります。\nもしjarファイル(例server.jar)がある場合は読み込むことができます。\n手動で読み込みますか？")
    if minecraft_local_jar_yes_no == "Yes":
        while True:
            print()
            minecraft_local_jar_path = sg.popup_get_file('jarファイルを指定してください\n例:server.jar', file_types=(("Java Archive", ".jar"),))
            if not minecraft_local_jar_path:
                sg.popup("ファイルが選択されていません")
                return "no"
            minecraft_local_jar_check_file = els.check_file_dir(minecraft_local_jar_path, "False", "False")
            if minecraft_local_jar_check_file == "error":
                sg.popup("ファイルが存在しません。")
                return False
            return minecraft_local_jar_path
    elif minecraft_local_jar_yes_no == "No":
        return "no"

# server.properties ダウンロード
def minecraft_server_properties_download(path):
    url = 'https://server.properties/'
    # そのままだとurllib.error.HTTPError: HTTP Error 403: Forbiddenでコケるからユーザーエージェントを偽装
    headers = {'User-Agent': 'Mozilla/5.0'}
    request = Request(url, headers=headers)
    html = urlopen(request).read()
    html = html.decode('utf-8')
    # ファイル書き込み(server.properties)
    file = open(path+"/server.properties", mode='w')
    file.write(str(html))
    file.close()

def main_run():
    dt_now = datetime.datetime.now()
    check_dir = els.check_file_dir("minecraft/", "false", "false")
    if (check_dir == "error"):
        os.mkdir("minecraft")
    BAR_MAX = 100
    # ウィンドウに配置するコンポーネント
    layout = [  [sg.Text('作成',font=('Arial',20))],
                [sg.Text("バージョンは自分がjarファイルを持っている場合には、入力する必要がありません")],
                [sg.Text('バージョン(デフォルトだと：1.19.3)'), sg.InputText()],
                [sg.Text('ポート(デフォルトだと：25565)'), sg.InputText()],
                [sg.Text('名前(デフォルトだと：サーバー（未入力）)'), sg.InputText()],
                [sg.Text("進捗："),sg.ProgressBar(BAR_MAX, orientation='h', size=(20, 20), key='-PROG-')],
                [sg.Text('', key='-PROGRESS-')],
                [sg.Button('次へ'), sg.Button('戻る')] ]

    # ウィンドウの生成
    window = sg.Window('Minecraft-Auto-Server', layout)

    # イベントループ
    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED or event == '戻る':
            break
        elif event == '次へ':
            # jar読み込みモードかどうか・その場合の動作
            minecraft_server_local_jar_result = minecraft_server_local_jar_file()
            minecraft.minecraft_install_yes_no(values[1], values[0], minecraft_server_local_jar_result)
            new_dir_path_time = dt_now.strftime('%Y-%m-%d-%H-%M-%S-%f')[:-3]
            new_dir_path = "minecraft/minecraft-"+new_dir_path_time
            window['-PROGRESS-'].update(f'フォルダ作成'+new_dir_path)
            os.mkdir(new_dir_path)
            window['-PROGRESS-'].update(f'ファルダ作成完了')
            window.find_element('-PROG-').update(10)
            # jar読み込みモードではないときの動作
            if minecraft_server_local_jar_result == "no":
                window['-PROGRESS-'].update(f'サーバーダウンロード中')
                minecraft_server_version = minecraft.minecraft_download(values[0], new_dir_path)
                print(minecraft_server_version)
                window.find_element('-PROG-').update(70)
                window['-PROGRESS-'].update(f'サーバーダウンロード完了')
            # jar読み込みモード時の動作
            else:
                window['-PROGRESS-'].update(f'jarファイルコピー中')
                shutil.copyfile(minecraft_server_local_jar_result, new_dir_path+"/server.jar")
                minecraft_server_version = "unknown"
                window.find_element('-PROG-').update(70)
                window['-PROGRESS-'].update(f'jarファイルコピー完了')
            # minecraftのeula(eula.txt)の同意するか？同意したら書き換える
            eula_yes_no_popup = sg.popup_yes_no("Minecraft EULA（使用許諾契約 / 利用許諾契約）に同意しますか？\nMinecraftのEULA は https://www.minecraft.net/ja-jp/terms/r3 こちらを参照してください。")
            if eula_yes_no_popup == "Yes":
                pass
            else:
                sys.exit()
            file = open(new_dir_path+"/eula.txt", mode='w')
            # 書き換え(作成)内容
            file.write('#By changing the setting below to TRUE you are indicating your agreement to our EULA (https://aka.ms/MinecraftEULA).\n#Fri Dec 09 09:06:15 JST 2022\neula=true')
            file.close()
            window.find_element('-PROG-').update(85)
            window['-PROGRESS-'].update(f'EULA(ソフトウェア利用許諾契約)同意完了')
            # minecraftのポート変更（server.properties）
            window['-PROGRESS-'].update(f'ポート設定中')
            minecraft_server_properties_download(new_dir_path)
            if not values[1]:
                values[1] = "25565"
            window['-PROGRESS-'].update(f'ポート設定完了')
            # txtファイル（data/minecraft-dir-list.txt・data/minecraft-list.txt）
            window['-PROGRESS-'].update(f'txtファイル記述中')
            minecraft_server_name = values[2]
            minecraft_server_list_txt_lines_count = sum([1 for _ in open('data/minecraft-list.txt')])
            if not minecraft_server_name:
                minecraft_server_name = "サーバー（未入力）"
            with open('data/minecraft-list.txt', 'a', encoding="utf-8") as f:
                print("NO："+str(minecraft_server_list_txt_lines_count + 1)+" ｜サーバー名："+minecraft_server_name+" ｜作成時間："+dt_now.strftime('%Y年%m月%d日 %H:%M:%S')[:-3]+" ｜サーバーバージョン（jar読み込みだとunknown）："+minecraft_server_version+" ｜ディレクトリ位置："+new_dir_path+"/", file=f)
            with open('data/minecraft-dir-list.txt', 'a', encoding="utf-8") as f:
                print(new_dir_path, file=f)
            window['-PROGRESS-'].update(f'txtファイル記述完了')
            # 終わり
            window.find_element('-PROG-').update(100)
            window['-PROGRESS-'].update(f'インストール完了')
            sg.popup("インストールが終わりました\n管理から起動できます")
            break

    window.close()

if __name__ == "__main__":
    main_run()