import roslibpy
import numpy as np
import quaternion
import time

import ros_mobile_client as rmc
from grounded_action import GroundedAction, GroundedActionPool, GroundedStep
import area_globalization as ag
from occupancygrid_tools import AreaChecker

from typing import List, Dict, Sequence

import matplotlib.pyplot as plt
# %matplotlib inline

COLOR_OBSTACLE = 100
COLOR_UNKNOWN = -1
COLOR_PASSABLE = 0

obs_thresh = 3
unk_thresh = 3
view_options = 10
view_r = 6

sel_count = 3

def random_select(l: Sequence, c: int=sel_count) -> List:
    return [l.pop(np.random.randint(len(l))) for i in range(min(len(l), c))]

class AreaSelection(GroundedAction):
    def _gen_candidates(self) -> GroundedStep:
        obs = ag.get_obstacles(self.mc.map_data, obs_thresh, COLOR_OBSTACLE)
        filterd = list(filter(lambda o: o.convex_area>0, obs))
        sel = random_select(filterd)

        gs = [s.convex_gravity for s in sel]
        gsxy = [self.mc.get_coordinates_from_index(g) for g in gs]

        pos = [np.quaternion(0,g[0],g[1],0) for g in gsxy]
        ori = [self.mc.orientation for n in range(len(pos))]
        are = [s.convex_area for s in sel]

        return GroundedStep(self, pos=pos, ori=ori, are=are)

    def _evaluate(self, candidates: GroundedStep) -> GroundedStep:
        if len(candidates.candidates)==0: return candidates
        are = candidates.candidates['are']
        areasum = sum(are)

        for i in range(len(are)):
            ev = are[i]/areasum*np.random.random()
            candidates.evaluations[i] = ev

        candidates.selected_cand_id = np.argmax(candidates.evaluations)
        return candidates

class Observation(GroundedAction):
    def _gen_candidates(self):
        obs = ag.get_obstacles(self.mc.map_data, obs_thresh, COLOR_OBSTACLE)
        print(f'found obstacles: {len(obs)}')
        selob = random_select(obs)
        selob = selob[np.argmin([o.convex_area for o in selob])]
        print(f'selected: {selob.convex_gravity}')
        del obs

        selob_r = selob.diameter/2
        selob_vec = selob_r+view_r
        selob_g_qua = np.quaternion(0,selob.convex_gravity[0],selob.convex_gravity[1],0)

        yaws = np.random.random([view_options])*(np.pi*2)
        qs = np.array([quaternion.from_euler_angles(0,0,y) for y in yaws])
        vs = np.array([np.quaternion(0,selob_vec,0,0) for _ in range(view_options)])

        vecs = list(filter(lambda q: 0<=q.x and q.x<self.mc.map_data.shape[0] and 0<=q.y and q.y<self.mc.map_data.shape[1], selob_g_qua+qs*vs*qs.conj()))
        print(f'1 filterd vecs: {vecs}')
        vecs = list(filter(lambda q: self.mc.map_data[int(q.x),int(q.y)]==COLOR_PASSABLE, vecs))
        print(f'2 filterd vecs: {vecs}')
        sel = random_select(vecs)

        pos = [self.mc.get_coordinates_from_index((q.x, q.y)) for q in sel]
        posq = [np.quaternion(0,p[0],p[1],0) for p in pos]
        ori = [self.mc.get_relative_orientation(selob_g_qua-q) for q in sel]
#         ori = [self.mc.orientation for _ in sel]

        return GroundedStep(self, pos=posq, ori=ori)

    def _evaluate(self, candidates: GroundedStep):
        if len(candidates.candidates)==0: return candidates
        ## all random evaluation
        evas = np.random.random([len(candidates.candidates['pos'])])
        evsum = np.sum(evas)
        candidates.evaluations = evas/evsum
        candidates.selected_cand_id = np.argmax(candidates.evaluations)
        return candidates

class MapExploration(GroundedAction):
    def _gen_candidates(self):
        ac = AreaChecker(self.mc.map_data, self.mc.get_index_from_coordinates(self.mc.position))
        print(np.unique(ac.color_map), ac.color_map.shape)
        unks = ag.get_obstacles(ac.color_map, unk_thresh, COLOR_UNKNOWN)
        print(f'found unknown area: {len(unks)}')
        sel = random_select(unks)

        gs = [s.convex_gravity+ac.start for s in sel]
        print(f'gs: {gs}')
        gsxy = [self.mc.get_coordinates_from_index(g) for g in gs]

        pos = [np.quaternion(0,g[0],g[1],0) for g in gsxy]
        ori = [self.mc.get_orientation_from_body(g) for g in pos]
        are = [s.convex_area for s in sel]

        return GroundedStep(self, pos=pos, ori=ori, are=are)

    def _evaluate(self, candidates):
        if len(candidates.candidates)==0: return candidates
        are = candidates.candidates['are']
        areasum = sum(are)

        for i in range(len(are)):
            ev = 0 if areasum == 0 else are[i]/areasum
            candidates.evaluations[i] = ev

        candidates.selected_cand_id = np.argmax(candidates.evaluations)
        return candidates

class GAScheduler(GroundedAction):
    def __init__(self, name, client, pool):
        super().__init__(name, client)
        self.pool = pool

    def _gen_candidates(self) -> GroundedStep:
        stps = [ga.step() for ga in self.pool.pool.values()]
        return GroundedStep(self, stp=stps)

    def _evaluate(self, candidates) -> GroundedStep:
        stps = candidates.candidates['stp']
        e = np.array([0 if s.selected_cand_id==-1 else 1 for s in stps])

        ## all random evaluation
        evas = np.random.random([len(candidates.candidates['stp'])])*e
        evsum = np.sum(evas)
        candidates.evaluations = evas/evsum
        candidates.selected_cand_id = np.argmax(candidates.evaluations)
        return stps[candidates.selected_cand_id]

def main():
    rosclient = roslibpy.Ros('10.244.1.176', port=9090)
    rosclient.on_ready(lambda: print('is ROS connected: ', rosclient.is_connected))
    rosclient.run()

    mc = rmc.MobileClient(rosclient, lambda *s: print(f'【reached】 result: {s}'))
    mc.wait_for_ready()
    print(f'pos: {mc.position}, map_shape: {mc.map_data.shape}')
    ga_map = MapExploration('map_exploration', mc)
    ga_are = AreaSelection('area_selection', mc)
    ga_obs = Observation('observation', mc)

    pool_grounded = GroundedActionPool([ga_map, ga_are, ga_obs])
    ga_sched = GAScheduler('top_scheduler', mc, pool_grounded)

    mc.start()
    # ------------------------------------------------

    for i in range(10):
        s = ga_sched.step()
        pos = s.candidates['pos'][s.selected_cand_id]
        ori = s.candidates['ori'][s.selected_cand_id]

        mc.set_goal(pos, ori)
        mc.wait_for_goal_accepted()

    # ------------------------------------------------
    mc.stop()
    rosclient.terminate()
    print(f'finished {s.candidates}')

if __name__ == '__main__':
    main()


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

import oneflow as flow

BLOCK_COUNTS = [3, 4, 6, 3]
BLOCK_FILTERS = [256, 512, 1024, 2048]
BLOCK_FILTERS_INNER = [64, 128, 256, 512]

class ResnetBuilder(object):
    def __init__(self, weight_regularizer, trainable=True, training=True):
        self.weight_initializer = flow.variance_scaling_initializer(
            2, 'fan_in', 'random_normal', data_format="NCHW")
        self.weight_regularizer = weight_regularizer
        self.trainable = trainable
        self.training = training

    def _conv2d(
        self,
        name,
        input,
        filters,
        kernel_size,
        strides=1,
        padding="SAME",
        data_format="NCHW",
        dilations=1,
    ):
        weight = flow.get_variable(
            name + "-weight",
            shape=(filters, input.shape[1], kernel_size, kernel_size),
            dtype=input.dtype,
            initializer=self.weight_initializer,
            regularizer=self.weight_regularizer,
            model_name="weight",
            trainable=self.trainable,
        )
        return flow.nn.conv2d(
            input,
            weight,
            strides,
            padding,
            data_format,
            dilations,
            name=name)

    def _batch_norm(self, inputs, name=None, last=False):
        initializer = flow.zeros_initializer() if last else flow.ones_initializer()
        return flow.layers.batch_normalization(
            inputs=inputs,
            axis=1,
            momentum=0.9,  # 97,
            epsilon=1e-5,
            center=True,
            scale=True,
            trainable=self.trainable,
            training=self.training,
            gamma_initializer=initializer,
            moving_variance_initializer=initializer,
            gamma_regularizer=self.weight_regularizer,
            beta_regularizer=self.weight_regularizer,
            name=name,
        )

    def conv2d_affine(
            self,
            input,
            name,
            filters,
            kernel_size,
            strides,
            activation=None,
            last=False):
        # input data_format must be NCHW, cannot check now
        padding = "SAME" if strides > 1 or kernel_size > 1 else "VALID"
        output = self._conv2d(
            name,
            input,
            filters,
            kernel_size,
            strides,
            padding)
        output = self._batch_norm(output, name + "_bn", last=last)
        if activation == "Relu":
            output = flow.nn.relu(output)

        return output

    def bottleneck_transformation(
            self,
            input,
            block_name,
            filters,
            filters_inner,
            strides):
        a = self.conv2d_affine(
            input,
            block_name +
            "_branch2a",
            filters_inner,
            1,
            1,
            activation="Relu")

        b = self.conv2d_affine(
            a,
            block_name +
            "_branch2b",
            filters_inner,
            3,
            strides,
            activation="Relu")

        c = self.conv2d_affine(
            b,
            block_name +
            "_branch2c",
            filters,
            1,
            1,
            last=True)

        return c

    def residual_block(
            self,
            input,
            block_name,
            filters,
            filters_inner,
            strides_init):
        if strides_init != 1 or block_name == "res2_0":
            shortcut = self.conv2d_affine(
                input, block_name + "_branch1", filters, 1, strides_init
            )
        else:
            shortcut = input

        bottleneck = self.bottleneck_transformation(
            input, block_name, filters, filters_inner, strides_init,
        )

        return flow.nn.relu(bottleneck + shortcut)

    def residual_stage(
            self,
            input,
            stage_name,
            counts,
            filters,
            filters_inner,
            stride_init=2):
        output = input
        for i in range(counts):
            block_name = "%s_%d" % (stage_name, i)
            output = self.residual_block(
                output,
                block_name,
                filters,
                filters_inner,
                stride_init if i == 0 else 1)

        return output

    def resnet_conv_x_body(self, input):
        output = input
        for i, (counts, filters, filters_inner) in enumerate(
            zip(BLOCK_COUNTS, BLOCK_FILTERS, BLOCK_FILTERS_INNER)
        ):
            stage_name = "res%d" % (i + 2)
            output = self.residual_stage(
                output,
                stage_name,
                counts,
                filters,
                filters_inner,
                1 if i == 0 else 2)

        return output

    def resnet_stem(self, input):
        conv1 = self._conv2d("conv1", input, 64, 7, 2)
        conv1_bn = flow.nn.relu(self._batch_norm(conv1, "conv1_bn"))
        pool1 = flow.nn.max_pool2d(
            conv1_bn,
            ksize=3,
            strides=2,
            padding="SAME",
            data_format="NCHW",
            name="pool1",
        )
        return pool1

