import torch
import torch.nn as nn
from models.fcn import PFCN, FCN
from models.tnet import InputTransformNet, FeatureTransformNet

class PointNetCommon(nn.Module):
    '''
        common part of point-net
        input -> (T-Net) -> SFCN(64) -> SFCN(64) -> (T-Net) -> SFCN(64) -> SFCN(128) -> SFCN(1024) -> MaxPool -> output
                                                                                |
                                                                                v
                                                                                point_wise_feature
    '''

    def __init__(self, in_channels=3, point_num=1024, input_trans=False, feature_trans=False):
        super(PointNetCommon, self).__init__()
        self.input_trans = input_trans
        self.feature_trans = feature_trans

        if self.input_trans:
            self.inputTrans = InputTransformNet(in_channels, point_num, 3)

        self.pfcn1 = PFCN(in_channels, 64)
        self.pfcn2 = PFCN(64, 64)

        if self.feature_trans:
            self.featureTrans = FeatureTransformNet(64, point_num, 64)

        self.pfcn3 = PFCN(64, 64)
        self.pfcn4 = PFCN(64, 128)
        self.pfcn5 = PFCN(128, 1024)

        self.max_pool = nn.MaxPool1d(kernel_size=point_num)

    def forward(self, x):
        # x: B * C * N
        end_points = {}
        if self.input_trans:
            # inTrans: B * C * C
            inTrans = self.inputTrans(x)

            if x.shape[1] > 3:
                # only need transform the xyz part
                xyz = x[:, 0:3, :]
                xyz = xyz.permute(0, 2, 1)
                xyz = torch.matmul(xyz, inTrans)
                xyz = xyz.permute(0, 2, 1)
                x[:, 0:3, :] = xyz
            else:
                x = x.permute(0, 2, 1)
                x = torch.matmul(x, inTrans)
                x = x.permute(0, 2, 1)

            end_points["input_trans"] = inTrans

        x = self.pfcn1(x)
        x = self.pfcn2(x)

        if self.feature_trans:
            fTrans = self.featureTrans(x)
            x = x.permute(0, 2, 1)
            x = torch.matmul(x, fTrans)
            x = x.permute(0, 2, 1)

            end_points["feature_trans"] = fTrans

        x = self.pfcn3(x)
        x = self.pfcn4(x)
        x = self.pfcn5(x)
        point_wise_feature = x

        x = self.max_pool(x)

        # B,C,1 -> B,C
        x = x.squeeze(2)

        return x, point_wise_feature, end_points

if __name__ == "__main__":
    pnc = PointNetCommon(in_channels=3, point_num=1024)

    p_in = torch.randn((5, 3, 1024))
    f_out, pwf, _ = pnc(p_in)

    print(pnc)
    print("input: ", p_in.shape)
    print("feature output: ", f_out.shape)
    print("point-wise feature: ", pwf.shape)

    assert f_out.shape == torch.Size([5, 1024])
    assert pwf.shape == torch.Size([5, 64, 1024])


__author__ = 'Kalyan'

notes = '''
Implement a left binary search and write exhaustive tests for the same. Left binary search returns the index of left most
element when a search key repeats. For e.g if input is [1,2,3,3,4,4,5] and I search 3, it should return 2 as index 2 is
the left most occurance of 3.

In [1,1,1,1,1,1,1,1], I search for 1, you should return 0.

Note that we are looking for a binary search => we want not more than log(N) lookups, so a solution that involves finding
a random 1 and then doing a linear scan to the left is not a solution :).

- input is an indexable, value is any object.
- return -1 if not found or index of 1st occurance if found.
'''

def left_binary_search(input, value):
    import bisect
    if input == None: return -1
    lo=0
    hi = None
    hi = hi if hi is not None else len(input)
    pos = bisect.bisect_left(input, value, lo, hi)
    return (pos if pos != hi and input[ pos ] == value else -1)

# write your own exhaustive tests :)
def test_left_binary_search_student():
    assert 2 == left_binary_search([1,2,3,3,3,3,3,3,4,4,5], 3)
    assert 0 == left_binary_search([1,1,1,1,1,1,1,1], 1)
    assert 0 == left_binary_search([ 0, 1, 1, 1, 1, 1, 1, 1, 1 ], 0)
    assert 10 == left_binary_search([ 1, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5 ], 5)
    assert -1 == left_binary_search(None,10)

# these tests run only on our runs and will be skipped on your computers.
# DO NOT EDIT.
import pytest
def test_left_binary_search_server():
    servertests = pytest.importorskip("unit5_server_tests")
    servertests.test_left_binary_search(left_binary_search)


# -*- coding: utf-8 -*-
from pandas import Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.maps import Imports
from pandas_ta.utils import v_offset, v_pos_default, v_series, v_talib
from .sma import sma

def trima(
    close: Series, length: Int = None, talib: bool = None,
    offset: Int = None, **kwargs: DictLike
) -> Series:
    """Triangular Moving Average (TRIMA)

    A weighted moving average where the shape of the weights are triangular
    and the greatest weight is in the middle of the period.

    Sources:
        https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triangular-moving-average-trima/
        tma = sma(sma(src, ceil(length / 2)), floor(length / 2) + 1)  # Tradingview
        trima = sma(sma(x, n), n)  # Tradingview

    Args:
        close (pd.Series): Series of 'close's
        length (int): It's period. Default: 10
        talib (bool): If TA Lib is installed and talib is True, Returns
            the TA Lib version. Default: True
        offset (int): How many periods to offset the result. Default: 0

    Kwargs:
        adjust (bool): Default: True
        fillna (value, optional): pd.DataFrame.fillna(value)
        fill_method (value, optional): Type of fill method

    Returns:
        pd.Series: New feature generated.
    """
    # Validate
    length = v_pos_default(length, 10)
    close = v_series(close, length)

    if close is None:
        return

    mode_tal = v_talib(talib)
    offset = v_offset(offset)

    # Calculate
    if Imports["talib"] and mode_tal:
        from talib import TRIMA
        trima = TRIMA(close, length)
    else:
        half_length = round(0.5 * (length + 1))
        sma1 = sma(close, length=half_length, talib=mode_tal)
        trima = sma(sma1, length=half_length, talib=mode_tal)

    # Offset
    if offset != 0:
        trima = trima.shift(offset)

    # Fill
    if "fillna" in kwargs:
        trima.fillna(kwargs["fillna"], inplace=True)
    if "fill_method" in kwargs:
        trima.fillna(method=kwargs["fill_method"], inplace=True)

    # Name and Category
    trima.name = f"TRIMA_{length}"
    trima.category = "overlap"

    return trima


import cv2
import numpy as np

img = cv2.imread('IconFaceLv2.png')

def showPanda() :
    # cv2.imshow('image',img)
    cv2.namedWindow('panda',cv2.WINDOW_NORMAL)
    cv2.imshow('panda',img)
    cv2.waitKey(0)


import requests
import streamlit as st

BASE_URL = "https://api.kraken.com/0"

@st.cache(ttl=5, suppress_st_warning=True)
def get_status():
    request = BASE_URL + '/public/SystemStatus'
    st.code(request)
    response = requests.get(request).json()
    st.json(response)
    return response


import sys
_module = sys.modules[__name__]
del sys
dataset = _module
layer = _module
lfw_eval = _module
main = _module
net = _module

from _paritybench_helpers import _mock_config, patch_functional
from unittest.mock import mock_open, MagicMock
from torch.autograd import Function
from torch.nn import Module
import abc, collections, copy, enum, functools, inspect, itertools, logging, math, matplotlib, numbers, numpy, pandas, queue, random, re, scipy, sklearn, string, tensorflow, time, torch, torchaudio, torchtext, torchvision, types, typing, uuid, warnings
import numpy as np
from torch import Tensor
patch_functional()
open = mock_open()
yaml = logging = sys = argparse = MagicMock()
ArgumentParser = argparse.ArgumentParser
_global_config = args = argv = cfg = config = params = _mock_config()
argparse.ArgumentParser.return_value.parse_args.return_value = _global_config
yaml.load.return_value = _global_config
sys.argv = _global_config
__version__ = '1.0.0'
xrange = range
wraps = functools.wraps

import torch.utils.data as data

import torch

import torch.nn as nn

import torch.nn.functional as F

from torch.nn import Parameter

import math

import numpy as np

from torchvision.transforms import functional as F

import torchvision.transforms as transforms

from torch.autograd import Variable

import torch.backends.cudnn as cudnn

import time

import torch.utils.data

import torch.optim

def cosine_sim(x1, x2, dim=1, eps=1e-08):
    ip = torch.mm(x1, x2.t())
    w1 = torch.norm(x1, 2, dim)
    w2 = torch.norm(x2, 2, dim)
    return ip / torch.ger(w1, w2).clamp(min=eps)