def resnet50(
        images,
        trainable=True,
        need_transpose=False,
        training=True,
        wd=1.0 / 32768):
    weight_regularizer = flow.regularizers.l2(
        wd) if wd > 0.0 and wd < 1.0 else None
    builder = ResnetBuilder(weight_regularizer, trainable, training)
    # note: images.shape = (N C H W) in cc's new dataloader, transpose is not
    # needed anymore
    if need_transpose:
        images = flow.transpose(images, name="transpose", perm=[0, 3, 1, 2])

    with flow.deprecated.variable_scope("Resnet"):
        stem = builder.resnet_stem(images)
        body = builder.resnet_conv_x_body(stem)
        pool5 = flow.nn.avg_pool2d(
            body,
            ksize=7,
            strides=1,
            padding="VALID",
            data_format="NCHW",
            name="pool5",
        )
        fc1001 = flow.layers.dense(
            flow.reshape(pool5, (pool5.shape[0], -1)),
            units=1000,
            use_bias=True,
            kernel_initializer=flow.variance_scaling_initializer(2, 'fan_in', 'random_normal'),
            bias_initializer=flow.zeros_initializer(),
            kernel_regularizer=weight_regularizer,
            bias_regularizer=weight_regularizer,
            trainable=trainable,
            name="fc1001",
        )

    return fc1001


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

import serial
import time
from functools import reduce

MAX_ANGLE = 270
MIN_ANGLE = 0

def ListToStr(data):
    strings = "".join(map(str, data))
    return strings

def DataToStr(x, y):
    if isinstance(x, str):
        return x + chr(y)
    else:
        return chr(x) + chr(y)

con = None

def SetSerial(port="/dev/ttyUSB0"):
    global con
    con = serial.Serial(port,
                        115200,
                        parity=serial.PARITY_EVEN,
                        stopbits=serial.STOPBITS_ONE,
                        timeout=1)

class Servo:
    def __init__(self, con, addr, angle=None):
        self.con = con
        self.addr = int(addr)
        self.angle = angle
        self.bef_angle = 0
        if angle != None:
            self.Pos(angle)

    def GetId(self):
        return self.addr

    def Pos(self, angle):
        if angle > 270: angle = 270
        if angle < 0:   angle = 0
        # self.bef_angle = self.angle
        self.angle = angle
        angle = int(3500 + int((8000 * angle) / 270))
        data = reduce(DataToStr, [(0x80 | int(self.addr)), angle >> 7, angle & 0x7f])
        self.con.write(data)

        time.sleep(0.0001)
        rcv = [ord(i) for i in self.con.read(6)]
        bef_angle = rcv[-2:]
        self.bef_angle = 270.0*((bef_angle[0] << 7 | bef_angle[1] & 0x7f) - 3500)/8000
        self.con.flushInput()
        return self.bef_angle

    def GetPos(self):
        return self.angle

    def Speed(self, speed):
        self.con.flushInput()
        self.con.write(ListToStr([(0xc0 | self.addr), 0x03, speed]))
        rcv = [ord(i) for i in self.con.read(6)]
        return rcv[-1]

    def GetSpeed(self):
        self.con.flushInput()
        self.con.write(ListToStr([(0xa0 | self.addr), 0x03]))
        rcv = [ord(i) for i in self.con.read(5)]
        return rcv[-1]

    def Stretch(self, stretch):
        self.con.flushInput()
        self.con.write(ListToStr([(0xc0 | self.addr), 0x02, stretch]))
        rcv = [ord(i) for i in self.con.read(6)]
        return rcv[-1]

    def GetStretch(self):
        self.con.flushInput()
        self.con.write(ListToStr([(0xc0 | self.addr), 0x02]))
        rcv = [ord(i) for i in self.con.read(5)]
        return rcv[-1]


from django.urls import path, include

from .views import MainPageView, SPageView, TPageView, NewsFieldDetail, NewsFieldUpdate, NewsFieldDelete

urlpatterns = [
    path('', MainPageView.as_view(), name='main'),
    path('s', SPageView.as_view(), name='s'),
    path('t', TPageView.as_view(), name='t'),
    path('t/<int:pk>', NewsFieldDetail.as_view(), name='nf_detail'),
    path('t/<int:pk>/edit/', NewsFieldUpdate.as_view(), name='nf_edit'),
    path('t/<int:pk>/delete/', NewsFieldDelete.as_view(), name='nf_delete'),
]


# -*- coding: utf-8 -*-
'''
生成热力渲染图交互界面
@author: Karwai Kwok
'''

import numpy as np
from PyQt4.QtGui import QDialog, QMessageBox, QLabel, QLineEdit, QDoubleValidator, \
    QComboBox, QGridLayout, QHBoxLayout, QVBoxLayout, QPushButton, QColor, QWidget
from PyQt4.QtCore import SIGNAL, Qt
from qgis.core import QgsVectorLayer, QgsFeature, QgsPoint,\
    QgsGeometry,QgsMapLayer,QgsSymbolV2,QgsRuleBasedRendererV2,QgsMapLayerRegistry,\
    QgsHeatmapRenderer,QgsMapLayerStyleManager,QgsFeatureRequest,QgsField,\
    QgsRendererRangeV2,QgsGraduatedSymbolRendererV2,\
    QgsRendererCategoryV2,QgsCategorizedSymbolRendererV2, QgsVectorGradientColorRampV2, \
    QgsGradientStop
from MyQGIS.Contorls.LayerControls import getLayerFieldNames

#  生成热力渲染图设置交互界面
class HeatRenderUI(QDialog):
    def __init__(self, iface, layer, StyleFromLayer, parent=None, radius=u"10.000", quality=2):
        super(HeatRenderUI, self).__init__()
        self.iface = iface
        self.layer = layer
        self.parent = parent
        self.styleManager = StyleFromLayer
        if not isinstance(radius, basestring):
            self.radius = str(radius)
        else:
            self.radius = radius
        self.quality = quality

        self.initUI()

    # 初始化界面
    def initUI(self):
        self.setWindowTitle(u"话务量渲染参数设置")

        radius_label = QLabel(u"渲染半径(mm)： ")
        self.radius_text = QLineEdit(self.radius)
        radius_validator = QDoubleValidator(0.0, 99999.9999, 4, self)
        self.radius_text.setValidator(radius_validator)
        quality_label = QLabel(u"渲染质量：")
        self.quality_combobox = QComboBox()
        self.quality_combobox.addItems([u"最好", u"较好", u"平衡", u"较快", u"最快"])
        self.quality_combobox.setCurrentIndex(self.quality)
        field_label = QLabel(u"渲染字段: ")
        self.field_conbobox = QComboBox()
        # 获取字段
        field_list = getLayerFieldNames(self.layer, True)
        if not field_list:
            QMessageBox.critical(self.parent, u"错误", u"所选图层不支持该功能！")
            self.accept()
            return
        self.field_conbobox.addItems(field_list)
        name_label = QLabel(u"图例名称：")
        self.name_text = QLineEdit()

        grid = QGridLayout()
        grid.setSpacing(10)
        grid.addWidget(radius_label, 0, 0)
        grid.addWidget(self.radius_text, 0, 1)
        grid.addWidget(quality_label, 1, 0)
        grid.addWidget(self.quality_combobox, 1, 1)
        grid.addWidget(field_label, 2, 0)
        grid.addWidget(self.field_conbobox, 2, 1)
        grid.addWidget(name_label, 3, 0)
        grid.addWidget(self.name_text, 3, 1)

        button_hbox = QHBoxLayout()
        button_hbox.addStretch(1)
        ok = QPushButton(u"确定")
        self.connect(ok, SIGNAL("clicked()"), self.run)
        button_hbox.addWidget(ok)
        cancel = QPushButton(u"取消")
        self.connect(cancel, SIGNAL("clicked()"), self.accept)
        button_hbox.addWidget(cancel)
        button_hbox.addStretch(1)

        vbox = QVBoxLayout()
        vbox.setSpacing(10)
        vbox.addLayout(grid)
        vbox.addStretch(1)
        vbox.addLayout(button_hbox)

        self.setLayout(vbox)
        self.resize(300, 120)

    def run(self):
        # 非空检查
        if self.radius_text.text().strip() == u"":
            QMessageBox.critical(self, u"错误", u"请填写渲染半径！")
            return
        else:
            self.accept()
        self.radius = float(self.radius_text.text().strip())
        self.quality = self.quality_combobox.currentIndex()
        tra = QgsHeatmapRenderer()  # 设置基站为热图样式
        tra.setMaximumValue(0) # 默认渲染最大值为0（自动）
        color_ramp = QgsVectorGradientColorRampV2(QColor("white"), QColor("red"), False,
                    [QgsGradientStop(0.25, QColor("#00ffff")),
                     QgsGradientStop(0.50, QColor("#00ff00")),
                     QgsGradientStop(0.75, QColor("#ffff00"))])
        tra.setColorRamp(color_ramp)
        self.color = tra.colorRamp()
        tra.setRadius(self.radius)
        tra.setRenderQuality(self.quality)
        # 获取渲染字段
        fieldName = self.field_conbobox.currentText()
        tra.setWeightExpression(fieldName)  # 根据字段渲染
        self.layer.setRendererV2(tra)
        # 获取渲染字段的最大值
        max_value, min_value = self.getMaxAndMinValue(fieldName)
        self.iface.actionDraw().trigger()
        # 获取图例名称
        legend_name = self.name_text.text()
        legend = HeatRenderLegend(self.iface, self.styleManager, max_value, min_value, legend_name, self.parent)
        legend.show()
        legend.exec_()

    # 返回设定的参数dict
    def getSetting(self):
        Setting = {}
        Setting["radius"] = self.radius
        Setting["quality"] = self.quality
        return Setting

    # 返回阶梯详细数值
    def getMaxAndMinValue(self, fieldName):
        value_list = []
        for feature in self.layer.getFeatures():
            value_list.append(feature[fieldName])
        value_array = np.array(value_list)
        if len(value_array) == 0:
            return (0, 0)
        return (value_array.max(), value_array.min())

#  热力渲染图图例
class HeatRenderLegend(QDialog):
    def __init__(self, iface, styleManager, max_value, min_value, legend_name, parent=None):
        super(HeatRenderLegend, self).__init__()
        self.iface = iface
        self.styleManager = styleManager # 当前图层的样式管理器
        if max_value:
            self.max_value = max_value
        else:
            self.max_value = 0.0
        if min_value:
            self.min_value = min_value
        else:
            self.min_value = 0.0
        if legend_name:
            self.legend_name = legend_name
        else:
            self.legend_name = u"渲染图例"
        self.parent = parent

        delta = self.max_value - self.min_value

        self.setWindowTitle(self.legend_name)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.setWindowFlags(Qt.WindowMinimizeButtonHint)

        widget_100 = QWidget()
        widget_100.setStyleSheet('QWidget {background-color: red}')
        widget_100.resize(20, 20)
        label_100 = QLabel("%.4f" % (float(self.max_value)))

        widget_75 = QWidget()
        widget_75.setStyleSheet('QWidget {background-color: #ffff00}')
        widget_75.resize(20, 20)
        label_75 = QLabel("%.4f" % (float(delta * 0.75) + self.min_value))

        widget_50 = QWidget()
        widget_50.setStyleSheet('QWidget {background-color: #00ff00}')
        widget_50.resize(20, 20)
        label_50 = QLabel("%.4f" % (float(delta * 0.50 + self.min_value)))

        widget_25 = QWidget()
        widget_25.setStyleSheet('QWidget {background-color: #00ffff}')
        widget_25.resize(20, 20)
        label_25 = QLabel("%.4f" % float((delta * 0.25 + self.min_value)))

        grid = QGridLayout()
        grid.setSpacing(20)
        grid.addWidget(widget_100, 0, 0)
        grid.addWidget(label_100, 0, 1)
        grid.addWidget(widget_75, 1, 0)
        grid.addWidget(label_75, 1, 1)
        grid.addWidget(widget_50, 2, 0)
        grid.addWidget(label_50, 2, 1)
        grid.addWidget(widget_25, 3, 0)
        grid.addWidget(label_25, 3, 1)

        self.setLayout(grid)
        self.setGeometry(300, 300, 250, 200)

    def closeEvent(self, event):
        self.accept()
        self.styleManager.setCurrentStyle(u"默认")  ##恢复上一级样式，即取消话务量渲染
        self.iface.actionDraw().trigger()


# -------------- Begin of Helper Methods --------------
''' Reads the .txt input file and converts it into a list of type Line '''
def read_input(path: str) -> list[int]:
    with open(path) as f:
        # put the single line into an int array
        return list(map(int, f.read().split(",")))

# -------------- End of Helper Methods --------------

def part_one(input_path: str) -> int:
    numbers = read_input(input_path)
    #print("Initial state: ", numbers)
    for day in range(1,81):
        for i in range(len(numbers)):
            if numbers[i] == 0:
                numbers[i] = 6
                numbers.append(8)
                continue
            numbers[i] -= 1
        #print("After day: ", day, numbers)
    return len(numbers)

def part_two(input_path: str) -> int:
    numbers = read_input(input_path)
    #print("Initial state: ", numbers)
    for day in range(1,257):
        for i in range(len(numbers)):
            if numbers[i] == 0:
                numbers[i] = 6
                numbers.append(8)
                continue
            numbers[i] -= 1
        print("After day: ", day)
    return len(numbers)

if __name__ == "__main__":
    input_path = "./2021-python/day06/input.txt"
    print("The result of Part 1:", part_one(input_path))
    print("The result of Part 2:", part_two(input_path))


from PyQt5.QtWidgets import QMainWindow, QTableWidget, QTableWidgetItem, QApplication, QHeaderView,\
    QMessageBox, QInputDialog, QDialog

from UI import Ui_MainWindow
from binarytree import BinaryTree

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.currentTree_ = BinaryTree()
        self.currentTree_.load('BinaryTree.db')
        self.ui.editorTranslate.returnPressed.connect(self.translate)
        self.ui.editorTranslate.textChanged.connect(self.distanceSearch)
        self.ui.listDistance.itemClicked.connect(self.cclicked)
        self.ui.add.clicked.connect(self.newNode)
        self.ui.editorRu.returnPressed.connect(self.newNode)

    def newNode(self):
        in_tree = self.currentTree_.getAll()
        if self.ui.editorEn.text().lower() not in in_tree:
            if self.ui.editorEn.text() and self.ui.editorRu.text().lower():
                self.currentTree_.put(self.ui.editorEn.text().lower(), self.ui.editorRu.text().lower())
                self.ui.editorEn.clear()
                self.ui.editorRu.clear()
            else:
                if not self.ui.editorEn.text():
                    QMessageBox.about(self,
                    'Неполные данные', 'Вы не ввели слово на английском')
                if not self.ui.editorRu.text():
                    QMessageBox.about(self,
                    'Неполные данные', f'Вы не ввели слово для перевода слова {self.ui.editorEn.text()}')
        else:
            QMessageBox.about(
            self, 'Уже есть', 'В базе данных был найден перевод данного слова!!!')
            self.ui.editorEn.clear()
            self.ui.editorRu.clear()

    def translate(self):
        self.ui.labelRu.setText(self.currentTree_.translate(self.ui.editorTranslate.text()))

    def distanceSearch(self, text):
        self.ui.listDistance.clear()
        for i in self.currentTree_.search(text.lower()):
            self.ui.listDistance.addItem(i)

    def cclicked(self, item):
        self.ui.editorTranslate.setText(item.text())
        self.translate()

    def __del__(self):
        self.currentTree_.save('BinaryTree.db')


class Events:
    def __init__(self, config, template, timesheet, text_color):
        self.config = config
        self.template = template
        self.timesheet = timesheet
        self.text_color = text_color

    def read_config(self):
        import configparser
        import logging
        logger = logging.getLogger(__name__)

        config = configparser.ConfigParser()
        config.read(self.config)
        config_dump = {}
        for each_section in config.sections():
            for (each_key, each_val) in config.items(each_section):
                config_dump[each_key] = each_val
        logger.debug({"config": config_dump})
        return config

    def get_dimensions(*, image, font, item, config, key):
        import logging
        logger = logging.getLogger(__name__)

        image_width, image_height = image.size
        logger.info({
            "image": {
                "width": image_width,
                "height": image_height
            }
        })
        canvas_width, canvas_height = font.getsize(item)
        try:
            item_width = config.getint(key, 'width', fallback=0)
        except KeyError:
            item_canvas_center = int((image_width - canvas_width) / 2)
            item_left_offset = config.getint(key, 'width_offset_left', fallback=0)
            item_right_offset = config.getint(key, 'width_offset_right', fallback=0)
            item_width = item_left_offset + item_canvas_center - item_right_offset
        try:
            item_height = int(config.get(key, 'height'))
        except KeyError:
            raise
        dimensions = (item_width, item_height)
        return dimensions

    def fill(self, data, template, uuid, cert_dir):
        from datetime import datetime
        from PIL import Image
        from PIL import ImageFont
        from PIL import ImageDraw
        import logging
        logger = logging.getLogger(__name__)

        config = read_config(self)
        logger.info({
            "data": data,
        })
        img = Image.open(template)
        draw = ImageDraw.Draw(img)
        # Credits:
        # https://stackoverflow.com/questions/1970807/center-middle-align-text-with-pil

        for key, value in data.items():
            logger.info({
                key: value
            })
            item = data[key].strip()
            font_size = config.getint(key, 'font_size')
            font = ImageFont.truetype(r'./news-serif.ttf', font_size)

            item_dimensions = get_dimensions(image=img, font=font, item=item, config=config, key=key)
            item_colour = self.text_color
            draw.text(item_dimensions, item, item_colour, font=font)

        cert_name = data['name'].lower().replace(' ', '_')
        cert_path = f'{cert_dir}/{cert_name}.jpg'
        try:
            img.save(cert_path)
            img.close()
            logger.info({
                "status": "saved",
                "certificate": cert_path,
                "identifier": uuid,
                "time": str(datetime.now())
            })
        except FileNotFoundError:
            logger.error({
                "status": "error",
                "exception": "Unable to save file. Please check the given directory exists.",
                "identifier": uuid,
                "time": datetime.now()
            })
            exit(1)