class MarginCosineProduct(nn.Module):
    """Implement of large margin cosine distance: :
    Args:
        in_features: size of each input sample
        out_features: size of each output sample
        s: norm of input feature
        m: margin
    """

    def __init__(self, in_features, out_features, s=30.0, m=0.4):
        super(MarginCosineProduct, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.s = s
        self.m = m
        self.weight = Parameter(torch.Tensor(out_features, in_features))
        nn.init.xavier_uniform_(self.weight)

    def forward(self, input, label):
        cosine = cosine_sim(input, self.weight)
        one_hot = torch.zeros_like(cosine)
        one_hot.scatter_(1, label.view(-1, 1), 1.0)
        output = self.s * (cosine - one_hot * self.m)
        return output

    def __repr__(self):
        return self.__class__.__name__ + '(' + 'in_features=' + str(self.in_features) + ', out_features=' + str(self.out_features) + ', s=' + str(self.s) + ', m=' + str(self.m) + ')'

class AngleLinear(nn.Module):

    def __init__(self, in_features, out_features, m=4):
        super(AngleLinear, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.m = m
        self.base = 1000.0
        self.gamma = 0.12
        self.power = 1
        self.LambdaMin = 5.0
        self.iter = 0
        self.weight = Parameter(torch.Tensor(out_features, in_features))
        nn.init.xavier_uniform_(self.weight)
        self.mlambda = [lambda x: x ** 0, lambda x: x ** 1, lambda x: 2 * x ** 2 - 1, lambda x: 4 * x ** 3 - 3 * x, lambda x: 8 * x ** 4 - 8 * x ** 2 + 1, lambda x: 16 * x ** 5 - 20 * x ** 3 + 5 * x]

    def forward(self, input, label):
        self.iter += 1
        self.lamb = max(self.LambdaMin, self.base * (1 + self.gamma * self.iter) ** (-1 * self.power))
        cos_theta = F.linear(F.normalize(input), F.normalize(self.weight))
        cos_theta = cos_theta.clamp(-1, 1)
        cos_m_theta = self.mlambda[self.m](cos_theta)
        theta = cos_theta.data.acos()
        k = (self.m * theta / 3.14159265).floor()
        phi_theta = (-1.0) ** k * cos_m_theta - 2 * k
        NormOfFeature = torch.norm(input, 2, 1)
        one_hot = torch.zeros_like(cos_theta)
        one_hot.scatter_(1, label.view(-1, 1), 1)
        output = one_hot * (phi_theta - cos_theta) / (1 + self.lamb) + cos_theta
        output *= NormOfFeature.view(-1, 1)
        return output

    def __repr__(self):
        return self.__class__.__name__ + '(' + 'in_features=' + str(self.in_features) + ', out_features=' + str(self.out_features) + ', m=' + str(self.m) + ')'

class Block(nn.Module):

    def __init__(self, planes):
        super(Block, self).__init__()
        self.conv1 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.prelu1 = nn.PReLU(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.prelu2 = nn.PReLU(planes)

    def forward(self, x):
        return x + self.prelu2(self.conv2(self.prelu1(self.conv1(x))))

class sphere(nn.Module):

    def __init__(self, type=20, is_gray=False):
        super(sphere, self).__init__()
        block = Block
        if type is 20:
            layers = [1, 2, 4, 1]
        elif type is 64:
            layers = [3, 7, 16, 3]
        else:
            raise ValueError('sphere' + str(type) + ' IS NOT SUPPORTED! (sphere20 or sphere64)')
        filter_list = [3, 64, 128, 256, 512]
        if is_gray:
            filter_list[0] = 1
        self.layer1 = self._make_layer(block, filter_list[0], filter_list[1], layers[0], stride=2)
        self.layer2 = self._make_layer(block, filter_list[1], filter_list[2], layers[1], stride=2)
        self.layer3 = self._make_layer(block, filter_list[2], filter_list[3], layers[2], stride=2)
        self.layer4 = self._make_layer(block, filter_list[3], filter_list[4], layers[3], stride=2)
        self.fc = nn.Linear(512 * 7 * 6, 512)
        for m in self.modules():
            if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
                if m.bias is not None:
                    nn.init.xavier_uniform_(m.weight)
                    nn.init.constant_(m.bias, 0.0)
                else:
                    nn.init.normal_(m.weight, 0, 0.01)

    def _make_layer(self, block, inplanes, planes, blocks, stride):
        layers = []
        layers.append(nn.Conv2d(inplanes, planes, 3, stride, 1))
        layers.append(nn.PReLU(planes))
        for i in range(blocks):
            layers.append(block(planes))
        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

    def save(self, file_path):
        with open(file_path, 'wb') as f:
            torch.save(self.state_dict(), f)

class BlockIR(nn.Module):

    def __init__(self, inplanes, planes, stride, dim_match):
        super(BlockIR, self).__init__()
        self.bn1 = nn.BatchNorm2d(inplanes)
        self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.prelu1 = nn.PReLU(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn3 = nn.BatchNorm2d(planes)
        if dim_match:
            self.downsample = None
        else:
            self.downsample = nn.Sequential(nn.Conv2d(inplanes, planes, kernel_size=1, stride=stride, bias=False), nn.BatchNorm2d(planes))

    def forward(self, x):
        residual = x
        out = self.bn1(x)
        out = self.conv1(out)
        out = self.bn2(out)
        out = self.prelu1(out)
        out = self.conv2(out)
        out = self.bn3(out)
        if self.downsample is not None:
            residual = self.downsample(x)
        out += residual
        return out

class LResNet(nn.Module):

    def __init__(self, block, layers, filter_list, is_gray=False):
        self.inplanes = 64
        super(LResNet, self).__init__()
        if is_gray:
            self.conv1 = nn.Conv2d(1, filter_list[0], kernel_size=3, stride=1, padding=1, bias=False)
        else:
            self.conv1 = nn.Conv2d(3, filter_list[0], kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(filter_list[0])
        self.prelu1 = nn.PReLU(filter_list[0])
        self.layer1 = self._make_layer(block, filter_list[0], filter_list[1], layers[0], stride=2)
        self.layer2 = self._make_layer(block, filter_list[1], filter_list[2], layers[1], stride=2)
        self.layer3 = self._make_layer(block, filter_list[2], filter_list[3], layers[2], stride=2)
        self.layer4 = self._make_layer(block, filter_list[3], filter_list[4], layers[3], stride=2)
        self.fc = nn.Sequential(nn.BatchNorm1d(filter_list[4] * 7 * 6), nn.Dropout(p=0.4), nn.Linear(filter_list[4] * 7 * 6, 512), nn.BatchNorm1d(512))
        for m in self.modules():
            if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear):
                nn.init.xavier_uniform_(m.weight)
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0.0)
            elif isinstance(m, nn.BatchNorm2d) or isinstance(m, nn.BatchNorm1d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def _make_layer(self, block, inplanes, planes, blocks, stride):
        layers = []
        layers.append(block(inplanes, planes, stride, False))
        for i in range(1, blocks):
            layers.append(block(planes, planes, stride=1, dim_match=True))
        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.prelu1(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

    def save(self, file_path):
        with open(file_path, 'wb') as f:
            torch.save(self.state_dict(), f)

import torch
from torch.nn import MSELoss, ReLU
from _paritybench_helpers import _mock_config, _mock_layer, _paritybench_base, _fails_compile

TESTCASES = [
    # (nn.Module, init_args, forward_args, jit_compiles)
    (Block,
     lambda: ([], {'planes': 4}),
     lambda: ([torch.rand([4, 4, 4, 4])], {}),
     True),
    (BlockIR,
     lambda: ([], {'inplanes': 4, 'planes': 4, 'stride': 1, 'dim_match': 4}),
     lambda: ([torch.rand([4, 4, 4, 4])], {}),
     True),
]

class Test_MuggleWang_CosFace_pytorch(_paritybench_base):
    def test_000(self):
        self._check(*TESTCASES[0])

    def test_001(self):
        self._check(*TESTCASES[1])


import argparse
import importlib

from pyspark.sql import SparkSession

parser = argparse.ArgumentParser()
parser.add_argument('--job', type=str, required=True, help='the job name you want to select')
parser.add_argument("--job-args", action='append', type=str, help='the arguments of the job passed\
  one or multiple timesin form of --job-args="[key]=[value]" ')

args = parser.parse_args()

#transforming the job args into a dictionary
def get_kwargs(job_args):
  dic = {}
  for el in job_args:
    key, value = el.split('=')
    dic[key] = value
  return dic

spark = SparkSession \
        .builder \
        .master("yarn") \
        .appName('dataproc-python-demo') \
        .getOrCreate()

# importing the selected job module
job_module = importlib.import_module('jobs.%s' % args.job)
# calling the function analyze the job exposes
job_module.analyze(spark, **get_kwargs(args.job_args))


import time
import re
import sys
import random
from unittest.util import strclass
import numpy as np
from argparse import ArgumentParser, Namespace
from typing import Callable, List, Optional, Tuple, Union
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5.QtWidgets import (
    QMainWindow, QApplication, QPushButton, QLineEdit,
    QMessageBox, QAbstractItemView, QGraphicsScene, QGraphicsView, QLabel,
    QGraphicsSimpleTextItem, QTableWidget, QTableWidgetItem)
from PyQt5.QtGui import QColor, QBrush, QPen, QPolygonF
from PyQt5.QtCore import pyqtSlot, QPointF, Qt
from math import sqrt

POLSKIE_ZNAKI = "ŃńĘęŚśĄąŁłŹźŻżĆćÓó"
# zmienna globalna typu str zbierająca znaki diakrytyczne

MAX_WSPÓŁRZĘDNA = 7
# zmienna globalna do opisu wielkości planszy scrabble

WSPÓŁRZĘDNE = [(x - (y + 1) // 2, y) for x in range(-MAX_WSPÓŁRZĘDNA,
                                                    MAX_WSPÓŁRZĘDNA+1) for y in range(-MAX_WSPÓŁRZĘDNA, MAX_WSPÓŁRZĘDNA+1)]
# lista krotek współrzędnych kafelków na planszy

WSPÓŁRZĘDNE.sort(key=(lambda p: abs(p[0]) + abs(p[1])))
# sortujemy według podanego klucza - przeszukiwanie planszy od (0,0) "promieniście"

class StrMSet:
    # tworzymy klasę multiset str
    def __init__(self, literki: List[str]):
        self.dict = dict()
        for literka in literki:
            self.add(literka)

    def has(self, literka: str) -> bool:
        return literka in self.dict

    def add(self, literka: str):
        if literka not in self.dict:
            self.dict[literka] = 1
        else:
            self.dict[literka] += 1

    def remove(self, literka: str):
        if literka in self.dict:
            if self.dict[literka] == 1:
                self.dict.pop(literka)
            else:
                self.dict[literka] -= 1

class Dostawka:
    # klasa Dostawka - zawiera istotne informacje o dostawce

    KIERUNKI = {"UP": (0, 1), "RIGHT": (1, 0), "DOWN": (1, -1)}
    # kierunki są trzy: UP: (0,1), RIGHT: (1,0), DOWN: (1,-1) zgdodnie z zasadami hex-scrabble

    def __init__(self, słowo: str, start: Tuple[int, int],
                 kierunek: str, współrzędne: Optional[List[Tuple[int, int]]] = None):
        # konstruktor klasy Dostawka

        self.słowo = słowo # słowo, które chcemy utworzyć
        self.start = start # współrzędne startu
        self.wektor = Dostawka.KIERUNKI[kierunek] # kierunek w którym będzie tworzone słowo
        self.litery_od_gracza = StrMSet([]) # litery, które gracz wyłożył z ręki na dostawkę
        if współrzędne is None:
            self.współrzędne = [
                (self.start[0] + i*self.wektor[0],
                 self.start[1] + i*self.wektor[1])
                for i in range(len(self.słowo))
            ]
        else:
            self.współrzędne = współrzędne # ustalamy współrzędne dostawki na planszę

    def czy_dobra(self, plansza: dict) -> bool:
        # sprawdzamy czy dostawka spełnia warunki konieczne: nie wychodzi poza planszę, w przypadku zaczynania
        # przechodzi przez punkt (0,0), czy da się ją dopisać do planszy (mamy punkt zaczepienia)
        # i czy nie jest pusta

        czy_jakaś_nowa = False
        czy_jakaś_pasuje = False
        if not plansza and (0, 0) not in self.współrzędne:
            return False
        for (x, y), literka in zip(self.współrzędne, self.słowo):
            if not (y <= MAX_WSPÓŁRZĘDNA
                    and y >= -MAX_WSPÓŁRZĘDNA
                    and x <= MAX_WSPÓŁRZĘDNA - (y + 1) // 2
                    and x >= -MAX_WSPÓŁRZĘDNA - (y + 1) // 2):
                return False
            if (x, y) in plansza:
                if plansza[(x, y)] != literka:
                    return False
                else:
                    czy_jakaś_pasuje = True
            else:
                czy_jakaś_nowa = True
        return czy_jakaś_nowa and (czy_jakaś_pasuje or not plansza)

    def dodaj_litere(self, litera: str):
        # wykładamy literę na dostawkę

        self.litery_od_gracza.add(litera)

    def dodaj_litery_gracza(self, plansza: dict, litery_gracza: List[str]) -> bool:
        # sprawdzamy czy z liter w ręce da się ułożyć słowo i wyłożyć dostawkę, zapisujemy litery

        litery = StrMSet(litery_gracza)
        for i, punkt in enumerate(self.współrzędne):
            if punkt not in plansza:
                if not litery.has(self.słowo[i]):
                    return False
                else:
                    litery.remove(self.słowo[i])
                    self.dodaj_litere(self.słowo[i])
        return True

    def litery_gracza(self) -> str:
        # zwracamy wyłożone lietry jako string

        return ''.join([k*v for k, v in self.litery_od_gracza.dict.items()])

class Kafelek:
    # w klasie Kafelek trzymamy rysunek pola hex-scrabble

    RAMKA = QPen(Qt.black)
    WYBRANA_RAMKA = QPen(Qt.green)
    PREMIA_2W = Qt.cyan
    PREMIA_3W = Qt.magenta
    PREMIA_2L = Qt.red
    PREMIA_3L = Qt.blue
    START = QBrush(QColor(209, 204, 255))
    PUSTY = QBrush(QColor(255, 255, 204))
    PEŁNY = QBrush(QColor(255, 204, 229))
    # KOLORY w zależności od funkcji i stanu pola

    def __init__(self, scene: QGraphicsScene, pos: Tuple[int, int],
                 premie_słowne: Optional[str], premie_literowe: dict):
        # konstruktor klasy Kafelek

        poly = QPolygonF([
            QPointF(10, 10), QPointF(10, 15),
            QPointF(10 - 5 * sqrt(3)/2, 17.5), QPointF(10 - 5 * sqrt(3), 15),
            QPointF(10 - 5 * sqrt(3), 10), QPointF(10 - 5 * sqrt(3)/2, 7.5)
        ])
        # tworzenie szcześciokąta na postawie wyznaczających go punków - wierzchołków

        y = -pos[1]
        x = pos[0] + (-y + 1) // 2
        poly.translate(x*10 + (5 * sqrt(3)/2 if (y + 1) % 2 else 0), y*10)
        # ustawiamy kafelek w odpowiedniej pozycji

        self.hexagon = scene.addPolygon(poly, self.RAMKA, self.PUSTY)
        self.hexagon.setScale(4)
        # dodajemy do okna planszy i ustalamy rozmiar kafelków

        self.premia = (f'{premie_słowne}W' if premie_słowne is not None else
                       f'{premie_literowe}L' if premie_literowe is not None else "")
        # sprawdzamy czy to kafelek pola specjalnego

        self.ustaw_premię()
        # ustawiamy premię

        if (pos == (0, 0)):
            self.hexagon.setPen(self.WYBRANA_RAMKA)
            self.hexagon.setBrush(self.START)
        # ustawiamy kolor startu

        self.textItem = QGraphicsSimpleTextItem('', self.hexagon)
        # str(pos) zamiast '' - żeby zoaczyć jak rozmieszczone są współrzędne

        self.textItem.setScale(0.2)
        # wielkość napisu na kafelku

        self.textItem.setPos((self.hexagon.boundingRect().center()
                              + self.hexagon.boundingRect().topLeft())/2)
        # ustawiamy pozycję tekstu w zależności od prostokąta opisanego/ograniczająego kafelek

        self.litera = None
        self.pos = pos

    def ustaw_premię(self):
        # ustawiamy znaczniki pól specjalnych (są one wyróżnione kolorami ramek)

        if self.premia == "3W":
            self.hexagon.setPen(self.PREMIA_3W)
        elif self.premia == "2W":
            self.hexagon.setPen(self.PREMIA_2W)
        elif self.premia == "3L":
            self.hexagon.setPen(self.PREMIA_3L)
        elif self.premia == "2L":
            self.hexagon.setPen(self.PREMIA_2L)

    def zaznacz(self, zapal: bool):
        # podświetla zaznaczone pole i gasi jeśli nie jest zaznaczone - potrzebne do porusznia się na planszy

        self.hexagon.setPen(self.WYBRANA_RAMKA if zapal else self.RAMKA)
        if not zapal:
            self.ustaw_premię()

    def zmień_literkę(self, literka: str):
        # zmienianie pola tekstowego - do ustawiania literki

        self.textItem.setText(literka)

def punkty(plansza: dict, dostawka: Dostawka,
           premie_literowe: dict, premie_słowne: dict, wartości: dict
           ) -> Tuple[int, List[str]]:
    # punkty trzeba liczyć przed kładzeniem dostawki na planszę - szukamy max

    if dostawka.czy_dobra(plansza):
        # dostawka spełnia warunki konieczne na prawidłową dostawkę

        suma_za_dostawkę = 0
        # robimy możliwe dostawki - trzymamy je w liście dostawki

        dostawki = [dostawka]
        for poz, (x, y) in enumerate(dostawka.współrzędne):
            if (x, y) not in plansza:
                # pole w które chcemy wstawić literkę jest wolne

                for v in [v for v in Dostawka.KIERUNKI.values() if v != dostawka.wektor]:
                    # musimy sprawdzić czy dostawka pasuje, czy po dostawiniu powstaną nowe prawidłowe słowa
                    # na planszy (zajęte)

                    if ((x+v[0], y+v[1]) in plansza) or ((x-v[0], y-v[1]) in plansza):
                        # pola, które nie należą do kierunku dostawiania a stykają się z tym do którego
                        # chcemy dostawić są na planszy (zajęte)

                        słowo = dostawka.słowo[poz]
                        gdzie_jest_start = 0
                        if ((x-v[0], y-v[1]) in plansza):
                            gdzie_jest_start = 1
                            i = 1
                            while (x - i*v[0], y - i*v[1]) in plansza:
                                słowo = plansza[(
                                    x - i*v[0], y - i*v[1])] + słowo
                                i += 1
                            start = (x - (i-1)*v[0], y - (i-1)*v[1])
                        if ((x+v[0], y+v[1]) in plansza):
                            i = 1
                            while (x + i*v[0], y + i*v[1]) in plansza:
                                słowo += plansza[(x + i*v[0], y + i*v[1])]
                                i += 1
                            if not gdzie_jest_start:
                                start = (x, y)
                        # po dostwieniu powstanie ciąg znaków, za pomocą powyższych operacji
                        # chcemy otzrymać współrzędne startu, aby utorzyć dst - nową zmienną klasy Dostawka

                        dst = Dostawka(słowo, start, "RIGHT")
                        dst.wektor = v
                        dostawki.append(dst)

        for dst in dostawki:
            # liczymy punkty za dostawkę - nowoutworzone słowa też się liczą do punktcji

            premia = 1
            suma = 0
            for i, (x, y) in enumerate(dst.współrzędne):
                premia *= premie_słowne.get((x, y), 1)
                try:
                    suma += wartości[dst.słowo[i]] * \
                        premie_literowe.get((x, y), 1)
                except KeyError:
                    # na wypadek błędu klucza

                    return -1, []
            suma_za_dostawkę += premia * suma

        nowesłowa = [
            dst.słowo for dst in dostawki if dst.słowo != dostawka.słowo]
        # lista nowych słów (będziemy je sprawdzać w ruchu komputera - założenie, że gracz uczciwy)

        return suma_za_dostawkę, nowesłowa
    else:
        return -1, []

def wstaw(plansza: dict, dostawka: Dostawka) -> bool:
    # wstawianie dostawki na planszę

    if dostawka.czy_dobra(plansza):
        for (x, y), literka in zip(dostawka.współrzędne, dostawka.słowo):
            plansza[(x, y)] = literka
        return True
    else:
        return False

def ruch_gracza(plansza: dict, dostawka: Dostawka,
                premie_literowe: dict, premie_słowne: dict, wartości: dict) -> int:
    # przeprowadzmy ruch gracza

    pkt, _ = punkty(plansza, dostawka, premie_literowe,
                    premie_słowne, wartości)
    if pkt != -1:
        wstaw(plansza, dostawka)

    return pkt

def ruch(plansza: dict, mojelitery: List[str], kolekcjasłów: set,
         premie_literowe: dict, premie_słowne: dict, wartości: dict, **opcje
         ) -> Union[Dostawka, np.ndarray]:
    # przeprowadzamy ruch komputera

    best = (-1, None)
    if "limit" in opcje and opcje["limit"]:
        # jeśli użytkownik wybrtał poziom trudności w którym komputer ma ograniczony czas
        # zaczynamy mierzyć czas komputerowi na ruch

        start = time.time()
    for słowo in kolekcjasłów:
        # przechodzimy słownik

        if not any([c in mojelitery for c in słowo]):
            # jeśli nie mamy żadnej literki ze słowa to przechodzimy do kolejnego
            # musimy mieć co dostawić

            continue
        for (x, y) in WSPÓŁRZĘDNE:
            # przechodzimy po współrzędnych planszy

            for kierunek in ["UP", "RIGHT", "DOWN"]:
                # sprawdzamy każdy kierunek

                v = Dostawka.KIERUNKI[kierunek]
                współrzędne = [(x+i*v[0], y+i*v[1]) for i in range(len(słowo))]
                end = (współrzędne[-1][0], współrzędne[-1][1])
                # produkujemy współrzędne kandydata na dostawkę

                if plansza.get((x - v[0], y - v[1])) or plansza.get((end[0] + v[0], end[1] + v[1])):
                    # eliminujemy możliwość, że komputer przedłuża słowo bez względu na to co jest
                    # na planszy postawione

                    break
                if not (end[1] <= MAX_WSPÓŁRZĘDNA
                        and end[1] >= -MAX_WSPÓŁRZĘDNA
                        and end[0] <= MAX_WSPÓŁRZĘDNA - (end[1] + 1) // 2
                        and end[0] >= -MAX_WSPÓŁRZĘDNA - (end[1] + 1) // 2):
                        # sprawdzamy czy słowo się mieści na planszy

                    break
                zajęte = [p in plansza for p in współrzędne]
                # lista zajętych współrzędnych z tych do których chcemy dostawiać

                if (not any(zajęte) and plansza) or all(zajęte):
                    # przypadek kiedy chcemy dostawić na puste pola, ale plansza nie jest pusta
                    # (nie mamy jak zaczepić słowa) lub wszystkie z naszych pozycji są zajęte

                    break

                dst = Dostawka(słowo, (x, y), kierunek, współrzędne)
                # tworzymy z tego słowa dostawkę

                pkt, nowesłowa = punkty(
                    plansza, dst, premie_literowe, premie_słowne, wartości)
                # liczymy punkty i dostajemy listę nowych słów, które sprawdzimy
                # czy należą do słownika

                if pkt != -1:
                    # dostawka spełnia warunki konieczne

                    jest_ok = dst.dodaj_litery_gracza(plansza, mojelitery)
                    # da się ułożyć słowo z dostępnych liter

                    if jest_ok and best[0] < pkt:
                        # jeśli dostawka, którą sprawdzmy jest potencjalnie lepsza

                        złe_nowe_słowo = False
                        for nowe in nowesłowa:
                            # sprawdzamy czy nowe słowa to słowa ze słownika

                            if nowe not in kolekcjasłów:
                                złe_nowe_słowo = True
                                break
                        if not złe_nowe_słowo:
                            # jeśli nowe słowa są w słowniku to ustawiamy dostawkę jako najlepszą dotyczas

                            best = (pkt, dst)
            if "limit" in opcje and opcje["limit"] and time.time() - start > opcje["limit"]:
                # kiedy czas się skończył to przerywamy pętlę

                break
    if best[1] != None:
        # jeśli znaleźliśmy dostawkę to ją zwracamy

        return best[1]
    else:
        # jeśli nie znaleźliśmy dostawki zwracamy tablicę liter do wymiany

        return np.random.choice(
            np.array(mojelitery), np.random.randint(1, len(mojelitery) + 1), replace = False
        )
        # losowanie bez zwracania z tablicy literek

def rozgrywka(konfiguracja: dict, imię_gracza: str, trudność: str) -> int:
    # funkcja która przeprowadza rozrywkę w zależności od wprowadzonych danych gracza i konfiguracji

    app = QApplication([])
    App(imię_gracza, konfiguracja, app.processEvents, trudność)
    return app.exec_()

class App(QMainWindow):
    # klasa App kontroluje grę i część wizualizacujną GUI

    def __init__(self, imię_gracza: str, konfiguracja: dict, update_gui: Callable, trudność: str):
        # konstruktor klasy App, ustalamy parametry GUI i parametry gry z konfiguracji

        super().__init__()
        self.title = 'Scrabble'
        self.update_gui = update_gui

        self.left = 150
        self.top = 150
        self.width = 1200
        self.height = 710
        # wymiary okna głównego gry

        self.wynik_komputera = 0
        self.wynik_gracza = 0
        self.imię_gracza = imię_gracza
        self.czy_tura_gracza = random.choice([0, 1])
        # parametry dotyczące wyniku i bieżącej tury -> wyświetlane w GUI

        self.plansza = dict()
        self.kafelki = dict()
        # słowniki do przechowywania kafelków i stanu planszy

        self.kierunek = "RIGHT"
        self.start = (0, 0)
        # domyślnie start w (0,0) i kierunek wpisywania słowa w prawo

        self.woreczek = [
            li for li, _, cz in konfiguracja['worek'] for _ in range(int(cz))
        ]
        self.literki_gracza = [
            random.choice(self.woreczek) for _ in range(konfiguracja['liczba_liter_gracz'])
        ]
        self.literki_komputera = [
            random.choice(self.woreczek) for _ in range(konfiguracja['liczba_liter_gracz'])
        ]
        self.słownik = set([slowo.upper()
                           for slowo in konfiguracja['słownik']])
        self.premie_literowe = konfiguracja['premie_literowe']
        self.premie_słowne = konfiguracja['premie_słowne']
        self.wartości = {literka: int(wart)
                         for literka, wart, _ in konfiguracja['worek']}
        self.limit = 10 if trudność == "ŁATWY" else 20 if trudność == "NORMALNY" else None
        # ustalamy konfigurację gry

        self.initUI()
        # tworzymy okno

        if not self.czy_tura_gracza:
            # losowo grę rozpoczyna albo komputer albo gracz

            self.tura_komputera()

    def initUI(self):
        # tworzymy okno w którym będzie toczyła się gra

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        # tworzymy okno o ustalonych rozmiarach

        self.textbox = QLineEdit(self)
        self.textbox.setValidator(QtGui.QRegExpValidator(
            QtCore.QRegExp(f"[a-zA-Z{POLSKIE_ZNAKI}]+")))
        self.textbox.move(20, 630)
        self.textbox.resize(580, 40)
        # tworzymy skrzynkę tekstową do której gracz będzie wpisywał słowo

        self.button = QPushButton('Dodaj słowo', self)
        self.button.move(20, 670)
        # tworzymy przycisk do dodawania słów

        self.button.clicked.connect(self.textbox_klik)
        # łączymy przycisk z skrzynką tekstową

        self.score1 = QLabel("", self)
        self.score1.resize(300, 20)
        self.score1.move(850, 70)
        self.score2 = QLabel("", self)
        self.score2.resize(300, 20)
        self.score2.move(850, 120)
        self.zmień_wynik()
        # pola tektowe w których będziemy wyświetlać wyniki

        self.tura = QLabel("", self)
        self.tura.resize(300, 20)
        self.tura.move(850, 15)
        myFont=QtGui.QFont()
        myFont.setBold(True)
        self.tura.setFont(myFont)
        self.zmień_turę()
        # pole tektowe w którym będziemy wyświetlać czyja tura

        literki = self.literki_gracza
        self.tableWidget = QTableWidget(len(literki), 2, self)
        self.tableWidget.setHorizontalHeaderLabels(["Literka", "Wartość"])
        self.tableWidget.verticalHeader().hide()
        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableWidget.adjustSize()
        self.tableWidget.setGeometry(820, 200, 330, 400)
        self.set_table(self.wartości)
        # ustalamy tabelkę w której gracz będzie miał literki i będzie mógł wybrać literki do wymiany

        self.button_table = QPushButton('Wymień', self)
        self.button_table.move(820, 610)
        # przycisk wymień do tabelki

        self.button_table.clicked.connect(self.tabela_klik)
        # łączymy przycisk z tabelką

        scene = QGraphicsScene()
        scene.setBackgroundBrush(QBrush(QColor(255, 229, 204)))
        # rysowanie pola w którym wyświetli się plansza do gry

        for punkt in WSPÓŁRZĘDNE:
            # łączymy punkt z odpowiednim kafelkiem na planszy

            self.kafelki[punkt] = Kafelek(scene, punkt, self.premie_słowne.get(
                punkt, None), self.premie_literowe.get(punkt, None))

        view = QGraphicsView(scene, self)
        view.setGeometry(10, 10, 800, 610)
        # ustawiamy pole w oknie

        view.keyPressEvent = self.keyPressEvent_
        # akcja po wciśnięciu odpowiedniego przycisku z klawiatury

        view.focusInEvent = self.repaint
        # aktualne kafelki będą zapalone po fokusie na pole z kafelkami

        self.show()

    def repaint(self, _):
        # zapala kafelki których pola ma zająć dostawka i gasi pozostałe

        for punkt in WSPÓŁRZĘDNE:
            self.kafelki[punkt].zaznacz(False)
        self.zapal()

    def zmień_wynik(self):
        # aktualizuje wyniki graczy

        self.score1.setText(f"Komputer: {self.wynik_komputera}")
        self.score2.setText(f"{self.imię_gracza}: {self.wynik_gracza}")

    def zmień_turę(self):
        # aktualizuje napis czyja tura

        self.czy_tura_gracza = not self.czy_tura_gracza
        self.tura.setText(
            f"Tura {self.imię_gracza if self.czy_tura_gracza else 'Komputera'}")

    @pyqtSlot() # dektorator łączy sygnał przycisku skrzynki tekstowej z funkcją textbox_klik()
    def textbox_klik(self):
        # wciskając przycisk chcemy dodać słowo na planszę

        słowo = self.textbox.text().upper()
        # chcemy wielkie litery bo na takich działamy w słownikach (domyślnie w konfiguracji)

        dst = Dostawka(słowo, self.start, self.kierunek)
        if not dst.dodaj_litery_gracza(self.plansza, self.literki_gracza):
            QMessageBox.question(
                self, 'Uwaga', "Wpisano złe słowo - błąd ręki", QMessageBox.Ok, QMessageBox.Ok)
            return
        # sprawdzamy czy gracz ma w ręce to co chce wpisać

        points = ruch_gracza(
            self.plansza, dst, self.premie_literowe, self.premie_słowne, self.wartości)
        if points == -1:
            QMessageBox.question(
                self, 'Uwaga', "Wpisano złe słowo - błąd warunki konieczne", QMessageBox.Ok, QMessageBox.Ok)
            return
        # sprawdzamy czy dostawka spełnia watunki konieczne

        self.zgaś(self.kierunek)
        self.połóż(dst, self.premie_literowe, self.premie_słowne)
        self.wynik_gracza += points
        self.zmień_wynik()
        # aktualizujemy okno po dodaniu słowa

        lgracza = dst.litery_gracza()
        self.wymień_litery(
            [x for x in range(len(self.literki_gracza))
             if self.literki_gracza[x] in lgracza],
            self.literki_gracza)
        # uzupełniamy braki w literach

        self.textbox.setText("")
        self.tura_komputera()
        # usuwamy tekst ze skrzynki i zmieniamy turę

    def połóż(self, dostawka: Dostawka,
              premie_literowe: dict, premie_słowne: dict):
        # kładziemy lietrki na planszy

        for punkt, litera in zip(dostawka.współrzędne, dostawka.słowo):
            self.kafelki[punkt].zmień_literkę(litera)
            self.kafelki[punkt].hexagon.setBrush(self.kafelki[punkt].PEŁNY)
            for wspol in premie_literowe:
                if punkt == wspol and premie_literowe[wspol] == 2:
                    self.kafelki[punkt].hexagon.setBrush(
                        self.kafelki[punkt].PREMIA_2L)
                if punkt == wspol and premie_literowe[wspol] == 3:
                    self.kafelki[punkt].hexagon.setBrush(
                        self.kafelki[punkt].PREMIA_3L)
            for wspol in premie_słowne:
                if punkt == wspol and premie_słowne[wspol] == 2:
                    self.kafelki[punkt].hexagon.setBrush(
                        self.kafelki[punkt].PREMIA_2W)
                if punkt == wspol and premie_słowne[wspol] == 3:
                    self.kafelki[punkt].hexagon.setBrush(
                        self.kafelki[punkt].PREMIA_3W)
        # pola specjalne kiedy mają lietrkę wypełniają się kolorkiem z ramki
        # aby gracz wiedział, że to pola specjalne, bo premia nie znika

    def set_table(self, wartości: dict):
        # ustawiamy lietrki w tabelce

        literki = self.literki_gracza
        for i in range(len(literki)):
            self.tableWidget.setItem(i, 0, QTableWidgetItem(literki[i]))
            self.tableWidget.setItem(
                i, 1, QTableWidgetItem(str(wartości[literki[i]])))

    def wymień_litery(self, idx_do_wyjęcia: List[int], ręka: List[str],
                      literki: List[str] = [], wymiana: bool = False):
        # funkcja służy do wymiany liter

        indeksy = np.random.choice(
            np.array(range(len(self.woreczek))), len(idx_do_wyjęcia), replace=False)
        # tablica losowych liter z woreczka o długości listy indeksów do wyjęcia

        for i, idx in zip(idx_do_wyjęcia, indeksy):
            # dobieramy do ręki

            ręka[i] = self.woreczek[idx]
        if wymiana:
            j = 0
            for i in range(len(self.woreczek)):
                if i in indeksy:
                    self.woreczek[i] = literki[j]
                    j += 1
        else:
            self.woreczek = [self.woreczek[i]
                             for i in range(len(self.woreczek)) if i not in indeksy]
        # zmiana która następuje w woreczku po wymianie

        self.set_table(self.wartości)
        # ustawiamy literki wraz z wartościami w tabelce

    @pyqtSlot() # dektorator łączy sygnał przycisku tabelki z funkcją table_klik()
    def tabela_klik(self):
        # klikamy wymień i wymieniamy lietrki w tabelce

        self.zgaś(self.kierunek)
        literki = [item.text()
                   for item in self.tableWidget.selectedItems() if item.column() == 0]
        self.wymień_litery(
            [item.row() for item in self.tableWidget.selectedItems()
             if item.column() == 0],
            self.literki_gracza,
            literki,
            True)
        self.tura_komputera()
        # zmieniamy turę na turę komputera

    def tura_komputera(self):
        # funkcja która przeprowadza turę komputera

        if self.czy_tura_gracza:
            self.zmień_turę()
        # zmieniamy napis czyja tura i int który wskazuje czy tura gracza

        self.update_gui()
        # aktualizujemy okno z nowymi informacjami

        ret = ruch(self.plansza, self.literki_komputera, self.słownik,
                   self.premie_literowe, self.premie_słowne, self.wartości, limit=self.limit)
        # wykomujemy ruch komputera -> zwraca dostawkę bądź tablicę liter do wymiany

        if isinstance(ret, Dostawka):
            # sprawdzamy czy ret jest typu Dostawka

            self.połóż(ret, self.premie_literowe, self.premie_słowne)
            # kładziemy dostawkę na planszę (wizualnie)

            self.wynik_komputera += punkty(
                self.plansza, ret, self.premie_literowe, self.premie_słowne, self.wartości)[0]
            # liczymy komputerowi punkty

            wstaw(self.plansza, ret)
            # wstawiamy literki na planszę (słownik)

            self.zmień_wynik()
            # zmieniamy wynik w oknie

            lgracza = ret.litery_gracza()
            self.wymień_litery(
                [x for x in range(len(self.literki_komputera))
                 if self.literki_komputera[x] in lgracza],
                self.literki_komputera)
            # uzupełnimy rękę komputera

        else:
            # jesteśmy w else - czyli ret to tablica liter do wymiany

            indeksy = []
            tret = ret.copy()
            # kopiujemy tablicę

            for i in range(len(self.literki_komputera)):
                if self.literki_komputera[i] in tret:
                    indeksy.append(i)
                    tret[np.where(tret == self.literki_komputera[i])[0][0]] = ""
                    # w ręce może być kilka takich samych literek a potrzebujemy wymienić dokładnie tyle
                    # ile pojawiło się w tablicy

            for i in indeksy: print(self.literki_komputera[i])
            self.wymień_litery(indeksy, self.literki_komputera, ret, True)
            # wymieniamy literki

        self.zmień_turę()
        # zmieniamy turę w oknie

    def keyPressEvent_(self, a0: QtGui.QKeyEvent) -> None:
        # funkcja obsługuje przyciski z klawiatury
        # manipulujemy nimi pola podświetlane do których chcielibyśmy wpisać dostawkę

        zmiana = False
        nowy_start = self.start
        kierunek = self.kierunek
        if a0.key() == Qt.Key_Up:
            if (self.start[0], self.start[1] + 1) in WSPÓŁRZĘDNE:
                zmiana = True
                nowy_start = (self.start[0], self.start[1] + 1)
        elif a0.key() == Qt.Key_Right:
            if (self.start[0] + 1, self.start[1]) in WSPÓŁRZĘDNE:
                zmiana = True
                nowy_start = (self.start[0] + 1, self.start[1])
        elif a0.key() == Qt.Key_Down:
            if (self.start[0], self.start[1] - 1) in WSPÓŁRZĘDNE:
                zmiana = True
                nowy_start = (self.start[0], self.start[1] - 1)
        elif a0.key() == Qt.Key_Left:
            if (self.start[0] - 1, self.start[1]) in WSPÓŁRZĘDNE:
                zmiana = True
                nowy_start = (self.start[0] - 1, self.start[1])
        # strzałkami poruszamy się po planszy

        elif a0.key() == Qt.Key_Space:
            zmiana = True
            if self.kierunek == "RIGHT":
                self.kierunek = "DOWN"
            elif self.kierunek == "DOWN":
                self.kierunek = "UP"
            else:
                self.kierunek = "RIGHT"
        # spacją zmieniamy kierunek wpisywania kodu

        if zmiana:
            # gasimy i zapalamy wtedy kiedy naciśnie dopuszczalne przyciski z klawiatury

            self.zgaś(kierunek)
            self.start = nowy_start
            self.zapal()

        return super().keyPressEvent(a0)

    def zgaś(self, kierunek: str):
        # gasimy podświetlone kafelki, kierunek po to, żeby zgasić w odpowienim kierunku

        słowo = self.textbox.text()
        for punkt in [self.start] + Dostawka(słowo, self.start, kierunek).współrzędne:
            if punkt in WSPÓŁRZĘDNE:
                self.kafelki[punkt].zaznacz(False)

    def zapal(self):
        # zapalamy kafelki

        słowo = self.textbox.text()
        for punkt in [self.start] + Dostawka(słowo, self.start, self.kierunek).współrzędne:
            if punkt in WSPÓŁRZĘDNE:
                self.kafelki[punkt].zaznacz(True)

def init_parser() -> ArgumentParser:
    # tworzymy parser

    parser = ArgumentParser(
        description="Gra Scrabble na hexagonalnej planszy. Gracz vs komputer.")
    parser.add_argument("-I", dest='imię_gracza',
                        help="Wybrane imię gracza realnego")
    parser.add_argument("-S", dest='plik_ze_slownikiem',
                        help="Ścieżka do pliku tekstowego ze słownikiem dla komputera")
    parser.add_argument("-c", dest='konfiguracja',
                        help="Ścieżka do pliku tekstowego z odpowiednią sformatowaną konfiguracją")
    parser.add_argument("-d", dest='trudność', choices=["ŁATWY", "NORMALNY", "TRUDNY"], default="ŁATWY",
                        help="Ustawienie poziomu trudności. Domyślnie: ŁATWY")
    # dodajemy argumenty porzebne do odpalenia gry

    return parser

def init_config(args: Namespace) -> dict:
    # czytamy konfigurację z pliku konfiguracyjnego

    regex = r'(-?\d+), (-?\d+)'
    # wyrażenie regularne do pobierania współrzędnych

    with open(args.plik_ze_slownikiem, encoding='UTF-8') as file:
        slownik = file.read().split()
    with open(args.konfiguracja, encoding='UTF-8') as konfig:
        lista_do_konfiguracji = konfig.read().splitlines()
    # otwieramy słownik i plik konfiguracyjny
    # odpowiednio tworzymy listę słów i listę linii z odpowiednimi parametrami

    liczba_w_ręce = int(re.findall(r'(\d+)', lista_do_konfiguracji[0])[0])
    PREMIA_2LS = re.findall(regex, lista_do_konfiguracji[1])
    PREMIA_3LS = re.findall(regex, lista_do_konfiguracji[2])
    PREMIA_2WS = re.findall(regex, lista_do_konfiguracji[3])
    PREMIA_3WS = re.findall(regex, lista_do_konfiguracji[4])
    KOSTKI = re.findall(
        fr"'([a-zA-Z{POLSKIE_ZNAKI}])', (\d+), (\d+)", lista_do_konfiguracji[5])
    # re.findall zwraca listy krotek

    premie_literowe = {(int(x), int(y)): 2 for x, y in PREMIA_2LS} | {
        (int(x), int(y)): 3 for x, y in PREMIA_3LS}
    premie_słowne = {(int(x), int(y)): 2 for x, y in PREMIA_2WS} | {
        (int(x), int(y)): 3 for x, y in PREMIA_3WS}
    # łączymy dwa słowniki do premii: literowych i słownych

    return {
        'słownik': slownik,
        'liczba_liter_gracz': liczba_w_ręce,
        'premie_słowne': premie_słowne,
        'premie_literowe': premie_literowe,
        'worek': KOSTKI
    }
# dostajemy konfigurację w postacji słownika

if __name__ == '__main__':
    # w mainie uruchamiamy grę

    args = init_parser().parse_args()
    konfiguracja = init_config(args)
    sys.exit(rozgrywka(konfiguracja, args.imię_gracza, args.trudność))


"""
Contains possible interactions with the Apollo Organisms Module
"""
import json

from apollo.client import Client
from apollo.decorators import raise_error_decorator

class OrganismsClient(Client):
    CLIENT_BASE = '/organism/'

    @raise_error_decorator
    def add_organism(self, common_name, directory, blatdb=None, genus=None,
                     species=None, public=False, metadata=None, suppress_output=False):
        """
        Add an organism

        :type common_name: str
        :param common_name: Organism common name

        :type directory: str
        :param directory: Server-side directory

        :type blatdb: str
        :param blatdb: Server-side path to 2bit index of the genome for Blat

        :type genus: str
        :param genus: Genus

        :type species: str
        :param species: Species

        :type public: bool
        :param public: Should the organism be public or not

        :type metadata: str
        :param metadata: JSON formatted arbitrary metadata

        :type suppress_output: bool
        :param suppress_output: Suppress output of all organisms (true / false) (default false)

        :rtype: dict
        :return: a dictionary with information about the new organism
        """
        data = {
            'commonName': common_name,
            'directory': directory,
            'publicMode': public,
        }

        if blatdb is not None:
            data['blatdb'] = blatdb
        if genus is not None:
            data['genus'] = genus
        if species is not None:
            data['species'] = species
        if metadata is not None:
            if isinstance(metadata, dict):
                # Apollo wants a string
                metadata = json.dumps(metadata)
            data['metadata'] = metadata
        if suppress_output is not None and suppress_output is True:
            data['returnAllOrganisms'] = False

        response = self.post('addOrganism', data)
        # Apollo decides here that it would be nice to return information about
        # EVERY organism. LMAO.
        if type(response) is not list:
            return response
        if len(response) > 0:
            return [x for x in response if x['commonName'] == common_name][0]
        else:
            return data

    def update_organism(self, organism_id, common_name, directory, blatdb=None, species=None, genus=None, public=False,
                        no_reload_sequences=False, suppress_output=False):
        """
        Update an organism

        :type organism_id: str
        :param organism_id: Organism ID Number

        :type common_name: str
        :param common_name: Organism common name

        :type directory: str
        :param directory: Server-side directory

        :type blatdb: str
        :param blatdb: Server-side Blat directory for the organism

        :type genus: str
        :param genus: Genus

        :type species: str
        :param species: Species

        :type public: bool
        :param public: User's email

        :type no_reload_sequences: bool
        :param no_reload_sequences: Set this if you don't want Apollo to reload genome sequences (no change in genome sequence)

        :type suppress_output: bool
        :param suppress_output: Suppress output of all organisms (true / false) (default false)

        :rtype: dict
        :return: a dictionary with information about the updated organism
        """
        data = {
            'id': organism_id,
            'name': common_name,
            'directory': directory,
            'publicMode': public,
            'noReloadSequences': no_reload_sequences,
        }

        if blatdb is not None:
            data['blatdb'] = blatdb
        if genus is not None:
            data['genus'] = genus
        if species is not None:
            data['species'] = species
        if suppress_output is not None and suppress_output is True:
            data['returnAllOrganisms'] = False

        response = self.post('updateOrganismInfo', data)
        if type(response) is not list:
            return response
        if len(response) > 0:
            return [x for x in response if x['commonName'] == common_name][0]
        else:
            return self.show_organism(common_name)

    def get_organisms(self, common_name=None):
        """
        Get all organisms

        :type common_name: str
        :param common_name: Optionally filter on common name

        :rtype: list
        :return: Organism information
        """
        if common_name is None:
            orgs = self.post('findAllOrganisms', data={})
        else:
            orgs = self.post('findAllOrganisms', {'organism': common_name})
        return orgs

    def show_organism(self, common_name):
        """
        Get information about a specific organism.

        :type common_name: str
        :param common_name: Organism Common Name

        :rtype: dict
        :return: a dictionary containing the organism's information
        """
        orgs = self.get_organisms(common_name=common_name)
        if isinstance(orgs, list) and len(orgs) > 0:
            orgs = orgs[0]
        return orgs

    def delete_organism(self, organism_id, suppress_output=False):
        """
        Delete an organism

        :type organism_id: str
        :param organism_id: Organism ID Number

        :type suppress_output: bool
        :param suppress_output: Suppress return of all organisms (true / false) (default false)

        :rtype: list
        :return: A list of all remaining organisms

        """
        data = {
            'id': organism_id,
        }
        if suppress_output is not None and suppress_output is not False:
            data['returnAllOrganisms'] = False

        return self.post('deleteOrganism', data)

    def delete_features(self, organism_id):
        """
        Remove features of an organism

        :type organism_id: str
        :param organism_id: Organism ID Number

        :rtype: dict
        :return: an empty dictionary
        """
        return self.post('deleteOrganismFeatures', {'organism': organism_id})

    def get_sequences(self, organism_id):
        """
        Get the sequences for an organism

        :type organism_id: str
        :param organism_id: Organism ID Number

        :rtype: list of dict
        :return: The set of sequences associated with an organism
        """
        return self.post('getSequencesForOrganism', {'organism': organism_id})

    def get_organism_creator(self, organism_id):
        """
        Get the creator of an organism

        :type organism_id: str
        :param organism_id: Organism ID Number

        :rtype: dict
        :return: a dictionary containing user information
        """
        return self.post('getOrganismCreator', {'organism': organism_id})

    def update_metadata(self, organism_id, metadata):
        """
        Update the metadata for an existing organism.

        :type organism_id: str
        :param organism_id: Organism ID Number

        :type metadata: str
        :param metadata: Organism metadata. (Recommendation: use a structured format like JSON)

        :rtype: dict
        :return: An empty, useless dictionary
        """
        return self.post('updateOrganismMetadata', {'id': organism_id, 'metadata': metadata})


import requests

def main():
	location = input("Enter Your City Name: ")

	res = requests.get("http://api.openweathermap.org/data/2.5/weather?q="+location+"&APPID=8daef122aca4c4d9d40408fb5566bb65")

	data = res.json()

	co = data['main'] ['temp']

	temp_max = data['main'] ['temp_max']

	temp_min = data['main'] ['temp_min']

	conditions = data['weather'] [0] ['main']

	co = co - 273.15

	co = "%.2f" % co

	temp_min = temp_min - 273.15

	temp_max = temp_max - 273.15

	temp_min = "%.2f" % temp_min

	temp_max = "%.2f" % temp_max

	print("Your conditions were: "+conditions)

	print("The current temp is: "+str(co)+" in celsius")

	print("The max temp will: "+temp_max+"and temp_min"+temp_min)

	return conditions,temp_min,temp_max

main()


import pytz
import schedule
import subprocess

from crawling_python.global_utils import get_database_connect

kst = pytz.timezone('Asia/Seoul')

def delete_expired_data(today):
    kst = pytz.timezone('Asia/Seoul')
    connect = get_database_connect()
    cursor = connect.cursor()

    query = "DELETE FROM job WHERE expiration_date < %s"
    cursor.execute(query, (today,))

    connect.commit()
    cursor.close()
    connect.close()

def crawl_jobkorea():
    subprocess.run(["python", "crawling_jobkorea.py"])

def crawl_saramin():
    subprocess.run(["python", "crawling_saramin.py"])

schedule.every(3).days.at("00:00").do(crawl_saramin)
schedule.every(3).days.at("00:03").do(crawl_jobkorea)
schedule.every().day.at("00:05").do(delete_expired_data)

if __name__ == "__main__":
    while True:
        schedule.run_pending()


#!/usr/bin/env python
import math
import sys
import time
from math import sqrt, radians, cos, sin, tan, atan2

import rospy
import numpy as np
import pandas as pd

from ackermann_msgs.msg import AckermannDriveStamped
from geometry_msgs.msg import PoseStamped
from sensor_msgs.msg import LaserScan
from tf.transformations import euler_from_quaternion

class PurePursuit:
    POSE_TOPIC = "/gt_pose"
    DRIVE_TOPIC = "/pp_improv_drive"
    SCAN_TOPIC = "scan"

    LOOKAHEAD_DEFAULT = 2

    STRAIGHTS_SPEED = 5.0
    CORNERS_SPEED = 3.0
    STRAIGHTS_STEERING_ANGLE = radians(10)
    STEERING_ANGLE_CONSTANT = 1  # Curvature = K (2|y|)/(L^2)

    WHEELBASE = 0.3302
    """Constant from car size"""

    target_dist_diff = None
    """Distance of target from self.LOOKAHEAD"""

    VIABLE_WAYPOINT_ANGLE = radians(20)
    """Positive number of radians from the +X axis (Straight ahead).
    Only waypoints where (LOCAL) `tan(x/y)<VIABLE_WAYPOINT_ANGLE` will be considered viable waypoints"""

    global_waypoints = None
    """Global coords"""
    lookahead_dist = None
    """Lookahead distance in metres"""

    scan = None
    """The most recent LiDAR scan"""
    radians_per_elem = None
    CAR_DIVIDER = 1.9
    """What do divide car width by to get "half" of the car's width"""

    pose_previous = None
    pose_current = None

    # Current pos global
    global_curr_x = None
    global_curr_y = None
    global_curr_angle = None
    """
        Angle relative to the +X axis going towards +Y (Anti clockwise)
        Between 0 and 360 NOT -180 and +180
    """
    # To speed up global_to_local
    # Both equal to -current_angle
    cos_theta = None
    sin_theta = None

    # Local current everything will always be `0`

    # Current target global and local
    global_tar_x = None
    global_tar_y = None
    local_tar_x = None
    local_tar_y = None

    cycle_times = []

    def __init__(self, waypoints: pd.DataFrame, lookahead: float = LOOKAHEAD_DEFAULT):
        self.global_waypoints = waypoints
        self.lookahead_dist = lookahead

        self.CAR_WIDTH = rospy.get_param("width", 0.2032)

        self.pose_subscriber = rospy.Subscriber(self.POSE_TOPIC, PoseStamped, self.pose_callback, queue_size=1)
        self.scan_subscriber = rospy.Subscriber(self.SCAN_TOPIC, LaserScan, self.scan_callback, queue_size=1)
        self.drive_publisher = rospy.Publisher(self.DRIVE_TOPIC, AckermannDriveStamped, queue_size=10)

    def scan_callback(self, scan: LaserScan):
        self.scan = scan
        self.radians_per_elem = (2 * np.pi) / len(scan.ranges)

    def pose_callback(self, pose_stamped: PoseStamped):
        start_time = time.time_ns() / 10**9

        if self.scan is None:
            return

        self.pose_current = pose_stamped.pose

        self.global_curr_x = self.pose_current.position.x
        self.global_curr_y = self.pose_current.position.y

        quat = (self.pose_current.orientation.x,
                self.pose_current.orientation.y,
                self.pose_current.orientation.z,
                self.pose_current.orientation.w)

        euler = euler_from_quaternion(quat)
        self.global_curr_angle = np.double(euler[2])  # From +X towards +Y

        # Caching for global_to_local and local_to_global
        self.cos_theta = cos(self.global_curr_angle)
        self.sin_theta = sin(self.global_curr_angle)

        # Find taget and assing target values
        self.calc_target_waypoint()
        # rospy.loginfo(f"Viable: {len(self.local_viable_waypoints)}")

        angle = self.calc_drive_angle()
        self.publish_drive_msg(angle)

        self.pose_previous = self.pose_current

        end_time = time.time_ns() / 10**9
        self.cycle_times.append(end_time - start_time)
        # rospy.loginfo_throttle(15, f"{np.mean(self.cycle_times)}")

    def is_first_move(self) -> bool:
        """
            Returns true is no previous pose or if no target
        """
        return self.pose_previous is None or self.global_tar_x is None or self.global_tar_y is None

    def is_not_moving(self, error: float = 0.00003) -> bool:
        """
            Returns true if current pos is different than last pos

            Use a tight error tolerance as the car's position updates often
        """

        return float_equal_double(self.global_curr_x, self.pose_previous.position.x, self.global_curr_y,
                                   self.pose_previous.position.y, error=error)

    def has_reached_target(self, error: float = 0.10) -> bool:
        """
            Returns True if car's current x AND y coords are within error of target coords
        """

        return float_equal_double(self.global_tar_x, self.global_curr_x, self.global_curr_y, self.global_tar_y,
                                   error=error)

    def calc_target_waypoint(self) -> None:
        """
            Calculates target waypoint from self.waypoints
            Assigns:
                self.global_tar_x
                self.global_tar_y
                self.local_tar_x
                self.local_tar_y

            Viable waypoints are:
                In front of the car
                Not behind an object
        """

        # Convert global coords to local coords (of the car)
        # Then filter out unviable ones (Eg behind car)
        # Then find best one
        self.target_dist_diff = float("inf")

        for i, row in self.global_waypoints.iterrows():
            local_x, local_y = self.global_to_local_coords(row[0], row[1])

            # Anywhere in front of the car (But not underneath)
            if local_x > 0 or (local_x >= 0 and local_y != 0):
                # Within the angle range (Angle is from the +X axis in front of the car)
                if local_y == 0.0 or tan(local_x/local_y) < self.VIABLE_WAYPOINT_ANGLE:
                    dist_from_car = self.distance_to_point(local_x, local_y)
                    diff_dist_lookahead = dist_from_car - self.lookahead_dist

                    # If better than previous (Closer to lookahead)
                    if abs(diff_dist_lookahead) < abs(self.target_dist_diff):

                        # If not behind a wall
                        if self.waypoint_not_blocked(local_x, local_y):
                            self.target_dist_diff = diff_dist_lookahead

                            self.global_tar_x = row[0]
                            self.global_tar_y = row[1]

                            self.local_tar_x = local_x
                            self.local_tar_y = local_y

        if self.local_tar_x is None:
            rospy.logerr(f"No Viable Waypoints\n"
                         f"Global Waypoints: {self.global_waypoints}\n\n")
            exit()

    def waypoint_not_blocked(self, x: float, y: float) -> bool:
        """
            x: Local x value of waypoint
            y: Local y value of waypoint

            Returns true if waypoint closer to car than the obstacle in that direction is
        """
        distance_to_waypoint = self.distance_to_point(x, y)
        angle_to_point = self.angle_to_point(x, y)
        index_of_target = math.ceil(angle_to_point)
        distance_to_wall = self.scan.ranges[index_of_target]

        will_hit_wall = True

        # If not directly blocked
        if distance_to_waypoint < distance_to_wall:
            will_hit_wall = False

            # Check if edge of car will clip it
            theta = math.atan((self.CAR_WIDTH / self.CAR_DIVIDER) / distance_to_waypoint)
            bubble_radius = int(math.ceil(theta / self.radians_per_elem))

            min_index = index_of_target - bubble_radius
            max_index = index_of_target + bubble_radius
            if min_index < 0:
                min_index = 0
            if max_index >= len(self.scan.ranges):
                max_index = len(self.scan.ranges) - 1

            for i, dist_wall in enumerate(self.scan.ranges[min_index: max_index]):
                # Using distance_to_waypoint isn't exactly mathematically correct but will do
                if dist_wall < distance_to_waypoint:
                    will_hit_wall = True

        return not will_hit_wall

    def angle_to_point(self, x:float, y: float) -> float:
        angle = atan2(y, x)
        return angle

    def distance_to_point(self, x: float, y: float) -> float:
        """
            Calculates the distance to the given point assuming all coordinates are local
            All returned values will be positive
            Returns sqrt(x ** 2 + y ** 2)
        """
        return sqrt(x ** 2 + y ** 2)

    def calc_drive_angle(self) -> float:
        """
            Calculates the desired drive angle of the car in order to reach the waypoint

            Returns: The angle in radians. In range [-pi, +pi)
        """

        """
        Paper used:
        https://www.ri.cmu.edu/pub_files/pub3/coulter_r_craig_1992_1/coulter_r_craig_1992_1.pdf

        Curvature = 2x / L^2
        => 2x / (x^2 + y^2)
        Where:
            x = Distance between target's x coords and cars (Car's coord is 0,0 as local coords)
            L = Lookahead distance of the car to find waypoints
                OPTIONAL: Replaced with distance between car and point to increase accuracy
        """

        waypoint_x = self.local_tar_x
        waypoint_y = self.local_tar_y

        # lookahead can be replaced with (target_dist_diff + lookahead) as lookahead will not be exactly equal to the
        # actual distance "L"
        distance = self.distance_to_point(waypoint_x, waypoint_y)

        if distance == 0 or waypoint_x == 0:
            rospy.logerr(f"Distance to target waypoints is 0. This means target waypoint is beneath car. "
                         f"This should not happen")
            return 0

        curvature = 2 * waypoint_y / distance ** 2  # Curvature with +X in straight line and Y left and right
        return curvature

    def publish_drive_msg(self, angle: float) -> None:
        """
            Publish the final steering angle and speed to self.DRIVE_TOPIC
            Speed is determined by:
                self.STRAIGHTS_STEERING_ANGLE
                self.CORNERS_SPEED
                self.STRAIGHTS_SPEED
        """

        if abs(angle) > self.STRAIGHTS_STEERING_ANGLE:
            speed = self.CORNERS_SPEED
        else:
            speed = self.STRAIGHTS_SPEED

        drive_msg = AckermannDriveStamped()
        drive_msg.header.stamp = rospy.Time.now()
        drive_msg.header.frame_id = "laser"

        drive_msg.drive.steering_angle = angle
        drive_msg.drive.speed = speed

        self.drive_publisher.publish(drive_msg)

    def global_to_local_coords(self, tar_x: float, tar_y: float, log: bool = False) -> (float, float):
        # https://gamedev.stackexchange.com/a/109377
        # Checked this answer and think is correct

        x = tar_x - self.global_curr_x
        y = tar_y - self.global_curr_y

        # Uses constants calculated in pose_callback to speed up calculations
        loc_x = (x * self.cos_theta) + (y * self.sin_theta)
        loc_y = (-x * self.sin_theta) + (y * self.cos_theta)

        return loc_x, loc_y

    def local_to_global_coords(self, x: float, y: float) -> (float, float):
        # https://gamedev.stackexchange.com/a/109377
        # Checked this answer and think is correct

        # Uses constants calculated in pose_callback to speed up calculations
        global_x = (x * self.cos_theta) - (y * self.sin_theta) + self.global_curr_x
        global_y = (x * self.sin_theta) + (y * self.cos_theta) + self.global_curr_y

        return global_x, global_y

def float_equal(val1: float, val2: float, error: float = 0.05) -> bool:
    """
        Returns True if val1 and val2 are within error
    """
    return val1 - error <= val2 <= val1 + error

def float_equal_double(x1: float, x2: float, y1: float, y2: float, alt_inputs: bool = False,
                       error: float = 0.05) -> bool:
    """
        Returns True if x1 and x2 are the within error AND y1 and y2 are within error
        If alt_inputs is true compares x1/y1 AND x2/y2 instead
    """
    if alt_inputs:
        return float_equal(x1, y1, error=error) and float_equal(x2, y2, error=error)
    return float_equal(x1, x2, error=error) and float_equal(y1, y2, error=error)

def main(args: list) -> None:
    # https://vinesmsuic.github.io/2020/09/29/robotics-purepersuit/#importance-of-visualizations
    # Interesting way to smooth waypoints

    rospy.init_node("pure_pursuit_improv", anonymous=True)

    # Load raceline (The path to follow on this map)
    map_uri = args[1]

    # Uncomment to use race line
    # raceline_uri = map_uri.replace("map.yaml", "raceline.csv")
    # waypoints = pd.read_csv(raceline_uri, delimiter=";", dtype=float, header=2)
    # waypoints.rename(columns={" x_m": "x", " y_m": "y"}, inplace=True)
    # waypoints = waypoints[["x", "y"]]

    # Uncomment to use centre line
    raceline_uri = map_uri.replace("map.yaml", "centerline.csv")
    waypoints = pd.read_csv(raceline_uri, delimiter=",", dtype=float, header=0)
    waypoints.rename(columns={"# x_m": "x", " y_m": "y"}, inplace=True)

    PurePursuit(waypoints)

    rospy.spin()

if __name__ == '__main__':
    print("PPi running...")
    try:
        main(sys.argv)
    except rospy.ROSInterruptException:
        pass


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from collections import defaultdict
import numpy as np

class NaiveBayesClassifier(object):

	def train(self, dataset, classes):
		''' train naive bayes classifier
		'''

		# sorted by classes
		sub_datasets = defaultdict(lambda: [])
		cls_cnt = defaultdict(lambda: 0)

		for doc_vect, cls in zip(dataset, classes):
			sub_datasets[cls].append(doc_vect)
			cls_cnt[cls] += 1

		# compute classes prob
		cls_probs = {k: v/len(classes) for k, v in cls_cnt.items()}

		# compute conditional prob
		cond_probs = {}
		dataset = np.array(dataset)

		for cls, sub_dataset in sub_datasets.items():
			sub_dataset = np.array(sub_dataset)
			cond_prob_vect = np.log((np.sum(sub_dataset, axis=0) + 1)/(np.sum(dataset) + 2))
			cond_probs[cls] = cond_prob_vect

		return cond_probs, cls_probs

	def classify(self, doc_vect, cond_probs, cls_probs):
		''' use naive bayes classifier to classify
		'''

		pred_probs = {}

		for cls, cls_prob in cls_probs.items():
			cond_prob_vect = cond_probs[cls]
			pred_probs[cls] = np.sum(cond_prob_vect*doc_vect) + np.log(cls_prob)

		return max(pred_probs, key=pred_probs.get)


#!/usr/bin/env python3
import os
import time
import random
import argparse

import pandas as pd
from langdetect import *
from lxml import etree

from parsers import log
from parsers import utils, config

# def parse_arguments():
#     parser = argparse.ArgumentParser()
#     parser.add_argument('--own-name', dest='own_name', type=str,
#                         help='name of the owner of the chat logs, written as in the logs', required=True)
#     parser.add_argument('-f', '--file-path', dest='file_path', help='Facebook chat log file (HTML file)',
#                         default=config.DEFAULT_MESSENGER_RAW_FILE)
#     parser.add_argument('--max', '--max-exported-messages', dest='max_exported_messages', type=int,
#                         default=config.MAX_EXPORTED_MESSAGES, help='maximum number of messages to export')
#     args = parser.parse_args()
#     return args

def main():
    maxExportedMessages = 1000000
    ownName = 'Stefan'
    # filePath = "D:PythonData/FacebookData/Tina/"
    filePath = "D:PythonData/FacebookData/Alina/"

    fallbackDateParsing = False
    data = []
    warnedNameChanges = []
    nbInvalidSender = 0

    # make sure we don't crash if chat logs contain exotic characters
    etree.set_default_parser(etree.XMLParser(encoding='utf-8', ns_clean=True, recover=True))

    for filename in os.listdir(filePath):

        if not filename.endswith('.html'):
            continue

        document = os.path.join(filePath, filename)
        archive = etree.parse(document)

        conversationId = filename.replace('.html', '')
        groupConversation = False
        timestamp = ''
        senderName = ''
        conversationWithName = None

        for element in archive.iter():
            tag = element.tag
            className = element.get('class')
            content = element.text

            if tag == 'p':
                text = content

                if conversationWithName != '' and senderName != '':

                    # handles when the interlocutor's name changed at some point
                    if (senderName != conversationWithName) and (senderName != ownName) and \
                            (senderName not in warnedNameChanges) and (not groupConversation):
                        if senderName not in warnedNameChanges:
                            print('\t', 'Assuming', senderName, 'is', conversationWithName)
                            warnedNameChanges.append(senderName)

                        senderName = conversationWithName

                    data += [[timestamp, conversationId, conversationWithName, senderName, text]]

                else:
                    nbInvalidSender = nbInvalidSender + 1

            elif tag == 'span':
                if className == 'user':
                    senderName = content
                elif className == 'meta':
                    try:
                        if not fallbackDateParsing:
                            timestamp = time.mktime(
                                pd.to_datetime(content, format='%A, %B %d, %Y at %H:%M%p', exact=False).timetuple())
                        else:
                            timestamp = time.mktime(pd.to_datetime(content, infer_datetime_format=True).timetuple())

                    except ValueError:
                        if not fallbackDateParsing:
                            print('Unexpected date format. '
                                  'Falling back to infer_datetime_format, parsing will be slower.')
                            timestamp = time.mktime(pd.to_datetime(content, infer_datetime_format=True).timetuple())
                            fallbackDateParsing = True
                        else:
                            raise

            elif tag == 'div' and className == 'thread':
                nbParticipants = str(element.xpath("text()")).count(', ') + 1
                if nbParticipants > 1:
                    groupConversation = True

            elif tag == 'h3':
                if conversationWithName is not None:
                    print('Something is wrong. File format changed? (multiple conversation hearder in a single file)')
                    exit(0)
                else:
                    content = content.replace('Conversation with ', '')
                    conversationWithName = content

                print(conversationId, conversationWithName, "(group?", groupConversation, ")")

            if len(data) >= maxExportedMessages:
                break

    print(len(data), 'messages parsed.')

    if nbInvalidSender > 0:
        print(nbInvalidSender, 'messages discarded because of bad ID.')

    if len(data) < 1:
        print('Nothing to save.')
        exit(0)

    log.info('Converting to DataFrame...')
    df = pd.DataFrame(data)
    df.columns = config.DATAFRAME_COLUMNS
    df['platform'] = 'messenger'

    log.info('Detecting languages...')
    df['language'] = 'unknown'
    for name, group in df.groupby(df.conversationWithName):
        sample = ''
        df2 = df[df.conversationWithName == name].dropna()

        if len(df2) > 10:
            for x in range(0, min(len(df2), 100)):
                sample = sample + df2.iloc[random.randint(0, len(df2) - 1)]['text']

            print('\t', name, detect(sample), "(", len(df2), "msgs)")
            df.loc[df.conversationWithName == name, 'language'] = detect(sample)

    log.info('Computing dates...')
    df['datetime'] = df['timestamp'].apply(utils.timestamp_to_ordinal)

    print(df.head())
    utils.export_dataframe(df, 'messenger.pkl')
    log.info('Done.')

if __name__ == '__main__':
    main()


from django.db import models
from mongoengine import *
from mongoengine import connect
from django.core.paginator import Paginator
connect('djweb', host='127.0.0.1', port=27017)

# Create your models here.

class ArticleInfo(Document):
    des = StringField()
    title = StringField()
    score = StringField()
    tags = ListField(StringField())
    meta = {'collection' : 'djinfo1'}

for i in ArticleInfo.objects[:4]: # equal to limit(1)
    print(i.title, i.des, i.score, i.tags)

print("################################")
iter = 'sdfjowejqwjrkwj;efkjdskjf;sj'
paginator = Paginator(iter, 4) # can only display 4 items per page
page1 = paginator.page(1)
page2 = paginator.page(2)
print(page1.object_list)
print(page2.object_list)
print(page2.paginator.num_pages)


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import abc
from scipy.ndimage import gaussian_filter
import numpy as np

class AffinityRefinementOperation(metaclass=abc.ABCMeta):
    def check_input(self, X):
        """Check the input to the refine() method.

        Args:
            X: the input to the refine() method

        Raises:
            TypeError: if X has wrong type
            ValueError: if X has wrong shape, etc.
        """
        if not isinstance(X, np.ndarray):
            raise TypeError("X must be a numpy array")
        shape = X.shape
        if len(shape) != 2:
            raise ValueError("X must be 2-dimensional")
        if shape[0] != shape[1]:
            raise ValueError("X must be a square matrix")

    @abc.abstractmethod
    def refine(self, X):
        """Perform the refinement operation.

        Args:
            X: the affinity matrix, of size (n_samples, n_samples)

        Returns:
            a matrix of the same size as X
        """
        pass

class CropDiagonal(AffinityRefinementOperation):
    """Crop the diagonal.

    Replace diagonal element by the max non-diagonal value of row.
    After this operation, the matrix has similar properties to a standard
    Laplacian matrix.
    This also helps to avoid the bias during Gaussian blur and normalization.
    """

    def refine(self, X):
        self.check_input(X)
        Y = np.copy(X)
        np.fill_diagonal(Y, 0.0)
        di = np.diag_indices(Y.shape[0])
        Y[di] = Y.max(axis=1)
        return Y

class GaussianBlur(AffinityRefinementOperation):
    """Apply Gaussian blur."""

    def __init__(self, sigma=1):
        self.sigma = sigma

    def refine(self, X):
        self.check_input(X)
        return gaussian_filter(X, sigma=self.sigma)

class RowWiseThreshold(AffinityRefinementOperation):
    """Apply row wise thresholding."""

    def __init__(self,
                 p_percentile=0.95,
                 thresholding_soft_multiplier=0.01,
                 thresholding_with_row_max=False):
        self.p_percentile = p_percentile
        self.multiplier = thresholding_soft_multiplier
        self.thresholding_with_row_max = thresholding_with_row_max

    def refine(self, X):
        self.check_input(X)
        Y = np.copy(X)

        if self.thresholding_with_row_max:
            # row_max based thresholding
            row_max = Y.max(axis=1)
            row_max = np.expand_dims(row_max, axis=1)
            is_smaller = Y < (row_max * self.p_percentile)
        else:
            # percentile based thresholding
            row_percentile = np.percentile(Y, self.p_percentile * 100, axis=1)
            row_percentile = np.expand_dims(row_percentile, axis=1)
            is_smaller = Y < row_percentile

        Y = (Y * np.invert(is_smaller)) + (Y * self.multiplier * is_smaller)
        return Y

class Symmetrize(AffinityRefinementOperation):
    """The Symmetrization operation."""

    def refine(self, X):
        self.check_input(X)
        return np.maximum(X, np.transpose(X))

class Diffuse(AffinityRefinementOperation):
    """The diffusion operation."""

    def refine(self, X):
        self.check_input(X)
        return np.matmul(X, np.transpose(X))

class RowWiseNormalize(AffinityRefinementOperation):
    """The row wise max normalization operation."""

    def refine(self, X):
        self.check_input(X)
        Y = np.copy(X)
        row_max = Y.max(axis=1)
        Y /= np.expand_dims(row_max, axis=1)
        return Y


# %% [markdown]
# # Plots for comparison on ALD dataset with 20% add MAR values

# %%
from pathlib import Path
import matplotlib.pyplot as plt
import pandas as pd

import vaep
plt.rcParams['figure.figsize'] = [4, 2]  # [16.0, 7.0] , [4, 3]
vaep.plotting.make_large_descriptors(5)

COLORS_TO_USE_MAPPTING = vaep.plotting.defaults.color_model_mapping

def plot_qvalues(df, x: str, y: list, ax=None, cutoff=0.05,
                 alpha=1.0, style='.', markersize=3):
    ax = df.plot.line(x=x,
                      y=y,
                      style=style,
                      ax=ax,
                      color=COLORS_TO_USE_MAPPTING,
                      alpha=alpha,
                      markersize=markersize)
    _ = ax.hlines(cutoff,
                  xmin=ax.get_xlim()[0],
                  xmax=ax.get_xlim()[1],
                  linestyles='dashed',
                  color='grey',
                  linewidth=1)
    return ax

# %% [markdown]
# DA analysis

# %%
out_folder = 'runs/appl_ald_data/plasma/proteinGroups_80%_dataset/diff_analysis/kleiner/'
out_folder = Path(out_folder)

# %%
files_out = dict()
fname = out_folder / 'ald_reduced_dataset_plots.xlsx'
files_out[fname.name] = fname.as_posix()
writer = pd.ExcelWriter(fname)

# %% [markdown]
# Ordering of model and reference model

# %%
ORDER_MODELS = pd.read_csv(
    out_folder.parent.parent / 'figures/performance_test.csv',
    index_col=0
).index.to_list()
ORDER_MODELS

# %%
# overwrite for now to align with Fig. 3
ORDER_MODELS = ['DAE', 'VAE', 'rf', 'CF', 'KNN', 'Median', 'None']
REF_MODEL = 'None (100%)'
CUTOFF = 0.05

# %% [markdown]
# Load dumps

# %%
da_target = pd.read_pickle(out_folder / 'equality_rejected_target.pkl')
da_target.describe()

# %%
qvalues = pd.read_pickle(out_folder / 'qvalues_target.pkl')
qvalues

# %% [markdown]
# take only those with different decisions

# %%
da_target = da_target.drop('RSN', axis=1)
da_target_same = (da_target.sum(axis=1) == 0) | da_target.all(axis=1)
da_target_same.value_counts()

# %%
feat_idx_w_diff = da_target_same[~da_target_same].index
feat_idx_w_diff

# %%
qvalues_sel = (qvalues
               .loc[feat_idx_w_diff]
               .sort_values(('None', 'qvalue')
                            ))

# %%
da_target_sel = da_target.loc[qvalues_sel.index]
da_target_sel

# %% [markdown]
# ## Diff. abundant => not diff. abundant

# %%
mask_lost_sign = (
    (da_target_sel['None'] == False)
    & (da_target_sel[REF_MODEL] == True)
)
sel = qvalues_sel.loc[mask_lost_sign.squeeze()]
sel.columns = sel.columns.droplevel(-1)
sel = sel[ORDER_MODELS + [REF_MODEL]]
sel.to_excel(writer, sheet_name='lost_signal_qvalues')
sel

# %%
# 0: FN
# 1: TP
da_target_sel_counts = (da_target_sel[ORDER_MODELS]
 .loc[mask_lost_sign.squeeze()]
 .astype(int)
 .replace(
     {0: 'FN',
      1: 'TP'}
 ).droplevel(-1, axis=1)
)
da_target_sel_counts = vaep.pandas.combine_value_counts(da_target_sel_counts)
ax = da_target_sel_counts.T.plot.bar()
ax.locator_params(axis='y', integer=True)
fname = out_folder / 'lost_signal_da_counts.pdf'
files_out[fname.name] = fname.as_posix()
vaep.savefig(ax.figure, fname)

# %%
ax = plot_qvalues(df=sel,
                  x=REF_MODEL,
                  y=ORDER_MODELS,
                  cutoff=CUTOFF)
ax.set_xlim(-0.0005, CUTOFF + 0.0005)
ax.set_xlabel("q-value using 100% of the data without imputation")
ax.set_ylabel("q-value using 80% of the data")
fname = out_folder / 'lost_signal_qvalues.pdf'
files_out[fname.name] = fname.as_posix()
vaep.savefig(ax.figure, fname)

# %% [markdown]
# ## Not diff. abundant => diff. abundant

# %%
mask_gained_signal = (
    (da_target_sel['None'] == True)
    & (da_target_sel[REF_MODEL] == False)
)
sel = qvalues_sel.loc[mask_gained_signal.squeeze()]
sel.columns = sel.columns.droplevel(-1)
sel = sel[ORDER_MODELS + [REF_MODEL]]
sel.to_excel(writer, sheet_name='gained_signal_qvalues')
sel

# %%
da_target_sel_counts = (da_target_sel[ORDER_MODELS]
 .loc[mask_gained_signal.squeeze()]
 .astype(int)
 .replace(
     {0: 'TN',
      1: 'FP'}
 ).droplevel(-1, axis=1)
)
da_target_sel_counts = vaep.pandas.combine_value_counts(da_target_sel_counts)
ax = da_target_sel_counts.T.plot.bar()
ax.locator_params(axis='y', integer=True)
fname = out_folder / 'gained_signal_da_counts.pdf'
files_out[fname.name] = fname.as_posix()
vaep.savefig(ax.figure, fname)

# %%
ax = plot_qvalues(sel,
                  x=REF_MODEL,
                  y=ORDER_MODELS)
ax.set_xlim(CUTOFF - 0.01, sel[REF_MODEL].max() + 0.005)
ax.set_xlabel("q-value using 100% of the data without imputation")
ax.set_ylabel("q-value using 80%")
ax.legend(loc='upper center')
fname = out_folder / 'gained_signal_qvalues.pdf'
files_out[fname.name] = fname.as_posix()
vaep.savefig(ax.figure, fname)

# %% [markdown]
# Saved files

# %%
writer.close()
files_out

# %%


#!/usr/bin/env python3
from __future__ import annotations

import shlex
import shutil
import subprocess
from abc import ABCMeta, abstractmethod

from .dto import TrackedConfigurationDTO
from ..common.singleton import Singleton
from ..common.utils import get_real_gid, get_real_uid
from ..repository import Repository
from ..repository.dao import ConfigurationHandler, ConfigurationStrategy, ScannedConfiguration, TrackedConfiguration

__all__ = [
    "ConfigurationService"
]

class ConfigurationService(metaclass=Singleton):
    def __init__(self):
        self.repository: Repository = Repository()

        self.handlers = (
            GSettingsConfigurationHandler,
        )

    def check(self) -> list[TrackedConfigurationDTO]:
        result = []
        for handler in self.get_handlers():
            result.extend(handler.check())

        return sorted(result, key=lambda c: (c.handler.value, c.key))

    def get_handlers(self, dry_run: bool = False) -> list[BaseConfigurationHandler]:
        return [h(dry_run) for h in self.handlers if h.is_available()]

    def restore(self, dry_run: bool = False) -> None:
        for handler in self.get_handlers(dry_run):
            handler.restore()

    def scan(self) -> None:
        result = []
        for handler in self.get_handlers():
            result.extend(handler.scan())

        self.repository.set_scanned_configurations(result)

    def set(self, conf: TrackedConfiguration) -> None:
        self.repository.set_tracked_configuration(conf)

class BaseConfigurationHandler(metaclass=ABCMeta):
    def __init__(self, handler: ConfigurationHandler, dry_run: bool = False):
        self.dry_run = dry_run
        self.handler = handler
        self.repository = Repository()

    def check(self) -> list[TrackedConfigurationDTO]:
        previous_configurations = self.repository.get_scanned_configurations(handler=self.handler)
        previous_configurations = {conf.key: conf.value for conf in previous_configurations.values()}

        if not previous_configurations:
            return []

        current_configurations = self._get_system_configurations()

        tracked_configurations = self.repository.get_tracked_configurations(handler=self.handler)
        tracked_configurations = {c.key: c for c in tracked_configurations.values()}

        detected_configurations = {}
        for key, current in current_configurations.items():
            detected = TrackedConfigurationDTO(current=current, handler=self.handler, key=key)
            if key in previous_configurations:
                detected.previous = previous_configurations[key]

            if detected.current != detected.previous:
                if key in tracked_configurations:
                    detected.strategy = tracked_configurations[key].strategy
                detected_configurations[key] = detected

        for key, previous in previous_configurations.items():
            if key not in current_configurations:
                detected = TrackedConfigurationDTO(handler=self.handler, key=key, previous=previous)
                if key in tracked_configurations:
                    detected.strategy = tracked_configurations[key].strategy

                detected_configurations[key] = detected

        return [*detected_configurations.values()]

    @abstractmethod
    def _get_system_configurations(self) -> dict[str, str]:
        pass

    @staticmethod
    @abstractmethod
    def is_available() -> bool:
        pass

    def restore(self) -> None:
        previous_configurations = self.repository.get_scanned_configurations(handler=self.handler)
        previous_configurations = {c.key: c.value for c in previous_configurations.values()}

        if not previous_configurations:
            return

        current_configurations = self._get_system_configurations()

        tracked_configurations = self.repository.get_tracked_configurations(handler=self.handler)
        tracked_configurations = {c.key: c for c in tracked_configurations.values()}

        for key, previous in previous_configurations.items():
            if key not in tracked_configurations:
                continue

            current = current_configurations.get(key)
            strategy = tracked_configurations[key].strategy

            if strategy == ConfigurationStrategy.Track and current != previous:
                self._restore_configuration(key, previous)

    @abstractmethod
    def _restore_configuration(self, key: str, value: str) -> None:
        pass

    def scan(self) -> list[ScannedConfiguration]:
        configurations = self._get_system_configurations()
        return [ScannedConfiguration(key=key, handler=self.handler, value=value)
                for key, value in configurations.items()]

class GSettingsConfigurationHandler(BaseConfigurationHandler):
    def __init__(self, dry_run: bool = False):
        super().__init__(ConfigurationHandler.GSettings, dry_run)

    def _restore_configuration(self, key: str, value: str) -> None:
        schema, key = key.rsplit(".", 1)
        command = ["gsettings", "set", schema, key, value]
        print(f"# {shlex.join(command)}")
        if not self.dry_run:
            subprocess.run(command, group=get_real_gid(), stdin=subprocess.DEVNULL, user=get_real_uid())

    def _get_system_configurations(self) -> dict[str, str]:
        result = {}
        dump = subprocess.check_output(["gsettings", "list-recursively"], group=get_real_gid(),
                                       stdin=subprocess.DEVNULL, text=True, user=get_real_uid())
        dump = dump.strip().split("\n")
        for line in dump:
            line = line.strip().split(maxsplit=2)
            result[f"{line[0]}.{line[1]}"] = line[2]

        return result

    @staticmethod
    def is_available() -> bool:
        return bool(shutil.which("gsettings"))


import logging
from datetime import datetime, timezone

from django.db import models

logger = logging.getLogger(__name__)

class Task(models.Model):
    """Task model used to define tasks that will be run as cron jobs """

    FAILED = 'FAILED'
    IN_PROGRESS = 'IN_PROGRESS'
    SLEEPING = 'SLEEPING'
    SUCCESS = 'SUCCESS'

    CURRENT_STATUS = (
        (FAILED, 'Failed'),
        (IN_PROGRESS, 'In Progress'),
        (SLEEPING, 'Sleeping'),
        (SUCCESS, 'Success')
    )

    name = models.CharField(max_length=255, help_text='The human readable name of the task')
    registered_task = models.ForeignKey('sidekick.RegisteredTask', null=True, blank=True, on_delete=models.CASCADE)
    cron_schedule = models.ForeignKey('sidekick.CronSchedule', null=True, blank=True, on_delete=models.DO_NOTHING)
    enabled = models.BooleanField(default=False, help_text='Whether the task is enabled')
    status = models.CharField(max_length=11, choices=CURRENT_STATUS, default=SLEEPING)
    started_at = models.DateTimeField(null=True, blank=True)
    finished_at = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        """Task Pre Save"""
        if not self.registered_task or not self.cron_schedule:
            self.enabled = False

        super(Task, self).save(*args, **kwargs)

        """Task Post Save"""
        try:
            from sidekick.services.cron_files import CronService
            CronService().generate_cron_tasks()
        except Exception as e:
            logger.error(msg='Failed to generate cron task for {} due to {}'.format(self, e))

    def task_of(self):
        """The app which this task belongs to """
        return self.registered_task.task_name.split(' ')[0]

    def running_for(self):
        """How long has the current task been running for"""
        if self.status == self.IN_PROGRESS:
            now = datetime.now(timezone.utc)
            difference = now - self.started_at
            prefix = "Running for"
        elif self.started_at and self.finished_at:
            difference = self.finished_at - self.started_at
            if self.status == self.FAILED:
                prefix = "Failed after"
            else:
                prefix = "Completed in"
        else:
            return "Not currently running."
        days, seconds = difference.days, difference.seconds
        hours = days * 24 + seconds // 3600
        minutes = (seconds % 3600) // 60
        seconds = seconds % 60
        return "{} {} hours, {} minutes, {} seconds".format(prefix, hours, minutes, seconds)

class CronSchedule(models.Model):
    """Cron Schedule model for defining different time intervals """

    name = models.CharField(max_length=100, help_text='Human readable version of schedule, i.e Every 10 minutes')
    minute = models.CharField(max_length=100, help_text='At what minute. * for every', default='*')
    hour = models.CharField(max_length=100, help_text='At what hour. * for every', default='*')
    day_of_week = models.CharField(max_length=100, help_text='At what day of the week. * for every', default='*')
    day_of_month = models.CharField(max_length=100, help_text='At what day of the month. * for every', default='*')
    month_of_year = models.CharField(max_length=100, help_text='At what month of the year. * for every', default='*')

    def __str__(self):
        return self.name

    def schedule(self):
        return "{} {} {} {} {}".format(self.minute, self.hour, self.day_of_month, self.month_of_year, self.day_of_week)

class RegisteredTask(models.Model):
    """Model for the registered task to be used by the Task Model """

    task_name = models.CharField(max_length=125, help_text='The task to be run ie. stock --get_stock_updates')

    def __str__(self):
        return self.task_name.replace('--', ' - ').replace('_', ' ')