import os
import datetime
from flask import url_for
from flask import Blueprint, render_template
from flask import Flask
from flask_cors import CORS
from flask_restplus import Resource, Api, fields

PATH_TO_TEMPLATES = "./tpl/"

app = Flask(__name__)

# Default web page Blueprint START #############################################

default_web = Blueprint(
    "default_web", __name__, url_prefix="", template_folder=PATH_TO_TEMPLATES
)

@default_web.context_processor
def year_for_templates():
    return {"this_year": datetime.datetime.now().year}

@default_web.route("/")
def home_page():
    return render_template("layout.html", bodyhtml="main")

# <Error pages>
@default_web.app_errorhandler(404)
def page_not_found(e):
    return render_template("errors/404.html"), 404

@default_web.app_errorhandler(500)
def internal_server_error(e):
    return render_template("errors/500.html"), 500

app.register_blueprint(default_web)
# Default web page Blueprint FINISH #############################################

# REST API Blueprint START ######################################################
swagger = Blueprint("swagger", __name__, url_prefix="/api")

# Sometimes we need to build HTTPS url for swagger documentation (e.g. in managed environments like Azure Application Service)
# In this case we need to check any environment variables from this environment (e.g. WEBSITE_HOSTNAME for Azure)
# if so - we need to [auto]build HTTPS url:
if os.environ.get("WEBSITE_RESOURCE_GROUP"):

    @property
    def specs_url(self):
        return url_for(self.endpoint("specs"), _external=True, _scheme="https")

    Api.specs_url = specs_url

api = Api(
    swagger,
    version="1.0",
    title="Sample web REST service",
    description="Access to the stored data, if any.",
    default="Services",
    default_label="All available services list:",
)

class HealthCheck(Resource):
    def get(self):
        """
        REST Service health check
        """
        return {
            "status": "Sample REST service is up",
            "build": "Build number here",
            "serverTime": str(datetime.datetime.now()),
            "tag": "#GTO",
        }

api.add_resource(HealthCheck, "/health")

app.register_blueprint(swagger)
# REST API Blueprint FINISH ######################################################

# Uncomment this line, if running in Development environment
# i.e. not with Gunicorn
# (For this demo-project - using the Development server)
#
# Despite the fact that we may be in a managed environment (e.g. Azure App Service) with HTTPS by default,
# leave the port as 80 here:
app.run(host="0.0.0.0", port="80", threaded=True)


#!/usr/bin/python

import re
import fileMaker

def wordExtractor(line):
    # first lowercase it
    line = line.lower()

    # next, remove all non [a-z ] characters; [^a-z ] is a regular
    # expression for everything except a-z and space.
    line = re.sub("[^a-z ]", " ", line)

    # split out all words, since word == feature
    words = line.split()

    # compute the features
    feats = {}
    for word in words:
        if feats.has_key(word):
            feats[word] += 1
        else:
            feats[word] = 1

    return feats

if __name__=="__main__":
    fileMaker.mainExtractor(wordExtractor)


# -> is a function annotation
# http://www.python.org/dev/peps/pep-3107/

# Check the word for a palindrome
def isPalindrome(word: str) -> bool:

    if(word == word[::-1]): # reverse the word and check
        return True
    return False

def getPalindromes(inputStr: str) -> list:

    # clean the input string and split the srings to words
    cleanStr = inputStr.replace(",","").lower()
    words = set(cleanStr.split(" "))

    # Iterate through each word and use list comprehension
    wPalindromes = [
        word for word in words
        if isPalindrome(word) and word != ""
    ]
    return wPalindromes

getPalindromes('Lol, hah This is a joke')


M = 998244353

from collections import Counter

N = 1 + 10 ** 6
v = [False] * N
spf = [1] * N

for i in range(2, N, 2):
    spf[i] = 2

for i in range(3, N, 2):
    if not v[i]:
        spf[i] = i
        j = i
        while j * i < N:
            if not v[j * i]:
                v[j * i] = True
                spf[j * i] = i
            j += 2

def facts(n, mod):
    res = [1] * (n + 1)
    ctr = Counter()
    for i in range(1, n + 1):
        a = n - i + 1
        b = i
        while a > 1:
            ctr[spf[a]] += 1
            a //= spf[a]
        while b > 1:
            ctr[spf[b]] -= 1
            b //= spf[b]
        for p in ctr:
            res[i] *= pow(p, ctr[p], mod)
            res[i] %= mod
    return res

print(*facts(1000, 18))


import ruamel.yaml.scalarstring
import scapy.all
from ruamel.yaml import YAML
import binascii

class UniqueIpSender:
    def __init__(self, ip_addr, packets_sent):
        self.ip_addr = ip_addr
        self.packets_sent = packets_sent

def get_destination_address(current_packet):
    initial_destination_address = current_packet[:12]
    final_destination_address = ""

    # insert a character after every pair of characters,
    # from https://www.geeksforgeeks.org/python-insert-character-after-every-character-pair/
    for i in range(0, len(initial_destination_address), 2):
        final_destination_address += initial_destination_address[i:i + 2] + ":"

    final_destination_address = final_destination_address[:-1]
    return final_destination_address

def get_source_address(current_packet):
    initial_source_address = current_packet[12:24]
    final_source_address = ""

    # insert a character after every pair of characters,
    # from https://www.geeksforgeeks.org/python-insert-character-after-every-character-pair/
    for i in range(0, len(initial_source_address), 2):
        final_source_address += initial_source_address[i:i + 2] + ":"

    final_source_address = final_source_address[:-1]
    return final_source_address

def get_pcap_length(pretty_packet):

    return int(len(pretty_packet)/2)

def get_medium_length(pcap_length):
    if pcap_length > 59:
        medium_length = pcap_length + 4
    else:
        medium_length = 64
    return medium_length

def get_hexa_frame(pretty_packet):
    initial_packet = pretty_packet
    hexa_packet = ""

    # insert a character after every pair of characters,
    # from https://www.geeksforgeeks.org/python-insert-character-after-every-character-pair/
    for i in range(0, len(initial_packet), 2):
        hexa_packet += initial_packet[i:i + 2] + " "
    hexa_packet = hexa_packet[:-1]

    counter = 0
    for i in range(len(hexa_packet)):
        if hexa_packet[i] == ' ':
            counter = counter + 1
            if counter % 16 == 0 and counter != 0:
                temp_list = list(hexa_packet)
                temp_list[i] = '\n'
                hexa_packet = ''.join(temp_list)

    hexa_packet = ruamel.yaml.scalarstring.LiteralScalarString(hexa_packet)

    return hexa_packet

def get_frame_type(pretty_packet):
    frame_type_hex = pretty_packet[28:32]
    frame_length = int(pretty_packet[24:28], 16)

    if frame_length > 1500:
        frame_type = "ETHERNET II"
    elif frame_type_hex == "FFFF":
        frame_type = "Novell 802.3 RAW"
    elif frame_type_hex == "AAAA":
        frame_type = "IEEE 802.3 LLC & SNAP"
    else:
        frame_type = "IEEE 802.3 LLC"

    return frame_type

def get_sap(pretty_packet, protocols):
    sap_bytes = pretty_packet[28:32]

    for sap_type, sap_value in protocols["sap"].items():
        if sap_type == sap_bytes:
            return sap_value

def get_pid(pretty_packet, protocols):
    pid_bytes = pretty_packet[40:44]

    for pid_type, pid_value in protocols["pid"].items():
        if pid_type == pid_bytes:
            return pid_value

def get_ether_type(pretty_packet, protocols):
    ether_type_bytes = pretty_packet[24:28]

    for ether_type, ether_type_value in protocols["ether_type"].items():
        if ether_type == ether_type_bytes:
            return ether_type_value

def get_source_ip_address(pretty_packet, is_arp):
    source_ip_bytes = []

    if not is_arp:
        for i in range(0, 4):
            source_ip_bytes.append(int(pretty_packet[52+(i*2):54+(i*2)], 16))
    elif is_arp:
        for i in range(0, 4):
            source_ip_bytes.append(int(pretty_packet[56+(i*2):58+(i*2)], 16))

    source_ip_address = ""
    for byte in source_ip_bytes:
        source_ip_address = source_ip_address + str(byte) + "."

    source_ip_address = source_ip_address[:-1]
    return source_ip_address

def get_destination_ip_address(pretty_packet, is_arp):
    destination_ip_bytes = []

    if not is_arp:
        for i in range(0, 4):
            destination_ip_bytes.append(int(pretty_packet[60+(i*2):62+(i*2)], 16))
    elif is_arp:
        for i in range(0, 4):
            destination_ip_bytes.append(int(pretty_packet[76+(i*2):78+(i*2)], 16))

    destination_ip_address = ""
    for byte in destination_ip_bytes:
        destination_ip_address = destination_ip_address + str(byte) + "."

    destination_ip_address = destination_ip_address[:-1]
    return destination_ip_address

def get_ipv4_protocol(pretty_packet, protocols):
    protocol_bytes = pretty_packet[46:48]

    for protocol_type, protocol_value in protocols["ipv4_protocol"].items():
        if protocol_type == protocol_bytes:
            return protocol_value

def get_src_port(pretty_packet):
    return int(pretty_packet[68:72], 16)

def get_dst_port(pretty_packet):
    return int(pretty_packet[72:76], 16)

def get_arp_opcode(pretty_packet):
    if int(pretty_packet[40:44]) == 1:
        return "REQUEST"
    else:
        return "REPLY"

def get_active_flags(pretty_packet):
    ihl_bytes = pretty_packet[29:30]
    ip_header_length = int(ihl_bytes) * 4
    flag_bytes = (ip_header_length * 2)+53
    flags = pretty_packet[flag_bytes:flag_bytes+3]
    flags = int(flags, 16)
    flags = bin(flags)[2:]

    if len(flags) < 5:
        temp_flags = flags
        missing_length = 5 - len(flags)

        flags = ""

        for i in range(0, missing_length):
            flags = flags + "0"

        flags = flags + temp_flags

    list_of_active_flags = []

    if flags[0] == "1":
        list_of_active_flags.append("ACK")
    if flags[1] == "1":
        list_of_active_flags.append("PSH")
    if flags[2] == "1":
        list_of_active_flags.append("RST")
    if flags[3] == "1":
        list_of_active_flags.append("SYN")
    if flags[4] == "1":
        list_of_active_flags.append("FIN")

    return list_of_active_flags

def get_icmp_type(pretty_packet):
    ihl_bytes = pretty_packet[29:30]
    ip_header_length = int(ihl_bytes) * 4
    icmp_start = ip_header_length*2 + 28
    if pretty_packet[icmp_start:icmp_start+2] == "08":
        return "ECHO REQUEST"
    elif pretty_packet[icmp_start:icmp_start+2] == "00":
        return "ECHO REPLY"

def get_icmp_id(pretty_packet):
    ihl_bytes = pretty_packet[29:30]
    ip_header_length = int(ihl_bytes) * 4
    icmp_start = ip_header_length * 2 + 28
    return int(pretty_packet[icmp_start + 8:icmp_start + 12], 16)

def get_icmp_seq(pretty_packet):
    ihl_bytes = pretty_packet[29:30]
    ip_header_length = int(ihl_bytes) * 4
    icmp_start = ip_header_length * 2 + 28
    return int(pretty_packet[icmp_start + 12:icmp_start + 16], 16)

def is_port_known(src_port, dst_port, protocols, ipv4_protocol):
    if ipv4_protocol == "TCP":
        for protocol_type, protocol_value in protocols["tcp_protocol"].items():
            if str(src_port) == protocol_type or str(dst_port) == protocol_type:
                return protocol_value
        return
    elif ipv4_protocol == "UDP":
        for protocol_type, protocol_value in protocols["udp_protocol"].items():
            if str(src_port) == protocol_type or str(dst_port) == protocol_type:
                return protocol_value
        return

def analyze_file(file_name):
    content = {}
    with open(file_name, 'r') as file:
        rows = file.readlines()
        current_key = None
        for row in rows:
            if row.strip() and not row.startswith(" "):
                current_key = row.strip()[:-1]
                content[current_key] = {}
            elif row.startswith("  ") and current_key:
                key, value = map(str.strip, row.strip().split(":"))
                content[current_key][key] = value
    return content

def check_for_complete_communication(communication, complete_communications, current_communications):
    if "SYN" in communication[0]["flags"] and "SYN" in communication[1]["flags"] and "ACK" in communication[1]["flags"] and "ACK" in communication[2]["flags"]:
        # Established communication
        if "RST" in communication[len(communication)-1]["flags"]:
            # Finished
            complete_communications.append(communication)
            current_communications.remove(communication)
        elif len(communication) > 6:  # Check for finish handshake
            last_index = len(communication)
            if "FIN" in communication[last_index - 4]["flags"] and "ACK" in communication[last_index - 3]["flags"] and "FIN" in communication[last_index - 2]["flags"] and "ACK" in communication[last_index - 1]["flags"]:
                # Finished
                complete_communications.append(communication)
                current_communications.remove(communication)
            elif "FIN" in communication[last_index - 2]["flags"] and "ACK" in communication[last_index - 2]["flags"] and "FIN" in communication[last_index - 1]["flags"] and "ACK" in communication[last_index - 1]["flags"]:
                complete_communications.append(communication)
                current_communications.remove(communication)
    elif "SYN" in communication[0]["flags"] and "SYN" in communication[1]["flags"] and "ACK" in communication[2]["flags"] and "ACK" in communication[3]["flags"]:
        # Established connection
        if "RST" in communication[len(communication)-1]["flags"]:
            # Finished
            complete_communications.append(communication)
            current_communications.remove(communication)
        elif len(communication) > 7:  # Check for finish handshake
            last_index = len(communication)
            if "FIN" in communication[last_index - 4]["flags"] and "ACK" in communication[last_index - 3]["flags"] and "FIN" in communication[last_index - 2]["flags"] and "ACK" in communication[last_index - 1]["flags"]:
                # Finished
                complete_communications.append(communication)
                current_communications.remove(communication)
            elif "FIN" in communication[last_index - 2]["flags"] and "ACK" in communication[last_index - 2]["flags"] and "FIN" in communication[last_index - 1]["flags"] and "ACK" in communication[last_index - 1]["flags"]:
                complete_communications.append(communication)
                current_communications.remove(communication)

def analyze_packets():
    program_mode = ""

    while program_mode != "x":
        file_name = "trace-26.pcap"  # Change file
        packet_list = scapy.all.rdpcap(f"test_pcap_files/vzorky_pcap_na_analyzu/{file_name}")
        complete_communications = []
        incomplete_communications = [[]]
        current_communications = [[]]
        arp_complete_communications = [[]]
        arp_incomplete_replies = []
        arp_incomplete_requests = []
        icmp_incomplete_requests = []
        icmp_incomplete_replies = []
        icmp_communications = [[]]
        packets = []
        packets_with_flags = []
        unique_senders = []
        protocols = analyze_file("protocols.txt")
        filter_name = ""
        results_count = 0
        program_mode = ""

        while program_mode != "f" and program_mode != "a" and program_mode != "x" and program_mode != "arp" and program_mode != "icmp":
            is_valid_filter = False
            print("Analyze all packets : 'a'\nFilter by protocol : 'f'\nAnalyze ARP packets : 'arp'\nAnalyze ICMP : 'icmp'\nExit program : 'x'\n")
            program_mode = input()

            if program_mode == "x":  # Check for Exit program
                exit()

            if program_mode == "f":
                while not is_valid_filter:
                    print("Enter filter name \nType 'x' to exit program")
                    filter_name = input()  # Get filter name
                    if filter_name == "x":  # Check for Exit program
                        exit()

                    for value in protocols["tcp_protocol"].values():  # Check if this protocol exists
                        if filter_name == value:
                            is_valid_filter = True
                            break
                    if not is_valid_filter:
                        print("Not an existing protocol!")
            if program_mode != "f" and program_mode != "a" and program_mode != "x" and program_mode != "arp" and program_mode != "icmp":
                print("Enter correct input!")

        for current_packet_number in range(0, len(packet_list)):
            packet = packet_list[current_packet_number]
            pretty_packet = binascii.hexlify(scapy.all.raw(packet)).decode()
            pretty_packet = pretty_packet.upper()

            current_frame_type = get_frame_type(pretty_packet)
            current_app_protocol = ""

            current_packet_data = [
                ('frame_number', current_packet_number+1),
                ('pcap_length', get_pcap_length(pretty_packet)),
                ('medium_length', get_medium_length(get_pcap_length(pretty_packet))),
                ('frame_type',  current_frame_type),
                ('source_mac', get_source_address(pretty_packet)),
                ('destination_mac', get_destination_address(pretty_packet))
            ]

            if current_frame_type == "ETHERNET II":
                current_ether_type = get_ether_type(pretty_packet, protocols)
                current_packet_data.append(('ether_type', current_ether_type))

                if current_ether_type == "IPv4":
                    current_src_ip = get_source_ip_address(pretty_packet, False)
                    current_packet_data.append(('src_ip', current_src_ip))
                    current_packet_data.append(('dst_ip', get_destination_ip_address(pretty_packet, False)))

                    contains = False
                    for sender in unique_senders:
                        if current_src_ip == sender.ip_addr:
                            sender.packets_sent += 1
                            contains = True
                            break
                    if not contains:
                        unique_senders.append(UniqueIpSender(current_src_ip, 1))

                    current_ipv4_protocol = get_ipv4_protocol(pretty_packet, protocols)
                    current_packet_data.append(('protocol', current_ipv4_protocol))

                    if current_ipv4_protocol == "UDP" or current_ipv4_protocol == "TCP":
                        current_src_port = get_src_port(pretty_packet)
                        current_dst_port = get_dst_port(pretty_packet)

                        current_packet_data.append(('src_port', current_src_port))
                        current_packet_data.append(('dst_port', current_dst_port))

                        known_port = is_port_known(current_src_port, current_dst_port, protocols, current_ipv4_protocol)
                        if known_port:
                            current_app_protocol = known_port
                            current_packet_data.append(('app_protocol', current_app_protocol))

                    if current_ipv4_protocol == "ICMP":
                        current_icmp_type = get_icmp_type(pretty_packet)
                        current_icmp_id = get_icmp_id(pretty_packet)
                        current_icmp_seq = get_icmp_seq(pretty_packet)

                        current_packet_data.append(('icmp_type', current_icmp_type))
                        current_packet_data.append(('icmp_id', current_icmp_id))
                        current_packet_data.append(('icmp_seq', current_icmp_seq))

                elif current_ether_type == "ARP":
                    current_arp_opcode = get_arp_opcode(pretty_packet)
                    current_packet_data.append(('arp_opcode', current_arp_opcode))
                    current_packet_data.append(('src_ip', get_source_ip_address(pretty_packet, True)))
                    current_packet_data.append(('dst_ip', get_destination_ip_address(pretty_packet, True)))

            elif current_frame_type == "IEEE 802.3 LLC":
                current_packet_data.append(('sap', get_sap(pretty_packet, protocols)))

            elif current_frame_type == "IEEE 802.3 LLC & SNAP":
                current_packet_data.append(('pid', get_pid(pretty_packet, protocols)))

            current_packet_data.append(('hexa_frame', get_hexa_frame(pretty_packet)))
            current_data = dict(current_packet_data)

            if program_mode == "f":
                if current_app_protocol == filter_name:  # Check if protocol equals filtered protocol
                    packets.append(current_data)
                    if current_frame_type == "ETHERNET II" and current_ether_type == "IPv4" and current_ipv4_protocol == "TCP":  # Flags
                        current_packet_data.append(('flags', get_active_flags(pretty_packet)))
                        current_data = dict(current_packet_data)
                        packets_with_flags.append(current_data)
                    results_count += 1
            elif program_mode == "a":
                packets.append(current_data)
                results_count += 1
            elif program_mode == "arp":
                if current_frame_type == "ETHERNET II" and current_ether_type == "ARP":
                    packets.append(current_data)
                    results_count += 1
            elif program_mode == "icmp":
                if current_frame_type == "ETHERNET II" and current_ether_type == "IPv4" and current_ipv4_protocol == "ICMP":
                    packets.append(current_data)
                    results_count += 1

        # Analyze ICMP
        if program_mode == "icmp":
            icmp_requests = []
            icmp_replies = []
            for packet in packets:
                if packet["icmp_type"] == "ECHO REQUEST":
                    icmp_requests.append(packet)
                elif packet["icmp_type"] == "ECHO REPLY":
                    icmp_replies.append(packet)
            if len(icmp_replies) == 0 or len(icmp_requests) == 0:
                if len(icmp_replies) == 0:
                    for request in icmp_requests:
                        icmp_incomplete_requests.append(request)
                elif len(icmp_requests) == 0:
                    for reply in icmp_replies:
                        icmp_incomplete_replies.append(reply)

            for reply in icmp_replies:
                for request in icmp_requests:
                    # Find the pair
                    if reply["src_ip"] == request["dst_ip"] and reply["dst_ip"] == request["src_ip"] and \
                     reply["icmp_id"] == request["icmp_id"] and reply["icmp_seq"] == request["icmp_seq"]:
                        is_new_pair = True
                        for comm in icmp_communications:
                            if len(comm) > 0:
                                if comm[0]["src_ip"] == request["src_ip"] and comm[0]["dst_ip"] == request["dst_ip"] and \
                                 comm[0]["icmp_id"] == request["icmp_id"]:
                                    comm.append(request)
                                    comm.append(reply)
                                    icmp_requests.remove(request)
                                    icmp_replies.remove(reply)
                                    is_new_pair = False
                                    break
                        if is_new_pair:
                            icmp_communications.append([request, reply])
                            icmp_requests.remove(request)
                            icmp_replies.remove(reply)
            icmp_communications.pop(0)

        # Analyze ARP
        if program_mode == "arp":
            arp_communications = [[]]
            for packet in packets:
                is_unique = True
                for arp_communication in arp_communications:
                    if len(arp_communication) > 0:
                        if packet["arp_opcode"] == "REQUEST":
                            if packet["dst_ip"] == arp_communication[0]["dst_ip"]:
                                if packet["arp_opcode"] == arp_communication[len(arp_communication)-1]["arp_opcode"]:
                                    arp_incomplete_requests.append(packet)
                                    is_unique = False
                                    break
                                else:
                                    arp_communication.append(packet)
                                    is_unique = False
                                    break
                        elif packet["arp_opcode"] == "REPLY":
                            if packet["src_ip"] == arp_communication[0]["dst_ip"]:
                                if packet["arp_opcode"] == arp_communication[len(arp_communication)-1]["arp_opcode"]:
                                    arp_incomplete_replies.append(packet)
                                    is_unique = False
                                    break
                                elif packet["dst_ip"] == arp_communication[0]["src_ip"]:
                                    arp_communication.append(packet)
                                    is_unique = False
                                    break
                if is_unique:
                    if packet["arp_opcode"] == "REQUEST":
                        arp_communications.append([packet])
                    else:
                        arp_incomplete_replies.append(packet)
            for arp_communication in arp_communications:
                if len(arp_communication) > 0:
                    if arp_communication[len(arp_communication)-1]["arp_opcode"] == "REPLY":
                        arp_complete_communications.append(arp_communication)
                    else:
                        incomplete_request = arp_communication[len(arp_communication)-1]
                        arp_incomplete_requests.append(incomplete_request)
                        arp_communication.remove(incomplete_request)
                        if len(arp_communication) > 1:
                            arp_complete_communications.append(arp_communication)

        # Analyze flags
        for packet in packets_with_flags:
            if "SYN" in packet["flags"]:  # If we have SYN

                new_request = True
                for communication in current_communications:
                    # If it's a repeat request then the old one is incomplete and this one needs to reset
                    if len(communication) > 0 and communication[0]["src_ip"] == packet["src_ip"] and communication[0]["dst_ip"] == packet["dst_ip"]:
                        if communication[0]["src_port"] == packet["src_port"] and communication[0]["dst_port"] == packet["dst_port"]:
                            incomplete_communications.append(communication[0])
                            communication[0] = packet
                            new_request = False  # Not a new request
                            break
                    # If it's a reply then we add it
                    if len(communication) > 0 and communication[0]["src_ip"] == packet["dst_ip"] and communication[0]["dst_ip"] == packet["src_ip"]:
                        communication.append(packet)
                        new_request = False  # Not a new request
                        break
                if new_request:
                    new_communication = [packet]
                    current_communications.append(new_communication)
            elif "ACK" in packet["flags"]:  # If we have ACK or RST

                for communication in current_communications:
                    # If we have 2x SYN
                    if len(communication) > 1:
                        # If packet was sent by client to server
                        if communication[0]["src_ip"] == packet["src_ip"] and communication[0]["dst_ip"] == packet["dst_ip"]:
                            if communication[0]["src_port"] == packet["src_port"] and communication[0]["dst_port"] == packet["dst_port"]:
                                communication.append(packet)
                                check_for_complete_communication(communication, complete_communications, current_communications)

                        # If packet was sent by server to client
                        elif communication[1]["src_ip"] == packet["src_ip"] and communication[1]["dst_ip"] == packet["dst_ip"]:
                            if communication[1]["src_port"] == packet["src_port"] and communication[1]["dst_port"] == packet["dst_port"]:
                                communication.append(packet)
                                check_for_complete_communication(communication, complete_communications, current_communications)

            elif "RST" in packet["flags"]:  # If we have RST
                for communication in current_communications:
                    # If is established
                    if "SYN" in communication[0]["flags"] and "SYN" in communication[1]["flags"] and "ACK" in communication[1]["flags"] and "ACK" in communication[2]["flags"]:
                        # If packet was sent by client to server
                        if communication[0]["src_ip"] == packet["src_ip"] and communication[0]["dst_ip"] == packet["dst_ip"]:
                            if communication[0]["src_port"] == packet["src_port"] and communication[0]["dst_port"] == packet["dst_port"]:
                                communication.append(packet)
                                complete_communications.append(communication)
                                current_communications.remove(communication)
                        # If packet was sent by server to client
                        elif communication[1]["src_ip"] == packet["src_ip"] and communication[1]["dst_ip"] == packet["dst_ip"]:
                            if communication[1]["src_port"] == packet["src_port"] and communication[1]["dst_port"] == packet["dst_port"]:
                                communication.append(packet)
                                complete_communications.append(communication)
                                current_communications.remove(communication)
                    elif "SYN" in communication[0]["flags"] and "SYN" in communication[1]["flags"] and "ACK" in communication[2]["flags"] and "ACK" in communication[3]["flags"]:
                        # If packet was sent by client to server
                        if communication[0]["src_ip"] == packet["src_ip"] and communication[0]["dst_ip"] == packet["dst_ip"]:
                            if communication[0]["src_port"] == packet["src_port"] and communication[0]["dst_port"] == packet["dst_port"]:
                                communication.append(packet)
                                complete_communications.append(communication)
                                current_communications.remove(communication)
                        # If packet was sent by server to client
                        elif communication[1]["src_ip"] == packet["src_ip"] and communication[1]["dst_ip"] == packet["dst_ip"]:
                            if communication[1]["src_port"] == packet["src_port"] and communication[1]["dst_port"] == packet["dst_port"]:
                                communication.append(packet)
                                complete_communications.append(communication)
                                current_communications.remove(communication)
                    else:
                        new_communication = [packet]
                        incomplete_communications.append(new_communication)

            elif "FIN" in packet["flags"]:  # Everything except ACK, SYN and RST

                for communication in current_communications:
                    # If communication is established
                    if "SYN" in communication[0]["flags"] and "SYN" in communication[1]["flags"] and "ACK" in communication[1]["flags"] and "ACK" in communication[2]["flags"]:
                        # If packet was sent by client to server
                        if communication[0]["src_ip"] == packet["src_ip"] and communication[0]["dst_ip"] == packet["dst_ip"]:
                            if communication[0]["src_port"] == packet["src_port"] and communication[0]["dst_port"] == packet["dst_port"]:
                                communication.append(packet)

                        # If packet was sent by server to client
                        elif communication[1]["src_ip"] == packet["src_ip"] and communication[1]["dst_ip"] == packet["dst_ip"]:
                            if communication[1]["src_port"] == packet["src_port"] and communication[1]["dst_port"] == packet["dst_port"]:
                                communication.append(packet)
                    elif "SYN" in communication[0]["flags"] and "SYN" in communication[1]["flags"] and "ACK" in communication[2]["flags"] and "ACK" in communication[3]["flags"]:
                        if "SYN" in communication[0]["flags"] and "SYN" in communication[1]["flags"] and "ACK" in communication[1]["flags"] and "ACK" in communication[2]["flags"]:
                            # If packet was sent by client to server
                            if communication[0]["src_ip"] == packet["src_ip"] and communication[0]["dst_ip"] == packet["dst_ip"]:
                                if communication[0]["src_port"] == packet["src_port"] and communication[0]["dst_port"] == packet["dst_port"]:
                                    communication.append(packet)

                            # If packet was sent by server to client
                            elif communication[1]["src_ip"] == packet["src_ip"] and communication[1]["dst_ip"] == packet["dst_ip"]:
                                if communication[1]["src_port"] == packet["src_port"] and communication[1]["dst_port"] == packet["dst_port"]:
                                    communication.append(packet)

        ipv4_senders = []
        for sender in unique_senders:
            ipv4_senders.append({"node": sender.ip_addr, "number_of_sent_packets": sender.packets_sent})

        max_send_packets = []
        key_function = lambda obj: obj.packets_sent
        max_packets_sent = max(unique_senders, key=key_function).packets_sent
        max_objects = [obj for obj in unique_senders if obj.packets_sent == max_packets_sent]
        for i in max_objects:
            max_send_packets.append({"ip_addr": i.ip_addr, "packets_sent": i.packets_sent})

        with open("output.yaml", "w") as file:
            yaml = YAML()
            yaml.dump({"name": "PKS2023/24"}, file)
            yaml.dump({"pcap_name": file_name}, file)
            if program_mode == "f":
                yaml.dump({"filter_name": filter_name}, file)
                if results_count > 0:
                    for communication in complete_communications:
                        yaml.dump({f"complete_communication_{complete_communications.index(communication)+1}": communication}, file)
                    yaml.dump({"incomplete_communication": incomplete_communications[0]}, file)
                    yaml.dump({"ipv4_senders": ipv4_senders}, file)
                    yaml.dump({"max_send_packets_by": max_send_packets}, file)
                else:
                    yaml.dump("No packets found with this protocol!", file)
            elif program_mode == "a":
                if len(packets) > 0:
                    yaml.dump(packets, file)
                    yaml.dump({"ipv4_senders": ipv4_senders}, file)
                    yaml.dump({"max_send_packets_by": max_send_packets}, file)
                else:
                    yaml.dump("No packets found!", file)
            elif program_mode == "arp":
                yaml.dump({"filter_name": "ARP"}, file)
                if len(arp_complete_communications) > 0:
                    arp_complete_communications.pop(0)
                    for arp_communication in arp_complete_communications:
                        yaml.dump({f"complete_communication_{arp_complete_communications.index(arp_communication) + 1}": arp_communication}, file)
                arp_incomplete = []
                if len(arp_incomplete_requests) > 0:
                    arp_incomplete.append(arp_incomplete_requests)
                if len(arp_incomplete_replies) > 0:
                    arp_incomplete.append(arp_incomplete_requests)
                for i in arp_incomplete:
                    yaml.dump({f"partial_comms_{arp_incomplete.index(i)+1}": i}, file)
                if not len(arp_complete_communications) > 0 and not len(arp_incomplete_requests) > 0 and not len(arp_incomplete_replies) > 0:
                    yaml.dump("No packets found!", file)
            elif program_mode == "icmp":
                yaml.dump({"filter_name": "ICMP"}, file)
                if len(icmp_communications) > 0:
                    complete_comms = []
                    for comm in icmp_communications:
                        complete_comm = [{"number_comm": icmp_communications.index(comm) + 1}, {"packets": comm}]
                        complete_comms.append(complete_comm)
                    yaml.dump({"complete_comms": complete_comms}, file)
                partial_comms = []
                for comm in icmp_incomplete_requests:
                    partial_comms.append(comm)
                for comm in icmp_incomplete_replies:
                    partial_comms.append(comm)
                if len(partial_comms) > 0:
                    yaml.dump({"partial_comms": partial_comms}, file)
        print("\nDone, check output.yaml\n")

analyze_packets()


from __future__ import absolute_import, division, print_function

import os
import re

from qtpy import QtCore, QtWidgets
from qtpy.QtCore import Qt
from glue.core import parse
from glue import core
from glue.utils import nonpartial
from glue.utils.qt import load_ui
from glue.utils.qt import CompletionTextEdit

__all__ = ['CustomComponentWidget']

def disambiguate(label, labels):
    """ Changes name of label if it conflicts with labels list

    Parameters
    ----------
    label : str
        The label to change the name of
    labels : iterable
        A list of all labels

    Returns
    -------
    label : str
        If needed, appended with a suffix "_{number}". The output does not
        appear in labels
    """
    label = label.replace(' ', '_')
    if label not in labels:
        return label
    suffix = 1
    while label + ('_%i' % suffix) in labels:
        suffix += 1
    return label + ('_%i' % suffix)

class ColorizedCompletionTextEdit(CompletionTextEdit):

    updated = QtCore.Signal()

    def insertPlainText(self, *args):
        super(ColorizedCompletionTextEdit, self).insertPlainText(*args)
        self.reformat_text()
        self.updated.emit()

    def keyReleaseEvent(self, event):
        super(ColorizedCompletionTextEdit, self).keyReleaseEvent(event)
        self.reformat_text()
        self.updated.emit()

    def reformat_text(self):

        # Here every time a key is released, we re-colorize the expression.
        # We show valid components in blue, and invalid ones in red. We
        # recognized components because they contain a ":" which is not valid
        # Python syntax (except if one considers lambda functions, but we can
        # probably ignore that here)
        text = self.toPlainText()

        # If there are no : in the text we don't need to do anything
        if not ":" in text:
            return

        pattern = '[^\\s]*:[^\\s]*'

        def format_components(m):
            component = m.group(0)
            if component in self.word_list:
                return "" + component + " "
            else:
                return "" + component + " "

        html = re.sub(pattern, format_components, text)

        tc = self.textCursor()
        pos = tc.position()

        self.setHtml(html)

        # Sometimes the HTML gets rid of double spaces so we have to make
        # sure the position isn't greater than the text length.
        text = self.toPlainText()
        pos = min(pos, len(text))

        tc.setPosition(pos)
        self.setTextCursor(tc)
        self.setAlignment(Qt.AlignCenter)

class CustomComponentWidget(QtWidgets.QDialog):
    """
    Dialog to add derived components to data via parsed commands.
    """

    def __init__(self, collection, parent=None):

        super(CustomComponentWidget, self).__init__(parent=parent)

        # Load in ui file to set up widget
        self.ui = load_ui('widget.ui', self,
                          directory=os.path.dirname(__file__))

        # In the ui file we do not create the text field for the expression
        # because we want to use a custom widget that supports auto-complete.
        self.ui.expression.setAlignment(Qt.AlignCenter)

        self._labels = {}
        self._data = {}
        self._collection = collection
        self._gather_components()
        self._gather_data()
        self._init_widgets()
        self._connect()

        # Set up auto-completion. While the auto-complete window is open, we
        # cannot add/remove datasets or other components, so we can populate
        # the auto_completer straight off.
        self.ui.expression.set_word_list(list(self._labels.keys()))

        self.ui.button_ok.clicked.connect(self.accept)
        self.ui.button_cancel.clicked.connect(self.reject)

        self.ui.expression.updated.connect(self._update_status)
        self._update_status()

    def _update_status(self):
        if str(self.ui.expression.toPlainText()) == "":
            self.ui.label_status.setText("")
            self.ui.button_ok.setEnabled(False)
        else:
            try:
                pc = self._get_parsed_command()
                pc.evaluate_test()
            except SyntaxError:
                self.ui.label_status.setStyleSheet('color: red')
                self.ui.label_status.setText("Incomplete or invalid syntax")
                self.ui.button_ok.setEnabled(False)
            except parse.InvalidTagError as exc:
                self.ui.label_status.setStyleSheet('color: red')
                self.ui.label_status.setText("Invalid component: {0}".format(exc.tag))
                self.ui.button_ok.setEnabled(False)
            except Exception as exc:
                self.ui.label_status.setStyleSheet('color: red')
                self.ui.label_status.setText(str(exc))
                self.ui.button_ok.setEnabled(False)
            else:
                self.ui.label_status.setStyleSheet('color: green')
                self.ui.label_status.setText("Valid expression")
                self.ui.button_ok.setEnabled(True)

    def _connect(self):
        cl = self.ui.component_list
        cl.itemDoubleClicked.connect(self._add_to_expression)

    def _init_widgets(self):
        """
        Set up default state of widget
        """
        comps = self.ui.component_list
        comps.addItems(sorted(self._labels.keys()))
        data = self.ui.data_list
        data.addItems(sorted(self._data.keys()))

    def _gather_components(self):
        """
        Build a mapping from unique labels -> componentIDs
        """
        comps = set()
        for data in self._collection:
            for c in data.components:
                if c in comps:
                    continue
                label = "%s:%s" % (data.label, c)
                label = disambiguate(label, self._labels)
                self._labels[label] = c
                comps.add(c)

    def _gather_data(self):
        """
        Build a mapping from unique labels -> data objects
        """
        for data in self._collection:
            label = data.label
            label = disambiguate(label, self._data)
            self._data[label] = data

    def _selected_data(self):
        """
        Yield all data objects that are selected in the DataList
        """
        for items in self.ui.data_list.selectedItems():
            yield self._data[str(items.text())]

    def _create_link(self):
        """
        Create a ComponentLink from the state of the GUI

        Returns
        -------
        A new component link
        """
        pc = self._get_parsed_command()
        label = str(self.ui.new_label.text()) or 'new component'
        new_id = core.data.ComponentID(label)
        link = parse.ParsedComponentLink(new_id, pc)
        return link

    def _get_parsed_command(self):

        expression = str(self.ui.expression.toPlainText())

        # To maintain backward compatibility with previous versions of glue,
        # we add curly brackets around the components in the expression.
        pattern = '[^\\s]*:[^\\s]*'

        def add_curly(m):
            return "{" + m.group(0) + "}"
        expression = re.sub(pattern, add_curly, expression)

        return parse.ParsedCommand(expression, self._labels)

    @property
    def _number_targets(self):
        """
        How many targets are selected
        """
        return len(self.ui.data_list.selectedItems())

    def _add_link_to_targets(self, link):
        """
        Add a link to all the selected data
        """
        for target in self._selected_data():
            target.add_component_link(link)

    def _add_to_expression(self, item):
        """
        Add a component list item to the expression editor
        """
        addition = '%s ' % item.text()
        expression = self.ui.expression
        expression.insertPlainText(addition)

    def accept(self):
        if self._number_targets == 0:
            QtWidgets.QMessageBox.critical(self.ui, "Error", "Please specify the target dataset(s)",
                                       buttons=QtWidgets.QMessageBox.Ok)
        elif len(self.ui.new_label.text()) == 0:
            QtWidgets.QMessageBox.critical(self.ui, "Error", "Please specify the new component name",
                                       buttons=QtWidgets.QMessageBox.Ok)
        else:
            link = self._create_link()
            if link:
                self._add_link_to_targets(link)
            super(CustomComponentWidget, self).accept()

def main():
    from glue.core.data import Data
    from glue.core.data_collection import DataCollection
    import numpy as np

    x = np.random.random((5, 5))
    y = x * 3
    data = DataCollection(Data(label='test', x=x, y=y))

    widget = CustomComponentWidget(data)
    widget.exec_()

    for d in data:
        print(d.label)
        for c in d.components:
            print('\t%s' % c)

if __name__ == "__main__":
    from glue.utils.qt import get_qapp
    app = get_qapp()
    main()


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *

from PlasticRinseDialog import PlasticRinseDialog
from RecycleDialog import RecycleDialog
from ServoFuncs import openLid
from Worker import Worker

class PlasticFoodLiquidDialog(object):
    def setupPlasticFoodLiquid(self, Dialog):
        # Main Window
        Dialog.setObjectName("Dialog")
        Dialog.resize(400, 300)
        self.gridLayout = QtWidgets.QGridLayout(Dialog)
        self.gridLayout.setObjectName("gridLayout")
        Dialog.setWindowTitle("Food or Liquid?")

        # Food or Liquid Label
        self.lbl_foodliquid = QtWidgets.QLabel(Dialog)
        font = QtGui.QFont()
        font.setPointSize(18)
        self.lbl_foodliquid.setFont(font)
        self.lbl_foodliquid.setAlignment(QtCore.Qt.AlignCenter)
        self.lbl_foodliquid.setWordWrap(True)
        self.lbl_foodliquid.setObjectName("lbl_foodliquid")
        self.gridLayout.addWidget(self.lbl_foodliquid, 0, 0, 1, 2)
        self.lbl_foodliquid.setText("Did your item contain food or liquid?")

        # Yes Button
        self.btn_yes = QtWidgets.QPushButton(Dialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.btn_yes.sizePolicy().hasHeightForWidth())
        self.btn_yes.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(24)
        self.btn_yes.setFont(font)
        self.btn_yes.setObjectName("btn_yes")
        self.gridLayout.addWidget(self.btn_yes, 2, 0, 1, 1)
        self.btn_yes.setText("Yes")
        self.btn_yes.clicked.connect(self.openPlasticRinseDialog)
        self.btn_yes.clicked.connect(Dialog.close)

        # No Button
        self.btn_no = QtWidgets.QPushButton(Dialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.btn_no.sizePolicy().hasHeightForWidth())
        self.btn_no.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(24)
        self.btn_no.setFont(font)
        self.btn_no.setObjectName("btn_no")
        self.gridLayout.addWidget(self.btn_no, 2, 1, 1, 1)
        self.btn_no.setText("No")
        self.btn_no.clicked.connect(self.openRecycleDialog)
        self.btn_no.clicked.connect(Dialog.close)
        # OPEN PLASTIC LID HERE
        self.btn_no.clicked.connect(self.openPlasticLid)
        self.threadpool = QThreadPool()

        # Cancel Button Box
        self.bb_cancel = QtWidgets.QDialogButtonBox(Dialog)
        font = QtGui.QFont()
        font.setPointSize(8)
        self.bb_cancel.setFont(font)
        self.bb_cancel.setOrientation(QtCore.Qt.Horizontal)
        self.bb_cancel.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel)
        self.bb_cancel.setCenterButtons(True)
        self.bb_cancel.setObjectName("bb_cancel")
        self.gridLayout.addWidget(self.bb_cancel, 3, 0, 1, 2)
        self.bb_cancel.accepted.connect(Dialog.accept)
        self.bb_cancel.rejected.connect(Dialog.reject)

    def openPlasticRinseDialog(self):
        self.PlasticRinse = QtWidgets.QDialog()
        self.ui = PlasticRinseDialog()
        self.ui.setupPlasticRinse(self.PlasticRinse)
        self.PlasticRinse.show()

    def openRecycleDialog(self):
        self.Recycle = QtWidgets.QDialog()
        self.ui = RecycleDialog()
        self.ui.setupRecycle(self.Recycle)
        self.Recycle.show()

    def openPlasticLid(self):
        # Pass the function to execute
        worker = Worker(lambda: openLid(0))
        #  Execute
        self.threadpool.start(worker)

# Needed to run window by itself
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Dialog = QtWidgets.QDialog()
    ui = PlasticFoodLiquidDialog()
    ui.setupPlasticFoodLiquid(Dialog)
    Dialog.show()
    sys.exit(app.exec_())


#def move_zeros(lst):
#    count = 0
#    listt = []
#    for i in range(0, len(lst)):
#        if lst[i] == 0:
#            count += 1
#        else:
#            listt.append(lst[i])
#    for i in range(0, count): listt.append(0)
#    return listt

#print(move_zeros([1, 0, 1, 2, 0, 1, 3, 0, 5]))

#def count(s):
#    lstt = {}
#    for i in range(0, len(s)):
#       lstt.update(s[i], i)
#    return lstt

#print(count('aba'))

#The marketing team is spending way too much time typing in hashtags.
#Let's help them with our own Hashtag Generator!
#Here's the deal:
#It must start with a hashtag (#).
#All words must have their first letter capitalized.
#If the final result is longer than 140 chars it must return false.
#If the input or the result is an empty string it must return false.

def generate_hashtag(s):
    s = s.title()
    s = s.replace(' ', '')
    if len(s)+1 > 140: return False
    elif len(s) == 0: return False
    else:
        return f'#{s}'

print(generate_hashtag('ABbCccDdddEeeeeFfffffGggggggHhhhhhhhIiiiiiiiiJjjjjjjjjjKkkkkkkkkkkLlllllllllllMmmmmmmmmmmmmNnnnnnnnnnnnnnOooooooooooooooPpppppppppppppppQqqq'))


#!/usr/bin/python

#Execute this script in the folder with your node-00XX.log outputs to get a graph of initial and final images

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

########## INPUT #####################
nodes = 16 #Number of string nodes
######################################
end_lines = list()
end_data = list()
start_lines = list()
start_data = list()

for i in range(0, nodes):
    if i <= 9:
        fileName = "node-000{0}.log".format(i)
    else:
        fileName = "node-00{0}.log".format(i)

    fileHandle = open(fileName)
    lineList = fileHandle.readlines()
    end_lines.append(lineList[-1])
    start_lines.append(lineList[0])
    fileHandle.close()

for line in end_lines:
    end_data.append(line.split(' '))

for line in start_lines:
    start_data.append(line.split(' '))

end_x = list()
end_y = list()
start_x = list()
start_y = list()

for line in end_data:
    end_x.append(line[2])
    end_y.append(line[4])

for line in start_data:
    start_x.append(line[2])
    start_y.append(line[4])

fig = plt.figure()

ax1 = fig.add_subplot(111)

converter = 1.0
end_xdegree = converter*np.array(end_x, dtype=float)
end_ydegree = converter*np.array(end_y, dtype=float)
start_xdegree = converter*np.array(start_x, dtype=float)
start_ydegree = converter*np.array(start_y, dtype=float)

ax1.set_title("Langevin Particle")
ax1.set_xlabel('X')
ax1.set_ylabel('Y')

ax1.plot(end_xdegree,end_ydegree, 'ro-', label='Final Images')
ax1.plot(start_xdegree, start_ydegree, 'bo-', label='Initial Images')

#leg = ax1.legend()

plt.show()