import unittest

from aquilon.exceptions_ import ArgumentError

try:
    from unittest import mock
except ImportError:
    # noinspection PyUnresolvedReferences
    import mock

# As these are unit tests, we do not need the full broker capability,
# we can thus mock the DbFactory in order for it not to try and open
# the database (which is not required anyway)
with mock.patch('aquilon.aqdb.db_factory.DbFactory', autospec=True):
    from aquilon.aqdb.model import hostlifecycle
    from aquilon.worker.commands import del_host

class TestCommandDelHost(unittest.TestCase):
    @staticmethod
    def get_command_with_mock_config():
        command = del_host.CommandDelHost()
        mock_config = mock.MagicMock()
        command.config = mock_config
        mock_config.has_section.return_value = True
        mock_config.has_option.return_value = True
        return command

    @staticmethod
    def get_all_buildstatus():
        return set(hostlifecycle.HostLifecycle.__mapper__.polymorphic_map)

    @staticmethod
    def get_default():
        return set(del_host.CommandDelHost._default_allowed_status)

    @staticmethod
    def get_mock_archetype():
        archetype = mock.MagicMock()
        archetype.name = 'aquilon'
        return archetype

    @staticmethod
    def get_mock_status(name):
        status = mock.MagicMock()
        status.name = name
        return status

    def get_mock_host(self, status):
        host = mock.MagicMock()
        host.archetype = self.get_mock_archetype()
        host.status = self.get_mock_status(status)
        return host

    def test_get_allowed_status_filters_out_invalid_status_data(self):
        command = self.get_command_with_mock_config()
        archetype = self.get_mock_archetype()

        # Case 1.
        configured = (
                ' ,, ,, , , invalid1,'
                + ','.join(self.get_all_buildstatus())
                + ',invalid2,and3'
                + ' ,,,,, , invalid4,  , +,("$*^&%*)!,,'
        )
        command.config.get.return_value = configured
        expected = self.get_all_buildstatus()
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, expected)
        # Case 2.
        command.config.get.return_value = ''
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, set())
        # Case 3.
        command.config.get.return_value = ','
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, set())
        # Case 4.
        command.config.get.return_value = '  ready,reinstall,bad, wrong,failed'
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, {'failed', 'ready', 'reinstall'})
        # Case 5.
        command.config.get.return_value = ',re ady,reinstall'
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, {'reinstall'})

    def test_get_allowed_status_logs_detected_invalid_status(self):
        command = self.get_command_with_mock_config()
        command.config.get.return_value = ' ready, bad, install, wrong,invalid'
        archetype = self.get_mock_archetype()
        logger = mock.MagicMock()
        command._get_allowed_status(archetype, logger)
        logger.warning.assert_called_once()
        warning = str(logger.warning.call_args)
        self.assertIn('Invalid buildstatus detected', warning)
        self.assertIn('bad', warning)
        self.assertIn('invalid', warning)
        self.assertIn('wrong', warning)
        self.assertNotIn('ready', warning)
        self.assertNotIn('install', warning)

    def test_get_allowed_status_returns_default_if_no_override_config(self):
        command = self.get_command_with_mock_config()
        command.config.has_option.return_value = False
        command.config.get.return_value = 'this,should,not,be,used,blind,ready'
        archetype = self.get_mock_archetype()
        expected = self.get_default()
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, expected)

    def test_get_allowed_status_returns_empty_set_if_no_valid_status_given(
            self):
        command = self.get_command_with_mock_config()
        archetype = self.get_mock_archetype()
        expected = set()
        # Case 1.
        command.config.get.return_value = ''
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, expected)

        # Case 2.
        command.config.get.return_value = '   '
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, expected)

        # Case 3.
        command.config.get.return_value = ','
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, expected)

        # Case 4.
        command.config.get.return_value = 're ady, also wrong, invalid,'
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, expected)

        # Case 5.
        command.config.get.return_value = '  , ,,,, , '
        result = command._get_allowed_status(archetype, mock.MagicMock())
        self.assertEqual(result, expected)

    def test_validate_buildstatus_aborts_with_warning_for_protected_status(
            self):
        command = self.get_command_with_mock_config()
        command._get_allowed_status = mock.MagicMock()
        mock_logger = mock.MagicMock()
        mock_host = self.get_mock_host('protected')

        # Case 1: all status protected.
        command._get_allowed_status.return_value = set()
        expected = ('host status "protected" combined with',
                    'archetype configuration',
                    ' prevents it from being deleted',
                    'Current configuration for hosts that belong',
                    'archetype "aquilon"',
                    'any state in which they could be deleted')
        with self.assertRaises(ArgumentError) as cm:
            command._validate_buildstatus(dbhost=mock_host,
                                          logger=mock_logger)
        for s in expected:
            self.assertIn(s, cm.exception.message)

        # Case 2: not all status protected, status sorted alphabetically.
        mock_host = self.get_mock_host('another_protected')
        command._get_allowed_status.return_value = {'s2', 's3', 's1', 's0'}
        expected = ('host status "another_protected" combined with',
                    'archetype configuration',
                    ' prevents it from being deleted',
                    'case of archetype "aquilon"',
                    'only hosts with the following status can be deleted',
                    ': s0, s1, s2, s3.')
        with self.assertRaises(ArgumentError) as cm:
            command._validate_buildstatus(dbhost=mock_host,
                                          logger=mock_logger)
        for s in expected:
            self.assertIn(s, cm.exception.message)

    def test_validate_buildstatus_validates_allowed_status(
            self):
        command = self.get_command_with_mock_config()
        command._get_allowed_status = mock.MagicMock()
        mock_logger = mock.MagicMock()
        mock_host = self.get_mock_host('allowed')
        command._get_allowed_status.return_value = {'s3', 'allowed', 's1'}
        try:
            command._validate_buildstatus(dbhost=mock_host, logger=mock_logger)
        except ArgumentError as e:
            self.fail('The following ArgumentError should not have been raised'
                      ': "{}"'.format(e))

    def test_validate_buildstatus_logs_config_with_no_allowed_status(self):
        command = self.get_command_with_mock_config()
        command._get_allowed_status = mock.MagicMock()
        mock_logger = mock.MagicMock()
        mock_host = self.get_mock_host('decommissioned')

        command._get_allowed_status.return_value = set()
        expected = ('Current configuration for hosts that belong to archetype'
                    ' "aquilon" does not specify any state in which they could'
                    ' be deleted.')

        with self.assertRaises(ArgumentError):
            command._validate_buildstatus(dbhost=mock_host, logger=mock_logger)

        mock_logger.warning.assert_called_once()
        warning = str(mock_logger.warning.call_args)
        self.assertIn(expected, warning)

    def test_validate_buildstatus_invoked_at_start_of_render(self):
        expected = 'Correct exception for test of render raised.'
        command = self.get_command_with_mock_config()
        command._validate_buildstatus = mock.MagicMock()
        command._validate_buildstatus.side_effect = ArgumentError(expected)

        with mock.patch.object(del_host, 'hostname_to_host'):
            with self.assertRaises(ArgumentError) as cm:
                command.render(*([mock.MagicMock()] * 8))
        self.assertIn(expected, cm.exception.message)


from django.db import models
from django.contrib.auth import get_user_model
from django.core.validators import MinValueValidator, MaxValueValidator

from api_yamdb.settings import NAME_MAX_LENGTH, SLUG_MAX_LENGTH

User = get_user_model()

class Genre(models.Model):
    name = models.CharField(max_length=NAME_MAX_LENGTH,
                            null=False,
                            verbose_name='Имя жанра',)
    slug = models.SlugField(max_length=SLUG_MAX_LENGTH,
                            unique=True,
                            verbose_name='Slug жанра')

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('id',)
        verbose_name = 'Жанр'
        verbose_name_plural = 'Жанры'

class Category(models.Model):
    name = models.CharField(max_length=NAME_MAX_LENGTH,
                            verbose_name='Имя категории',)
    slug = models.SlugField(max_length=SLUG_MAX_LENGTH,
                            unique=True,
                            db_index=True,
                            verbose_name='Slug категории')

    class Meta:
        verbose_name = 'Категория'
        verbose_name_plural = 'Категории'

    def __str__(self):
        return f'{self.name} {self.name}'

class Title(models.Model):
    name = models.CharField('Название', max_length=NAME_MAX_LENGTH)
    year = models.IntegerField('Год выпуска',
                               blank=True,)
    description = models.TextField('Описание',
                                   null=True,
                                   blank=True)
    genre = models.ManyToManyField(Genre,
                                   related_name='GenreTitle',
                                   verbose_name='Slug жанра',)
    category = models.ForeignKey(Category,
                                 blank=True,
                                 null=True,
                                 on_delete=models.SET_NULL,
                                 related_name='titles',
                                 verbose_name='Slug категории',)

    class Meta:
        verbose_name = 'Произведение'
        verbose_name_plural = 'Произведения'
        ordering = ('id',)

    def __str__(self):
        return self.name

class Review(models.Model):
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='reviews',
        verbose_name='Автор отзыва'
    )
    text = models.TextField(verbose_name='Текст отзыва')
    title = models.ForeignKey(
        Title,
        on_delete=models.CASCADE,
        related_name='reviews',
        verbose_name='Название'
    )
    score = models.PositiveSmallIntegerField(verbose_name='Оценка отзыва',
                                             validators=[MinValueValidator(1),
                                                         MaxValueValidator(10)]
                                             )
    pub_date = models.DateTimeField(
        verbose_name='Дата добавления отзыва',
        auto_now_add=True,
        db_index=True
    )

    class Meta:
        verbose_name = 'Отзыв'
        verbose_name_plural = 'Отзывы'
        constraints = [
            models.UniqueConstraint(
                fields=('author', 'title'),
                name='unique reviews',
            )]
        ordering = ('pub_date',)

    def __str__(self):
        return self.text

class Comment(models.Model):
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='comments',
        verbose_name='Автор'
    )
    review = models.ForeignKey(
        Review,
        on_delete=models.CASCADE,
        related_name='comments',
        verbose_name='Отзыв'
    )
    text = models.TextField(verbose_name='Текст комментария')
    pub_date = models.DateTimeField(
        verbose_name='Дата добавления комментария',
        auto_now_add=True,
        db_index=True
    )

    class Meta:
        verbose_name = 'Комментарий'
        verbose_name_plural = 'Комментарии'

    def __str__(self):
        return self.text[:15]


from flask import Flask, render_template
import sqlite3

app = Flask(__name__)

def generarListaPerCapita():
  lista = []
  conn = sqlite3.connect('co_emissions.db')

  q = f'''SELECT Country, Value, Year
          FROM emissions
          WHERE Series = 'pcap'
          ORDER BY Value DESC
       '''
  resu = conn.execute(q)

  for fila in resu:
    lista.append(fila)

  conn.close()

  return lista

def generarListaTotal():
  lista = []
  conn = sqlite3.connect('co_emissions.db')

  q = '''SELECT country_id, Value, Year
         FROM emissions
         WHERE series = 'total'
      '''
  resu = conn.execute(q)

  for fila in resu:
    subLista = [fila[0], fila[1], fila[2]]
    lista.append(subLista)

  i = 0
  while i < len(lista):
    lista[i][1] = int(lista[i][1])
    i += 1

  """
    q = '''ALTER TABLE emissions
           ADD  ValueInt INT
        '''
    conn.execute(q)
    conn.commit()

    i = 0
    while i < len(lista):
      q = '''UPDATE emissions
             SET ValueInt = %i
             WHERE country_id = '%s' AND Year = '%s'
          ''' %(lista[i][1], lista[i][0], lista[i][2])
      conn.execute(q)
      conn.commit()
      i += 1
    """

  q = '''SELECT Country, ValueInt, Year
         FROM emissions
         WHERE Series = 'total'
         ORDER BY ValueInt DESC
      '''
  resu = conn.execute(q)

  lista.clear()

  for fila in resu:
    lista.append(fila)

  conn.close()

  return lista

def sacarRepetidos(lista):
  i = 1
  paises = []
  while i < 10:
    paises.append(lista[i-1][0])
    if lista[i][0] in paises:
      lista.pop(i)
    else:
      i += 1
  return lista

def generarListaPorPais(pais):
  lista = []
  conn = sqlite3.connect('co_emissions.db')

  q ='''SELECT Value, Series, Year
       FROM emissions
       WHERE Country = '%s'
     ''' % (pais)
  resu = conn.execute(q)

  for fila in resu:
    subLista = [fila[0], fila[1], fila[2]]
    lista.append(subLista)

  conn.close()

  return lista

def generarListaDePaises():
  lista = []
  conn = sqlite3.connect('co_emissions.db')

  q = '''SELECT DISTINCT Country
         FROM emissions
      '''
  resu = conn.execute(q)

  for fila in resu:
    lista.append(fila[0])

  conn.close()

  return lista

@app.route('/')
def index():
  return render_template('index.html', listaPaises = generarListaDePaises())

@app.route('/listado')
def listaPerCapita():
  return render_template('perCapita.html', listaValores = generarListaPerCapita(), listaPaises = sacarRepetidos(generarListaPerCapita()))
@app.route('/listado/<pais>')
def datosPais(pais):
  return render_template('porPais.html', paisElegido = pais.upper(), listaDatos = generarListaPorPais(pais))

@app.route('/top')
def listaTotal():
  return render_template('total.html', listaValores = generarListaTotal(), listaPaises = sacarRepetidos(generarListaTotal()))

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

app.run(host='0.0.0.0', port=81)


'''
GM(1,1)模型代码的写作思路
1.画出原始数据的实践序列图，判断原始数据中是否有负数或低于四期，是，则报错，否进行下一步
2.对一次累加后的数据进行准指数规律检验，返回两个指标
    指标1 光滑比小于0.5的数据占比
    指标2 除去前两个时期外，光滑比
'''

# # -*- coding: utf-8 -*-
# """
# Spyder Editor

# This is a temporary script file.
# """
import numpy as np
import math

history_data = [724.57,746.62,778.27,800.8,827.75,871.1,912.37,954.28,995.01,1037.2]
n = len(history_data)
X0 = np.array(history_data)

#累加生成
history_data_agg = [sum(history_data[0:i+1]) for i in range(n)]
X1 = np.array(history_data_agg)#累加x1

#计算数据矩阵B和数据向量Y
B = np.zeros([n-1,2])
Y = np.zeros([n-1,1])
for i in range(0,n-1):
    B[i][0] = -0.5*(X1[i] + X1[i+1])
    B[i][1] = 1
    Y[i][0] = X0[i+1]

#计算GM(1,1)微分方程的参数a和u
#A = np.zeros([2,1])
A = np.linalg.inv(B.T.dot(B)).dot(B.T).dot(Y)
a = A[0][0]
u = A[1][0]

#建立灰色预测模型
XX0 = np.zeros(n)
XX0[0] = X0[0]
for i in range(1,n):
    XX0[i] = (X0[0] - u/a)*(1-math.exp(a))*math.exp(-a*(i));

#模型精度的后验差检验
e = 0      #求残差平均值
for i in range(0,n):
    e += (X0[i] - XX0[i])
e /= n
print("残差平均值：",e)

#求历史数据平均值
aver = 0;
for i in range(0,n):
    aver += X0[i]
aver /= n

#求历史数据方差
s12 = 0;
for i in range(0,n):
    s12 += (X0[i]-aver)**2;
s12 /= n

#求残差方差
s22 = 0;
for i in range(0,n):
    s22 += ((X0[i] - XX0[i]) - e)**2;
s22 /= n

#求后验差比值
C = s22 / s12

#求小误差概率
cout = 0
for i in range(0,n):
    if abs((X0[i] - XX0[i]) - e) < 0.6754*math.sqrt(s12):
        cout = cout+1
    else:
        cout = cout
P = cout / n

if (C < 0.35 and P > 0.95):
    #预测精度为一级
    m = 10   #请输入需要预测的年数
    print('往后m各年负荷为：')
    f = np.zeros(m)
    for i in range(0,m):
        f[i] = (X0[0] - u/a)*(1-math.exp(a))*math.exp(-a*(i+n))
else:
    print('灰色预测法不适用')

# # 关于出现图案里面的中文不显示，只有口口的样子
# # 解决方案：

# import matplotlib.pyplot as plt
# plt.rcParams['font.sans-serif'] = ['SimSun']  # 设置字体为宋体或其他中文字体
# plt.figure(figsize=(8, 4))
# plt.plot([1, 2, 3, 4, 5], [10, 12, 5, 8, 9], 'b-o')
# plt.xlabel('X轴')
# plt.ylabel('Y轴')
# plt.title('中文标题')
# plt.grid(True)
# plt.show()

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

# # 创建一个圆的坐标点
# theta = np.linspace(0, 2 * np.pi, 100)  # 创建角度范围从0到2*pi
# r = 1.0  # 圆的半径

# # 计算圆上的点的坐标
# x = r * np.cos(theta)
# y = r * np.sin(theta)

# # 创建坐标图
# plt.figure(figsize=(6, 6))  # 设置图形大小
# plt.plot(x, y, label='圆', color='b')  # 绘制圆
# plt.xlabel('X轴')  # 设置X轴标签
# plt.ylabel('Y轴')  # 设置Y轴标签
# plt.title('圆的坐标图')  # 设置标题
# plt.legend()  # 显示图例
# plt.grid(True)  # 显示网格

# # 显示图形
# plt.show()

# '''输入原始数据并做出时间序列图'''
# import pandas as pd
# import matplotlib.pyplot as plt
# plt.rcParams['font.sans-serif'] = ['SimSun']

# # 导入CSV文件到DataFrame
# df = pd.read_csv('daima.csv',encoding='utf-8')

# # 将日期列解析为日期时间格式
# #df['Date'] = pd.to_datetime(df['Date']) #将文件中的Date列解析为日期时间格式

# # 设置日期列作为索引（如果未设置的话）
# # df.set_index('Date', inplace=True)

# # 创建时间序列图
# plt.figure(figsize=(12, 6))# 图形窗口的大小
# plt.plot(df['year'], df['zong'], label='时间序列数据', color='blue')
# #创建一个二维图表，第一个"date"作为x轴，第二个“Value”作为y轴，图例标签为“时间序列数据”，颜色为蓝色
# plt.xlabel('时间')
# plt.ylabel('值')
# plt.title('时间序列图')
# plt.legend()

# plt.grid(True)

# # 显示图像
# plt.show()

# #读取第几行数据
# import pandas as pd

# # 读取CSV文件
# df = pd.read_csv('daima.csv',encoding='utf-8')

# # 打印 DataFrame 的前几行
# print(df.head(1))

'''读取xlsx 文件进行处理成为csv文件
# import pandas as pd

# # 读取Excel文件
# excel_file = 'daima.xlsx'  # 替换为您的Excel文件路径
# df = pd.read_excel(excel_file)

# # 将数据保存为CSV文件
# csv_file = 'daima.csv'  # 指定CSV文件路径
# df.to_csv(csv_file, index=False)  # index=False 表示不保存索引列
'''

学习/第十二讲：预测模型/灰色预测/daima.py


from __future__ import annotations

from enum import Enum
from typing import Type

import discord

WAITING = "⏳"
DONE = "✅"

class StepEmbed(discord.Embed):
    def __init__(self, title: str, steps: Type[Enum]):
        super().__init__(title=title)
        self._steps: dict[Enum, str] = {e: WAITING for e in steps}
        self.generate_description()

    def generate_description(self) -> None:
        self.description = ""
        for step, emoji in self._steps.items():
            self.description += f"{step.value}: {emoji}\n"

    def update_step(self, step: Enum, emoji: str) -> None:
        self._steps[step] = emoji
        self.generate_description()

class StepMessageProxy:
    def __init__(self, message: discord.Message, embed: StepEmbed):
        self._message: discord.Message = message
        self._embed: StepEmbed = embed

    async def initial_edit(self) -> None:
        await self._message.edit(embed=self._embed)

    async def update(self, step: Enum, emoji: str) -> None:
        self._embed.update_step(step, emoji)
        await self._message.edit(embed=self._embed)

    async def done(self, step: Enum) -> None:
        await self.update(step, DONE)


import sys
import cmath
import numpy as np
import matplotlib.pyplot as plt

a = .5
b = 2
infinity = 5
timeSteps = 1024
period = 1
terms = 50
time = np.linspace(0,period,num=timeSteps)
maxCoefs = terms*infinity*(2**infinity)

def cn(n):
   c = z*np.exp(-1j*2*n*np.pi*time/period)
   return c.sum()/c.size

def f(x, terms):
   f = np.array([2*cn(i)*np.exp(1j*2*i*np.pi*x/period) for i in range(1,terms)])
   return cn(0)+f.sum()

def ek(k,x):
   if (k == 0):
      return 1
   elif (k % 2 != 0):
      y = np.array([(a**m)*cmath.exp(2*np.pi*1j*k*(2**m)*x) for m in range(infinity)])
      return np.sqrt(1-(a**2)) * y.sum()
   elif (k % 2 == 0):
      y = np.array([(a**m)*cmath.exp(2*np.pi*1j*k*(2**m)*x) for m in range(infinity)])
      x = np.array([(a**m)*cmath.exp(2*np.pi*1j*int(k/2)*(2**m)*x) for m in range(infinity)])
      return ((np.sqrt(1-(a**2)) * y.sum())-(a*(np.sqrt(1-(a**2)) * x.sum()))) / np.sqrt(1-a**2)

def ak(k):
   if (k == 0):
      return coefs[0]
   elif (k % 2 != 0):
      y = np.array([(a**m)*coefs[k*(2**m)] for m in range(infinity)])
      return np.sqrt(1-(a**2)) * y.sum()
   elif (k % 2 == 0):
      y = np.array([(a**m)*coefs[k*(2**m)] for m in range(infinity)])
      x = np.array([(a**m)*coefs[int(k/2)*(2**m)] for m in range(infinity)])
      return ((np.sqrt(1-(a**2)) * y.sum()) - (a*(np.sqrt(1-(a**2)) * x .sum()))) / np.sqrt(1-a**2)

def functionGuy(x):
   return x**2+.5

def wFourier(x):
   y = np.array([ak(k)*ek(k,x) for k in range(1,terms)])
   return coefs[0]+2*y.sum().real

z = np.array([functionGuy(t).real for t in time])
f = np.array([f(t, terms).real for t in time])
plt.plot(time, z)
plt.plot(time, f)
coefs = np.array([cn(n) for n in range(maxCoefs)])
points = np.array([wFourier(t) for t in time])
plt.plot(time, points)
plt.show()


class Solution:
    def numSubmatrixSumTarget(self, matrix: List[List[int]], target: int) -> int:
        m, n, ans = len(matrix), len(matrix[0]), 0
        prefix = [[0] * (n+1) for _ in range(m+1)]

        for i in range(1, m+1):
            for j in range(1, n+1):
                prefix[i][j] = matrix[i-1][j-1] + prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1]

        for i in range(1,m+1):
            for p in range(i, m+1):
                hash_map = defaultdict(int)
                hash_map[0] = 1
                for q in range(1, n+1):
                    curr = prefix[p][q] - prefix[i-1][q]
                    if  curr - target  in hash_map:
                        # print("i = ", i, ", p = ", p, ", q = ", q, ", curr = ", curr)
                        ans+=hash_map[curr - target]
                    hash_map[curr] += 1
        return ans


from helper.data_output import create_csv, create_ics
from classes.data_item import DataItem
from classes.dictionary_item import DictionaryItem
from typing import List
import datetime
from termcolor import *

def show_application_disclaimer():

    """
    Summary
    -------
    This function outputs the limitation of liability (Disclaimer).
    """
    print(colored("                                         FH-Kiel, Time Table Parser                                         ", attrs=['reverse']))
    print(colored("############################################################################################################", 'magenta'))
    print(colored("Limitation of liability (Disclaimer):\n", 'magenta'))
    print(colored("The contents of the TimeTableParser (TTP) were compiled with the greatest possible care and in accordance", 'magenta'))
    print(colored("with in the best of conscience. Nevertheless, the provider of this application does not assume any liability", 'magenta'))
    print(colored("for the topicality, completeness and correctness of the ical/ics files and other content provided.", 'magenta'))
    print(colored("############################################################################################################\n", 'magenta'))

def user_select(data: List[DictionaryItem]):

    """
    Summary
    -------
    This function creates an interface to create an individual list of modules. Which has to
    be filtered.

    Parameter
    ---------
    data : list     # DictionaryItem-list

    Returns
    -------

    data : list     # FinalList with Integers which have to be in the final calender.
    """

    pdfelements = list()
    pdfelements.append(data[0].pdf_name)
    text_seletion_type = "Whitelist ('" + colored("W", 'green') + "') / Blacklist ('" + colored("B", 'green') + "') / All ('" + colored(
        "A", 'green') + "')"
    finallist = list()
    templist = list()

    for event in data:
        flag = 1
        for element in pdfelements:
            if event.pdf_name == element:
                flag = 0
        if flag:
            pdfelements.append(event.pdf_name)

    for element in pdfelements:
        carrierlist = list()

        print("\nCurrently selected PDF-file: ", colored(element, attrs=['bold']))
        print("\nID\tModule")
        for event in data:
            if event.pdf_name == element:
                carrierlist.append(event)
                print(colored(str(event.module_id), 'yellow', attrs=['bold']) + "\t" + event.module)
        print("\n" + colored("What kind of selection do you want?", attrs=['reverse']))
        print(text_seletion_type)
        print("For help press ('" + colored("?", 'green') + "')")

        correct_input = 1
        while correct_input:
            user_input = input()
            if user_input == 'W' or user_input == 'w':
                correct_input = 0
                templist = whitelist(carrierlist)

            elif user_input == 'B' or user_input == 'b':
                correct_input = 0
                templist = blacklist(carrierlist)

            elif user_input == 'A' or user_input == 'a':
                correct_input = 0
                templist = add_all(carrierlist)

            elif user_input == '?':
                print(colored("\n-Whitelist-", 'yellow', attrs=['bold']) + ": Choose this if you want to add just a few modules.\n"
                      "Selected modules will be added to your calendar\n" +
                      colored("-Blacklist-", 'yellow', attrs=['bold']) + ": Choose this if you want to unselect some modules.\n"
                      "All modules which you had chosen, will not be in your calendar.\n" +
                      colored("-All-", 'yellow', attrs=['bold']) + ": All of the displayed modules will be added to your calendar.")

            else:
                print(colored('Incorrect input!', 'red'))

        finallist = finallist + templist
    if len(finallist) == 0:
        print(colored("You have no modules selected!", 'red'))
        return finallist
    print("\nYour selected modules:")
    for event in data:
        for index in finallist:
            if event.module_id == index:
                print(str(event.module_id) + "\t" + event.module)

    return finallist

def blacklist(carrier: List[DictionaryItem]):

    """
    Summary
    -------
    This function creates a whitelist of modules using a blacklist.

    Parameter
    ---------
    data : list     # Part of the DictionaryItem-list

    Returns
    -------

    data : list     # Returns index of data which has to be in the final list
    """

    whitelist = list()
    blacklist = list()

    print("\n" + colored("Which module would you like to remove?", attrs=['reverse']))
    print("Please select module " + colored("ID", 'yellow', attrs=['bold']) + " which you want to ignore.")
    print("To finish process press ('" + colored("D", 'green') + "')")

    while True:
        user_input = input()
        err = 1
        try:
            if user_input == "D" or user_input == "d":
                break

            for item in carrier:
                if item.module_id == int(user_input):
                    blacklist.append(int(user_input))
                    err = 0
                    break
            if err:
                print(colored("Could not find module.", 'red'))
        except:
            print(colored("Incorrect input!", 'red'))

    for item in carrier:
        flag = 1
        for index in blacklist:
            if item.module_id == index:
                flag = 0
                break

        if flag:
            whitelist.append(item.module_id)

    return whitelist

def whitelist(carrier: List[DictionaryItem]):

    """
    Summary
    -------
    This function creates a whitelist of modules.

    Parameter
    ---------
    data : list     # Part of the DictionaryItem-list

    Returns
    -------

    data : list     # Returns index of data which has to be in the final list
    """

    whitelist = list()

    print("\n" + colored("Which module would you like to add?", attrs=['reverse']))
    print("Please select module " + colored("ID", 'yellow', attrs=['bold']) + " to add")
    print("To finish process press ('" + colored("D", 'green') + "')")

    while True:
        user_input = input()
        flag = 0
        err = 1

        try:
            if user_input == "D" or user_input == "d":
                break

            for item in carrier:
                if item.module_id == int(user_input):
                    flag = 1
                    err = 0
                    break
            if err:
                print(colored("Could not find module.", 'red'))
            if flag:
                whitelist.append(int(user_input))
        except:
            print(colored("Incorrect input!.", 'red'))

    return whitelist

def add_all(carrier: List[DictionaryItem]):

    """
    Summary
    -------
    This function creates a whitelist of modules using a blacklist. But adds all modules

    Parameter
    ---------
    data : list     # Part of the DictionaryItem-list

    Returns
    -------

    data : list     # Returns index of data which has to be in the final list
    """

    whitelist = list()
    blacklist = list()

    for item in carrier:
        flag = 1
        for index in blacklist:
            if item.module_id == index:
                flag = 0
                break

        if flag:
            whitelist.append(item.module_id)

    return whitelist

def format_select(data: List[DataItem]):

    """
    Summary
    -------
    This function asks for preferd file format.
    """

    print("\n" + colored("Which output format do you want?", attrs=['reverse']))
    print(".csv = Google calendar")
    print(".ics = MacOS/iOS calendar")
    print(".csv ('" + colored("C", 'green') + "') / .ics ('" + colored("I", 'green') + "')")

    correct_input = 1
    while correct_input:
        question_input = input()

        if question_input == 'C' or question_input == 'c':
            correct_input = 0
            create_csv(data, name_select())
            print(colored("\nCalendar created, program shutdown!\n", 'magenta'))
            print(colored("You can find your new calendar in your output folder ('/data/output').\n", 'magenta'))

        elif question_input == 'I' or question_input == 'i':
            correct_input = 0
            create_ics(data, name_select())
            print(colored("\nCalendar created, program shutdown!\n", 'magenta'))
            print(colored("You can find your new calendar in your output folder ('/data/output').\n", 'magenta'))

        else:
            print(colored("Incorrect input!", 'red'))

def name_select():

    """
    Summary
    -------
    This function asks for a prefered filename.

    Returns
    -------
    name : str    # User prefered filename or default filename with timestamp
    """

    print("\n" + colored("Do you want to change the default filename?", attrs=['reverse']))
    print("Yes ('" + colored("Y", 'green') + "') / No ('" + colored("N", 'green') + "')")

    correct_input = 1
    while correct_input:
        question_input = input()

        if question_input == 'Y' or question_input == 'y':
            correct_input = 0
            print(colored("Enter filename:", attrs=['reverse']))
            return input()

        elif question_input == 'N' or question_input == 'n':
            correct_input = 0
            return "calendar_" + datetime.datetime.utcnow().strftime('%d%m%Y%H%M%S')

        else:
            print(colored("Incorrect input!", 'red'))


import pygame, pickle

try:
    with open('data.pkl', 'rb') as f:
        data = pickle.load(f)
except FileNotFoundError:
    data = []

highscore_list = data
from pygame.locals import *
pygame.init()

#variables
screen_width = 1000
screen_height= 600
name = ""
active=highscoreFlag=False
menueDone=False
y_spacing=20
timerStart = 0
finishedGame=False

clock = pygame.time.Clock()
fps = 80

screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("Platformer")

#define game variables
tile_size = 40

#load images
bg_img = pygame.image.load("assets/background/background.png")
bg_img2 = pygame.image.load("assets/background/middleground.png")

#function that draws a grid over the screen
def draw_grid():
    for line in range(0,25):
        if line <= 15:
            pygame.draw.line(screen, (255, 255, 255), (0, line * tile_size),(screen_width, line * tile_size))
        pygame.draw.line(screen, (255, 255, 255), (line * tile_size, 0), (line * tile_size, 1280))

#defines and blits the start screen (Name, instructions, controls and objective)
def startScreen():
    global name, active, menueDone
    font = pygame.font.SysFont("Arial",50)
    controlsFont = pygame.font.SysFont("Arial", 28)
    text_color = (0, 0, 0)
    input_surface = font.render(f"Name:{name}", True, text_color)
    background = pygame.Rect(0,0,1000,600)
    instructions_surface = font.render("Press Enter When Done", True, text_color)
    controls_surface = controlsFont.render("E = Dash, A = Move left, D = Move right, SPACE = Jump/Doublejump, M1 = attack", True, text_color)
    objective_text = "Your objective is to eliminate all the monsters and escape through the door"
    objective_surface = controlsFont.render(objective_text, True, text_color)

    #blits the name box in the middle of the screen
    name_width, name_height = input_surface.get_size()
    instructions_width, instructions_height = instructions_surface.get_size()

    name_x = (screen_width - name_width) // 2
    name_y = (screen_height - name_height) // 2
    instructions_x = (screen_width - instructions_width) // 2
    instructions_y = (screen_width - instructions_width) // 2

    input_rect = pygame.Rect(name_x,name_y, input_surface.get_width(), input_surface.get_height())

    pygame.draw.rect(screen, (255, 255, 255), background)
    screen.blit(controls_surface, (90, 0))
    screen.blit(objective_surface, (60, 100))
    screen.blit(input_surface, (name_x, name_y))
    screen.blit(instructions_surface,(instructions_x, instructions_y+100))
    pygame.draw.rect(screen, text_color, input_rect, 1)

    #if the input_rect collides with the mouse and mouse1 is clicked
    mouse_pos = pygame.mouse.get_pos()
    mouse_click = pygame.mouse.get_pressed()
    if input_rect.collidepoint(mouse_pos):
        if mouse_click[0] == 1:  #Left mouse button clicked
            active = True

    #if the condition above occurs
    if active:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                #if the enter key is pressed tha name is saved
                if event.key == pygame.K_RETURN:
                    print("Name entered:", name)
                    active = False
                    menueDone = True
                #the last letter is removed is backspace is pressed
                elif event.key == pygame.K_BACKSPACE:
                    name = name[:-1]
                #name equals name + the key that was pressed
                elif len(name)<7:
                    name += event.unicode

#function for timer (points)
def Timer():
    global timer, timerStart
    #Calculate the time in seconds

    #timerStart prevents the timer from going when in the menue
    if menueDone == False:
        timerStart = pygame.time.get_ticks() // 1000
    if menueDone and finishedGame == False:
        timer = pygame.time.get_ticks() // 1000 - timerStart
        #Check if the timer has reached 10 seconds
        if timer >= 60:
            #Calculate the number of minutes and seconds
            minutes = timer // 60
            seconds = timer % 60

            #If the seconds are less than 10, format them with a leading zero
            if seconds < 10:
                seconds_str = f"0{seconds}"
            else:
                seconds_str = str(seconds)

            #Format the timer string as "m:ss"
            timer = f"{minutes}:{seconds_str}"

        else:
            #Convert the timer value to a string
            timer = str(timer)

        #Render the timer label
        font = pygame.font.SysFont("Arial", 32)
        text_color = (255, 255, 255)
        timer_surface = font.render(f"Time:{timer}", True, text_color)
        #Blit the timer label onto the screen
        screen.blit(timer_surface, (850, 175))

def highscoreList():
    global timer, name, highscore_list

    #sorts the highscore
    #if enemy.allDemonsDead:

    if len(highscore_list)==0:
        highscore_list = [[name,timer]]
    else:
        highscore_list.append([name,timer])

    #saves highscore in a pickle file
    data = highscore_list
    with open('data.pkl', 'wb') as f:
        pickle.dump(data, f)

#draws highscore on the screen
def blitHighscore():
    global highscore_list, y_spacing
    font = pygame.font.SysFont("Arial", 20)
    text_color = (255, 255, 255)
    list_rect = pygame.Rect(870, 0, 200, 250)
    name_surface = font.render("Name", True, text_color)
    time_surface = font.render("Time", True, text_color)

    for i in range(len(highscore_list)):
        scoreboard_surface = font.render(f"{i+1}:   {highscore_list[i][0]} : {highscore_list[i][1]}", True, text_color)
        screen.blit(scoreboard_surface, (835, 25 + i * 20))
        y_spacing += 20

    screen.blit(name_surface, list_rect)
    screen.blit(time_surface, (list_rect.x + 75, list_rect.y))

#sort highscore_list
def sort_highscore_list():
    global highscore_list
    for i in range(len(highscore_list)):
        for j in range(i + 1, len(highscore_list)):
            if highscore_list[i][1] > highscore_list[j][1]:
                highscore_list[i], highscore_list[j] = highscore_list[j], highscore_list[i]
    #List can't contain more than 5 lists
    if len(highscore_list) == 6:
        highscore_list.pop(5)

#blits the endscreen with congratulations, time, name and placement
def blitEndScreen():
    global highscore_list, timer
    font = pygame.font.SysFont("Arial", 32)
    text_color = (0, 0, 0)
    background = pygame.Rect(0, 0, 1000, 600)
    congrats_surface = font.render("Congratulations", True, text_color)
    name_surface = font.render(f"Name: {name}", True, text_color)
    time_surface = font.render(f"Time: {timer}", True, text_color)
    for index in range(len(highscore_list)):
        if name in highscore_list[index][0]:
            placement_surface = font.render(f"You placed in the top {index+1}", True, text_color)
        else:
            placement_surface = font.render(f"You didn't reach the leaderboard", True, text_color)

    #blits everything in the middle
    congrats_width, congrats_height = congrats_surface.get_size()

    congrats_x = (screen_width - congrats_width) // 2
    congrats_y = (screen_height - congrats_height) // 2

    pygame.draw.rect(screen,(255,255,255),background)
    screen.blit(congrats_surface,(congrats_x,congrats_y))
    screen.blit(time_surface,(congrats_x,congrats_y+150))
    screen.blit(name_surface, (congrats_x, congrats_y+100))
    screen.blit(placement_surface, (congrats_x, congrats_y+200))

def Door():
    global timer,  highscoreFlag, finishedGame
    #draws the door
    rectCoordinates = (tile_size*23,screen_height-13.5*tile_size)
    rectSize = (2*tile_size,2.5*tile_size)
    if enemy.allDemonsDead:
        color=(255,255,255)
    else:
        color=(0,0,0)
    pygame.draw.rect(screen,color,(rectCoordinates,rectSize))
    pygame.draw.rect(screen, (0,0,0), (rectCoordinates, rectSize),5)

    #if player collides with door
    if player.rect.colliderect(rectCoordinates, rectSize):
        if enemy.allDemonsDead:
            if highscoreFlag == False:
                highscoreList()
                finishedGame=True
                highscoreFlag = True

class Enemy():
    def __init__(self):
        self.allDemonsDead = False
    def demon(self, x, y):
        self.turned = False
        self.widthDemon = 0
        self.heightDemon = 0
        self.imageDemon = None
        self.rectDemon = None
        self.images_demon_right = []
        self.images_demon_left = []
        self.images_death = []
        self.index = 0
        self.demonDmg = 50
        self.demonHealth = 100  # ska vara 100
        self.demonDead = False
        self.demonDeadAnimations = True
        self.counter = 0
        #the tile that the demon starts in (the x coordinates)
        self.startTile=x

        #creates all the images for animation
        for num in range(0, 4):
            demon_run_right = pygame.image.load(f"assets/demon/run/{num}.png")
            demon_run_right = pygame.transform.scale(demon_run_right, (60, 80))
            demon_run_left = pygame.transform.flip(demon_run_right, True, False)
            self.images_demon_right.append(demon_run_right)
            self.images_demon_left.append(demon_run_left)

        for num in range(0, 6):
            death = pygame.image.load(f"assets/death/{num}.png")
            death = pygame.transform.scale(death, (60, 80))
            self.images_death.append(death)

        self.imageDemon = self.images_demon_right[self.index]

        self.rectDemon = self.imageDemon.get_rect()
        self.rectDemon.x = x
        self.rectDemon.y = y
        self.turned = False
        self.vel_x=2
        self.widthDemon = self.imageDemon.get_width()
        self.heightDemon = self.imageDemon.get_height()

    #conditions for changing the demons image
    def demonAnimations(self):
        self.counter += 1
        animation_cooldown = 5

        if self.counter > animation_cooldown:
            self.counter = 0
            self.index += 1

            if self.demonDead == False:
                if self.index >= len(self.images_demon_right):
                    self.index = 0

                if self.turned == False:
                    self.imageDemon = self.images_demon_right[self.index]
                if self.turned:
                    self.imageDemon = self.images_demon_left[self.index]

        if self.demonHealth <= 0:
            if self.index >= len(self.images_death):
                self.demonDeadAnimations = False
                self.index = 0

            self.imageDemon = self.images_death[self.index]
            self.demonDead = True

        if self.demonDeadAnimations:
            screen.blit(self.imageDemon, self.rectDemon)

    #the update function always runs
    def update(self):
        #movementspeed
        #if the demon is within 200 pixels of the player and on the same y-coordinate it will get double the movementspeed
        if self.rectDemon.x-player.rect.x < 0 and self.rectDemon.x-player.rect.x >= -200 and self.rectDemon.y==player.rect.y:
            self.vel_x =4
        elif self.rectDemon.x-player.rect.x > 0 and self.rectDemon.x-player.rect.x <= 200 and self.rectDemon.y==player.rect.y:
            self.vel_x =4
        else:
            self.vel_x = 2
        self.demonAnimations()
        #changes the end coordinates for the demon depending on where it started (end coordinates = at what coordinates the demon should trun)
        if self.startTile == 8 * tile_size or 9 * tile_size:
            endTile = 15 * tile_size
        if self.startTile == 2 * tile_size:
            endTile = 5 * tile_size
        if self.startTile == 22 * tile_size:
            endTile = 24 * tile_size

        #the demon turns if it reaches the endTile or the startTile (if it is alive)
        if not self.demonDead:
            if self.turned == False:
                if self.rectDemon.x <= endTile:
                    self.rectDemon.x += self.vel_x
                else:
                    self.turned = True
            if self.turned:
                if self.rectDemon.x >= self.startTile:
                    self.rectDemon.x -= self.vel_x
                else:
                    self.turned = False
#creates multiple instances of the enemy class (creates four demons at different coordinates)
demon1 = Enemy()
demon1.demon(9 * tile_size, 480)

#Creates the second demon
demon2 = Enemy()
demon2.demon(8 * tile_size, screen_height-8*tile_size)

#Creates the third demon
demon3 = Enemy()
demon3.demon(2 * tile_size, screen_height - 10 * tile_size)

#Creates the fiourth demon
demon4 = Enemy()
demon4.demon(22 * tile_size, screen_height - 13 * tile_size)

class Combat():
    def __init__(self):
        self.hitCounterDemon = 0
        self.hitCounterPlayer = 0

    #update function runs all the time
    def update(self):
        #defines the cooldown and timer when you get hit
        if player.death==False:
            if self.hitCounterDemon < 50:
                self.hitCounterDemon += 1
            if self.hitCounterPlayer < 50:
                self.hitCounterPlayer += 1
            hitCooldown = 50

            #Combat with demon1

            #if the cooldown is over
            if self.hitCounterDemon >= hitCooldown:
                #player takes damage if the player and demon collides
                if not demon1.demonDead:
                    if player.rect.colliderect(demon1.rectDemon.x, demon1.rectDemon.y, demon1.widthDemon, demon1.heightDemon):
                        self.hitCounterDemon = 0
                        player.health -= demon1.demonDmg
                        #Prevents the player from dashing through the enemy at high speed
                        player.dx = 0

                        #if they collide both player and demon gets knocked back and the demon turns to the other direction
                        if demon1.turned == False:
                            demon1.turned = True
                            demon1.rectDemon.x -= 20
                            player.rect.x += 50
                        else:
                            demon1.turned = False
                            demon1.rectDemon.x += 20
                            player.rect.x -= 50

            #the demon takes dmaage if the cooldown is over and the demon is hit with an attack
            if self.hitCounterPlayer >= hitCooldown:
                if player.rect_attack.colliderect(demon1.rectDemon.x, demon1.rectDemon.y, demon1.widthDemon, demon1.heightDemon) and player.attacked:
                    self.hitCounterPlayer = 0
                    demon1.demonHealth -= player.playerDmg

            #Combat with all the other demons is the same but with other variables for the demon

            #Combat with demon2
            if self.hitCounterDemon >= hitCooldown:
                if not demon2.demonDead:
                    if player.rect.colliderect(demon2.rectDemon.x, demon2.rectDemon.y, demon2.widthDemon, demon2.heightDemon):
                        self.hitCounterDemon = 0
                        player.health -= demon2.demonDmg
                        #Prevents the player from dashing through the enemy at high speed
                        player.dx = 0
                        if demon2.turned == False:
                            demon2.turned = True
                            demon2.rectDemon.x -= 20
                            player.rect.x += 50
                        else:
                            demon2.turned = False
                            demon2.rectDemon.x += 20
                            player.rect.x -= 50

            if self.hitCounterPlayer >= hitCooldown:
                if player.rect_attack.colliderect(demon2.rectDemon.x, demon2.rectDemon.y, demon2.widthDemon, demon2.heightDemon) and player.attacked:
                    self.hitCounterPlayer = 0
                    demon2.demonHealth -= player.playerDmg

            # Combat with demon3
            if self.hitCounterDemon >= hitCooldown:
                if not demon3.demonDead:
                    if player.rect.colliderect(demon3.rectDemon.x, demon3.rectDemon.y,demon3.widthDemon, demon3.heightDemon):
                        self.hitCounterDemon = 0
                        player.health -= demon3.demonDmg
                        # Prevents the player from dashing through the enemy at high speed
                        player.dx = 0
                        if demon3.turned == False:
                            demon3.turned = True
                            demon3.rectDemon.x -= 20
                            player.rect.x += 50
                        else:
                            demon3.turned = False
                            demon3.rectDemon.x += 20
                            player.rect.x -= 50

            if self.hitCounterPlayer >= hitCooldown:
                if player.rect_attack.colliderect(demon3.rectDemon.x, demon3.rectDemon.y,demon3.widthDemon,demon3.heightDemon) and player.attacked:
                    self.hitCounterPlayer = 0
                    demon3.demonHealth -= player.playerDmg

            #Combat with demon4
            if self.hitCounterDemon >= hitCooldown:
                if not demon4.demonDead:
                    if player.rect.colliderect(demon4.rectDemon.x, demon4.rectDemon.y,demon4.widthDemon, demon4.heightDemon):
                        self.hitCounterDemon = 0
                        player.health -= demon4.demonDmg
                        # Prevents the player from dashing through the enemy at high speed
                        player.dx = 0
                        if demon4.turned == False:
                            demon4.turned = True
                            demon4.rectDemon.x -= 20
                            player.rect.x += 50
                        else:
                            demon4.turned = False
                            demon4.rectDemon.x += 20
                            player.rect.x -= 50

            if self.hitCounterPlayer >= hitCooldown:
                if player.rect_attack.colliderect(demon4.rectDemon.x, demon4.rectDemon.y,demon4.widthDemon,demon4.heightDemon) and player.attacked:
                    self.hitCounterPlayer = 0
                    demon4.demonHealth -= player.playerDmg
class Player():
    def __init__(self, x, y):
        self.images_right = []
        self.images_left = []
        self.images_idle_right = []
        self.images_idle_left = []
        self.images_jump_right = []
        self.images_jump_left = []
        self.images_fall_right = []
        self.images_fall_left = []
        self.images_attack1_right = []
        self.images_attack1_left = []
        self.images_attackEffect = []
        self.images_dash_right = []
        self.images_dash_left = []
        self.images_death_right = []
        self.images_death_left = []
        self.index = 0
        self.attackEffect_index = 0
        self.dash_index = 0
        self.counter = 0
        self.dx = 0
        self.dy = 0
        self.dashed = False
        self.health = 200
        self.playerDmg = 50

        #animation
        #attack effect
        for num in range(0,10):
            img_attackEffect = pygame.image.load(f"characters/samurai/attack effect/attackeffect_{num}.png")
            img_attackEffect = pygame.transform.scale(img_attackEffect,(100,100))
            self.images_attackEffect.append(img_attackEffect)

        #attack1 and attack2
        for num in range(0,6):
            img_attack1_right = pygame.image.load(f"characters/samurai/attack1/{num}.png")
            if num < 4:
                img_attack1_right = pygame.transform.scale(img_attack1_right, (60, 80))
            if num > 3:
                img_attack1_right = pygame.transform.scale(img_attack1_right, (200, 80))
            self.images_attack1_right.append(img_attack1_right)
            img_attack1_left = pygame.transform.flip(img_attack1_right, True, False)
            self.images_attack1_left.append(img_attack1_left)
        #jump/fall
        for num in range(0, 2):
            #jump
            img_jump_right = pygame.image.load(f"characters/samurai/jump/{num}.png")
            img_jump_right = pygame.transform.scale(img_jump_right, (60, 80))
            self.images_jump_right.append(img_jump_right)
            img_jump_left = pygame.transform.flip(img_jump_right, True, False)
            self.images_jump_left.append(img_jump_left)

            #fall
            img_fall_right = pygame.image.load(f"characters/samurai/fall/{num}.png")
            img_fall_right = pygame.transform.scale(img_fall_right, (60, 80))
            self.images_fall_right.append(img_fall_right)
            img_fall_left = pygame.transform.flip(img_fall_right, True, False)
            self.images_fall_left.append(img_fall_left)

        #left/right/idle
        for num in range(0, 8):
            img_idle_right = pygame.image.load(f"characters/samurai/idle/{num}.png")
            img_idle_right = pygame.transform.scale(img_idle_right, (60, 80))
            img_idle_left = pygame.transform.flip(img_idle_right, True, False)
            img_right = pygame.image.load(f"characters/samurai/run/{num}.png")
            img_right = pygame.transform.scale(img_right, (60,80))
            img_left = pygame.transform.flip(img_right, True, False)
            self.images_right.append(img_right)
            self.images_left.append(img_left)
            self.images_idle_right.append(img_idle_right)
            self.images_idle_left.append(img_idle_left)

        #dash
        for num in range (0, 6):
            img_dash_left = pygame.image.load(f"characters/samurai/dash/{num}.png")
            img_dash_left = pygame.transform.scale(img_dash_left, (60, 80))
            img_dash_right = pygame.transform.flip(img_dash_left, True, False)
            self.images_dash_right.append(img_dash_right)
            self.images_dash_left.append(img_dash_left)

        #death
        for num in range(0, 6):
            img_death_right = pygame.image.load(f"characters/samurai/death/{num}.png")
            img_death_right = pygame.transform.scale(img_death_right, (80, 80))
            img_death_left = pygame.transform.flip(img_death_right, True, False)
            self.images_death_right.append(img_death_right)
            self.images_death_left.append(img_death_left)

        self.image = self.images_idle_right[self.index]
        self.image_attackEffect = self.images_attackEffect[self.attackEffect_index]
        self.image_dash = self.images_dash_right[self.dash_index]
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.width = self.image.get_width()
        self.height = self.image.get_height()
        self.rect_attack = self.image_attackEffect.get_rect()
        self.rect_attack.x = self.rect.x+100
        self.rect_attack.y = self.rect.y-5
        self.vel_y = 0
        self.jumped = False
        self.jumpedTimes = 0
        self.direction = 1
        self.idle = True
        self.inAir = False
        self.attacked = False
        self.attack_cooldown = 50
        self.dash_duration = 200
        self.attackCounter = 50
        self.dash_counter = 0
        self.death = False
        self.respawnTimer = 0

        self.deathFlag=True

    #draws the healthbar
    def healthbar(self,x,y):
        self.healthbarRect_x=x
        self.healthbarRect_y=y
        self.healthbarHeight=35
        self.healthbarColor=(255,0,0)

        pygame.draw.rect(screen, self.healthbarColor, (self.healthbarRect_x, self.healthbarRect_y, self.health,self.healthbarHeight))
        pygame.draw.rect(screen, (0,0,0),(self.healthbarRect_x, self.healthbarRect_y, 200, self.healthbarHeight),5)

    #function that activates when the player dies
    def playerDeath(self):
        respawnCooldown=20
        self.respawnTimer += 0.1

        self.dashed = False #is needed because player continues dash while dead otherwise

        #label with respawn timer
        font = pygame.font.SysFont("Arial", 50)
        text_color = (255, 255, 255)
        respawnTimer_surface = font.render(f"Respawn: {round(20-self.respawnTimer,1)}", True, text_color)
        text_width, text_height = respawnTimer_surface.get_size()
        text_x = (screen_width - text_width) // 2
        text_y = (screen_height - text_height) // 2
        screen.blit(respawnTimer_surface, (text_x, text_y))

        #deathFlag only occurs once even though playerDeath is called in a while loop ( in update() )
        if self.deathFlag:
            self.index=0
            self.death = True
            self.deathFlag = False
        if self.respawnTimer >= respawnCooldown:
            self.death = False

            #Reset enemy positions and attributes
            demon1.demon(9 * tile_size, 480)
            demon2.demon(8 * tile_size, screen_height - 8 * tile_size)
            demon3.demon(2 * tile_size, screen_height - 10 * tile_size)
            demon4.demon(22 * tile_size, screen_height - 13 * tile_size)

            #reset player
            player.rect.x = 100
            player.rect.y = screen_height - 40
            player.health = 200
            player.rect_attack.y = self.rect.y - 5
            player.dx = 0
            player.vel_y=0

            #resets timer and flag
            self.respawnTimer=0
            self.deathFlag = True

    #function for jumping
    def jump(self):
        self.inAir = True
        self.attacked = False
        self.vel_y = -7
        self.jumped = True
        self.jumpedTimes += 1
        if [pygame.K_SPACE] == False:
            self.jumped = False

    #fuction for attacking
    def attack(self):
        if self.inAir == False:
            self.attacked = True
            self.index = 0
            self.attackEffect_index = 0
            self.attackCounter = 0

    #function for dashing
    def dash(self):
        self.dash_index = 0
        if self.dash_counter <= 0 and self.dashed == False:
            self.vel_y = 0
            self.dashed = True
            if self.direction == 1:
                self.dx = 20
            if self.direction == -1:
                self.dx = -20

    #update function runs all the time
    def update(self):
        player.healthbar(50, 15)

        #if the player is falling (gravity = 3) inAir = True
        if self.vel_y == 5:
            self.inAir = True

        #counts the attack cooldown
        if self.attackCounter < 50:
            self.attackCounter += 1
        if self.dashed == False:
            self.dx = 0
            self.dy = 0
        if self.attacked:
            animation_cooldown = 4
        if self.dashed:
            animation_cooldown = 3
        if self.death:
            animation_cooldown = 10
        else:
            animation_cooldown = 7

        #get keypresses
        key = pygame.key.get_pressed()

        #movement

        if self.death==False:
            if key[pygame.K_a]:
                if self.attacked == False and self.dashed == False:
                    self.dx = -3
                    self.direction = -1

                self.counter += 1
                self.idle = False
            if key[pygame.K_d]:
                if self.attacked == False and self.dashed == False:
                    self.dx = 3
                    self.direction = 1

                self.idle = False

            #if key a or d is not pushed down
            if key[pygame.K_a] == False and key[pygame.K_d] == False:
                self.idle= True

            #limits dashing
            if self.dashed:
                self.dash_counter += 20
                if self.dash_counter > self.dash_duration:
                    self.dashed = False

            if self.dashed == False:
                self.dash_counter -= 1
                if self.dash_counter <= 0:
                    self.dash_counter = 0

        #animations
        #index and cooldowns between each image
        self.counter += 1
        if self.counter > animation_cooldown:
            self.counter = 0
            self.index += 1
            if self.index >= len(self.images_right):
                 self.index = 0

            #facing right
            if self.inAir == False:
                #running right
                if self.direction == 1:
                    self.image = self.images_right[self.index]

                    #idle right
                    if self.idle:
                        self.image = self.images_idle_right[self.index]

                    #attack right
                    if self.attacked:
                        if self.index >= len(self.images_attack1_right):
                            self.index = 0
                            self.attacked = False

                        self.image = self.images_attack1_right[self.index]
                # facing left
                #running left
                if self.direction == -1:
                    self.image = self.images_left[self.index]

                    #idle left
                    if self.idle:
                        self.image = self.images_idle_left[self.index]

                    # attack left
                    if self.attacked:

                        if self.index >= len(self.images_attack1_right):
                            self.index = 0
                            self.attacked = False

                        self.image = self.images_attack1_left[self.index]
            #jumping/falling right and left
            if self.inAir and self.death==False:
                if self.index >= len(self.images_jump_right):
                    self.index = 0
                    if self.direction == 1:
                        if self.vel_y <= 0:
                            self.image = self.images_jump_right[self.index]
                        if self.vel_y >=0:
                            self.image = self.images_fall_right[self.index]
                    if self.direction == -1:
                        if self.vel_y <=0:
                            self.image = self.images_jump_left[self.index]
                        if self.vel_y >=0:
                            self.image = self.images_fall_left[self.index]

        #attack effect in both directions
        if self.counter > 2.5 and self.attackEffect_index < len(self.images_attackEffect):
            self.attackEffect_index += 1
            if self.attacked:
                if self.attackEffect_index >= len(self.images_attackEffect):
                    self.attackEffect_index = 0
                self.image_attackEffect = self.images_attackEffect[self.attackEffect_index]
        #dashing in both directions
        if self.dashed and self.death==False:
            if self.dash_counter > animation_cooldown and self.dash_index < len(self.images_dash_right):
                self.dash_index += 1
                if self.dash_index >= len(self.images_dash_right):
                    self.dash_index = 0
                if self.direction == 1:
                    self.image_dash = self.images_dash_right[self.dash_index]
                if self.direction == -1:
                    self.image_dash = self.images_dash_left[self.dash_index]
        #death animation
        if self.death:

            if self.index >= len(self.images_death_right):
                self.index=5
            if self.direction == 1:
                self.image = self.images_death_right[self.index]
            if self.direction == -1:
                self.image = self.images_death_left[self.index]

        #add gravity
        if self.dashed == False:
            self.vel_y += 0.3
        if self.vel_y > 5:
            self.vel_y = 5
        self.dy += self.vel_y

        #check for collision
        for tile in world.tile_list:
            #check for collision in x-direction
            if tile[1].colliderect(self.rect.x+self.dx, self.rect.y, self.width, self.height):
               self. dx = 0
            #check for collision in y-direction
            if tile[1].colliderect(self.rect.x, self.rect.y+self.dy,self.width, self.height):

                #check if below the ground (jumping)
                if self.vel_y < 0:
                    self.dy = tile[1].bottom - self.rect.top
                    self.vel_y = 0.0
                #check if above the ground (falling)
                elif self.vel_y >= 0:
                    self.dy = tile[1].top - self.rect.bottom
                    self.jumpedTimes = 0
                    self.vel_y = 0
                    self.inAir = False

        #update player coordinates
        self.rect.x += self.dx
        self.rect.y += self.dy
        self.rect_attack.x += self.dx
        self.rect_attack.y += self.dy

        #draw player onto screen
        if self.direction == 1:
            self.rect_attack.x = self.rect.x + 60
        if self.direction == -1:
            self.rect_attack.x = self.rect.x - 100

        #denna kontroll måste göras eftersom bild 4 och 5 i attack ej är centrerade, detta gör så att när man kör flip funktionen
        #på dom så kommer spriten att flytta sig till andra sidan istället istället för att förbli centrerad som med andra sprites.
        if self.direction== -1 and self.attacked and self.index == 4:
            screen.blit(self.image, (self.rect.x-140,self.rect.y))

        elif self.direction== -1 and self.attacked and self.index == 5:
            screen.blit(self.image, (self.rect.x - 140, self.rect.y))
        else:
            screen.blit(self.image, self.rect)

        #dash
        if self.dashed:
            if self.direction == 1:
                screen.blit(self.image_dash,(self.rect.x-50,self.rect.y))
            if self.direction == -1:
                screen.blit(self.image_dash, (self.rect.x + 50, self.rect.y))

        #attack effect
        if self.direction == 1 and self.attacked and self.inAir==False:
            screen.blit(self.image_attackEffect, (self.rect.x+100,self.rect.y-5))
        if self.direction == -1 and self.attacked and self.inAir==False:
            screen.blit(self.image_attackEffect, (self.rect.x-140,self.rect.y-5))

class World():
    def __init__(self, data):
        self.tile_list = []
        #block som ej ska ha någon collision
        #load images
        dirt_img = pygame.image.load("assets/tiles (biome 1)/tile001.png")
        void_img = pygame.image.load("assets/tiles (biome 1)/tile014.png")

        #creates all the images at the right coordinates for each row and column in the grid
        row_count = 0
        for row in data:
            col_count = 0
            for tile in row:
                if tile == 1:
                    img = pygame.transform.scale(dirt_img, (tile_size, tile_size))
                    img_rect = img.get_rect()
                    img_rect.x = col_count * tile_size
                    img_rect.y = row_count * tile_size
                    #saves the image and coordinates in a tuple
                    tile = (img, img_rect)
                    self.tile_list.append(tile)
                if tile == 2:
                    img = pygame.transform.scale(void_img, (tile_size, tile_size))
                    img_rect = img.get_rect()
                    img_rect.x = col_count * tile_size
                    img_rect.y = row_count * tile_size
                    #saves the image and coordinates in a tuple
                    tile = (img, img_rect)
                    self.tile_list.append(tile)
                col_count += 1
            row_count += 1

    #blits the tiles at the right coordinates
    def draw(self):
        for tile in self.tile_list:
            screen.blit(tile[0],tile[1])

#each number represents a different tile in the World() function
world_data=[
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[2,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[2,1,2,1,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
[2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2],
[2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2],
[2,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2],
[2,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2],
[2,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2],
[2,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,2],
[2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2],
[2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,2],
[2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,1,0,2],
[2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,1,1],
]

#instances
player = Player(100, screen_height-40)
enemy = Enemy()
combat = Combat()
world = World(world_data)

run = True
while run:
    clock.tick(60)
    screen.blit(bg_img, (0,0))
    screen.blit(bg_img2, (0,0))
    world.draw()
    Door()
    Timer()
    player.update()
    sort_highscore_list()
    blitHighscore()
    if player.health<=0:
        player.playerDeath()

    #updates every demon
    demon1.update()
    demon2.update()
    demon3.update()
    demon4.update()
    if menueDone == False:
        startScreen()
    #checks if all the demons are dead
    if demon1.demonDead and demon2.demonDead and demon3.demonDead and demon4.demonDead:
        enemy.allDemonsDead = True
    #Render
    screen.blit(screen, (0, 0))

    combat.update()

    #draw_grid()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
             run = False
             break
        if player.death==False:
            #jumping and doublejumping
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and player.jumpedTimes <2:
                    player.jump()
                #if e is pressed the player should dash
                if event.key == pygame.K_e:
                    player.dash()
            #mouseclick
            mKey = pygame.mouse.get_pressed()

            if mKey[0]:
                if player.attackCounter >= player.attack_cooldown:
                    player.attack()
    if finishedGame:
        blitEndScreen()

    pygame.display.update()
pygame.quit()
print(highscore_list)

#to do list
"""Fixa:minuter fungerar ej på scorebaord då den tror att 1:01 minuter < 10 sekunder"""


import time
import numpy as np
import pandas as pd
from utilities.visualization import make_figure

class ShmOHLCGenerator:
    """
    simple harmonic motion (sinewave) data generator for sanity check.
    noise and damping can be added.
    """

    def __init__(self, seed, start_date, num_asset, num_data, noise=0.0, damping=0.0):
        if seed:
            self.seed = seed
            np.random.seed(self.seed)

        self.start_date = start_date
        self.ticker_names = ['shm_{}'.format(i) for i in range(num_asset)]

        self.num_asset = num_asset
        self.num_data = num_data

        self.trend_per_tick = 0.0
        self.noise = noise
        self.damping = damping

    @staticmethod
    def shm_gen(dt=0.001,
                coef=100,  # coef = k/m
                amplitude=2,
                start_trend=100,
                trend_per_tick=0.0,
                noise=0.0,
                damping=0.0,
                verbose=0):
        """Generate simple harmonic motion around trend, with noise and damping"""

        period = 2 * np.pi * np.sqrt(1 / coef)

        if verbose:
            print("%s Amplitude: %.3f" % (time.strftime("%H:%M:%S"), amplitude))
            print("%s Period: %.3f" % (time.strftime("%H:%M:%S"), period))

        # initial stock price
        stock_price = start_trend + np.random.choice([-1, 1]) * amplitude
        stock_velocity = 0.0

        trend_index = start_trend
        t = 0.0

        while True:
            # acceleration based on distance from trend
            acc = - coef * (stock_price - trend_index)
            stock_velocity += acc * dt
            # add noise to velocity
            stock_velocity += np.random.normal(loc=0, scale=noise)
            # damp velocity by a % (could also make this a constant)
            stock_velocity *= (1 - damping)
            # increment stock price
            stock_price += stock_velocity * dt
            # add noise; doesn't impact velocity which makes velocity a partly hidden state variable
            stock_price += np.random.normal(loc=0, scale=noise / 2)

            yield (t, stock_price, trend_index)
            t += dt

    @staticmethod
    def plot_df(df):
        make_figure(df.index, df['close'],
                    title="Simulated Stock Price Data As Simple Harmonic Motion (Sine Wave)",
                    xtitle='Timesteps',
                    ytitle='Value'
                    )

    def get_shm_ohlc_df(self, total_time=1, coef=100, amplitude=2, start_trend=100):
        gen = self.shm_gen(dt=total_time / self.num_data,
                           coef=coef,
                           amplitude=amplitude,
                           start_trend=start_trend,
                           trend_per_tick=self.trend_per_tick,
                           noise=self.noise,
                           damping=self.damping,
                           verbose=0)

        trend_series = []
        stock_series = []
        time_series = []

        for i in range(self.num_data):
            t, stock_price, trend_index = next(gen)
            stock_series.append(stock_price)
            trend_series.append(trend_index)
            time_series.append(t)

        df = pd.DataFrame({'open': stock_series,
                           'high': stock_series,
                           'low': stock_series,
                           'close': stock_series,
                           'volume': trend_series},
                          index=pd.bdate_range(start=self.start_date, freq='1min', periods=self.num_data))
        # print(df)
        return df

    # common main method called by data controller
    def get_multi_data_df(self):
        shm_dfs = []
        for i in range(self.num_asset):
            # total_time = 1, coef = 100, amplitude = 2, start_trend = 100
            total_time = np.random.randint(1, 5)
            coef = np.random.randint(90, 110)
            amplitude = np.random.randint(2, 8)
            start_trend = np.random.randint(50, 150)
            shm_dfs.append(self.get_shm_ohlc_df(total_time, coef, amplitude, start_trend))
        return pd.concat(shm_dfs, keys=self.ticker_names)


#!/usr/bin/env python2
# vim:fileencoding=utf-8
from __future__ import (unicode_literals, division, absolute_import,
                        print_function)

__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'

import time, textwrap, json
from bisect import bisect_right
from base64 import b64encode
from future_builtins import map
from threading import Thread
from Queue import Queue, Empty
from functools import partial
from urlparse import urlparse

from PyQt5.Qt import (
    QWidget, QVBoxLayout, QApplication, QSize, QNetworkAccessManager, QMenu, QIcon,
    QNetworkReply, QTimer, QNetworkRequest, QUrl, Qt, QToolBar,
    pyqtSlot, pyqtSignal)
from PyQt5.QtWebKitWidgets import QWebView, QWebInspector, QWebPage

from calibre import prints
from calibre.constants import FAKE_PROTOCOL, FAKE_HOST
from calibre.ebooks.oeb.polish.parsing import parse
from calibre.ebooks.oeb.base import serialize, OEB_DOCS
from calibre.gui2 import error_dialog, open_url, NO_URL_FORMATTING, secure_web_page
from calibre.gui2.tweak_book import current_container, editors, tprefs, actions, TOP
from calibre.gui2.viewer.documentview import apply_settings
from calibre.gui2.viewer.config import config
from calibre.gui2.widgets2 import HistoryLineEdit2
from calibre.utils.ipc.simple_worker import offload_worker

shutdown = object()

def get_data(name):
    'Get the data for name. Returns a unicode string if name is a text document/stylesheet'
    if name in editors:
        return editors[name].get_raw_data()
    return current_container().raw_data(name)

# Parsing of html to add linenumbers {{{

def parse_html(raw):
    root = parse(raw, decoder=lambda x:x.decode('utf-8'), line_numbers=True, linenumber_attribute='data-lnum')
    return serialize(root, 'text/html').encode('utf-8')

class ParseItem(object):

    __slots__ = ('name', 'length', 'fingerprint', 'parsing_done', 'parsed_data')

    def __init__(self, name):
        self.name = name
        self.length, self.fingerprint = 0, None
        self.parsed_data = None
        self.parsing_done = False

    def __repr__(self):
        return 'ParsedItem(name=%r, length=%r, fingerprint=%r, parsing_done=%r, parsed_data_is_None=%r)' % (
            self.name, self.length, self.fingerprint, self.parsing_done, self.parsed_data is None)

class ParseWorker(Thread):

    daemon = True
    SLEEP_TIME = 1

    def __init__(self):
        Thread.__init__(self)
        self.requests = Queue()
        self.request_count = 0
        self.parse_items = {}
        self.launch_error = None

    def run(self):
        mod, func = 'calibre.gui2.tweak_book.preview', 'parse_html'
        try:
            # Connect to the worker and send a dummy job to initialize it
            self.worker = offload_worker(priority='low')
            self.worker(mod, func, '

')
        except:
            import traceback
            traceback.print_exc()
            self.launch_error = traceback.format_exc()
            return

        while True:
            time.sleep(self.SLEEP_TIME)
            x = self.requests.get()
            requests = [x]
            while True:
                try:
                    requests.append(self.requests.get_nowait())
                except Empty:
                    break
            if shutdown in requests:
                self.worker.shutdown()
                break
            request = sorted(requests, reverse=True)[0]
            del requests
            pi, data = request[1:]
            try:
                res = self.worker(mod, func, data)
            except:
                import traceback
                traceback.print_exc()
            else:
                pi.parsing_done = True
                parsed_data = res['result']
                if res['tb']:
                    prints("Parser error:")
                    prints(res['tb'])
                else:
                    pi.parsed_data = parsed_data

    def add_request(self, name):
        data = get_data(name)
        ldata, hdata = len(data), hash(data)
        pi = self.parse_items.get(name, None)
        if pi is None:
            self.parse_items[name] = pi = ParseItem(name)
        else:
            if pi.parsing_done and pi.length == ldata and pi.fingerprint == hdata:
                return
            pi.parsed_data = None
            pi.parsing_done = False
        pi.length, pi.fingerprint = ldata, hdata
        self.requests.put((self.request_count, pi, data))
        self.request_count += 1

    def shutdown(self):
        self.requests.put(shutdown)

    def get_data(self, name):
        return getattr(self.parse_items.get(name, None), 'parsed_data', None)

    def clear(self):
        self.parse_items.clear()

    def is_alive(self):
        return Thread.is_alive(self) or (hasattr(self, 'worker') and self.worker.is_alive())

parse_worker = ParseWorker()
# }}}

# Override network access to load data "live" from the editors {{{

class NetworkReply(QNetworkReply):

    def __init__(self, parent, request, mime_type, name):
        QNetworkReply.__init__(self, parent)
        self.setOpenMode(QNetworkReply.ReadOnly | QNetworkReply.Unbuffered)
        self.setRequest(request)
        self.setUrl(request.url())
        self._aborted = False
        if mime_type in OEB_DOCS:
            self.resource_name = name
            QTimer.singleShot(0, self.check_for_parse)
        else:
            data = get_data(name)
            if isinstance(data, type('')):
                data = data.encode('utf-8')
                mime_type += '; charset=utf-8'
            self.__data = data
            mime_type = {
                # Prevent warning in console about mimetype of fonts
                'application/vnd.ms-opentype':'application/x-font-ttf',
                'application/x-font-truetype':'application/x-font-ttf',
                'application/font-sfnt': 'application/x-font-ttf',
            }.get(mime_type, mime_type)
            self.setHeader(QNetworkRequest.ContentTypeHeader, mime_type)
            self.setHeader(QNetworkRequest.ContentLengthHeader, len(self.__data))
            QTimer.singleShot(0, self.finalize_reply)

    def check_for_parse(self):
        if self._aborted:
            return
        data = parse_worker.get_data(self.resource_name)
        if data is None:
            return QTimer.singleShot(10, self.check_for_parse)
        self.__data = data
        self.setHeader(QNetworkRequest.ContentTypeHeader, 'application/xhtml+xml; charset=utf-8')
        self.setHeader(QNetworkRequest.ContentLengthHeader, len(self.__data))
        self.finalize_reply()

    def bytesAvailable(self):
        try:
            return len(self.__data)
        except AttributeError:
            return 0

    def isSequential(self):
        return True

    def abort(self):
        self._aborted = True

    def readData(self, maxlen):
        ans, self.__data = self.__data[:maxlen], self.__data[maxlen:]
        return ans
    read = readData

    def finalize_reply(self):
        if self._aborted:
            return
        self.setFinished(True)
        self.setAttribute(QNetworkRequest.HttpStatusCodeAttribute, 200)
        self.setAttribute(QNetworkRequest.HttpReasonPhraseAttribute, "Ok")
        self.metaDataChanged.emit()
        self.downloadProgress.emit(len(self.__data), len(self.__data))
        self.readyRead.emit()
        self.finished.emit()

class NetworkAccessManager(QNetworkAccessManager):

    def createRequest(self, operation, request, data):
        qurl = request.url()
        if operation == self.GetOperation and qurl.host() == FAKE_HOST:
            name = qurl.path()[1:]
            c = current_container()
            if c.has_name(name):
                try:
                    return NetworkReply(self, request, c.mime_map.get(name, 'application/octet-stream'), name)
                except Exception:
                    import traceback
                    traceback.print_exc()
        return QNetworkAccessManager.createRequest(self, operation, request, data)

# }}}

def uniq(vals):
    ''' Remove all duplicates from vals, while preserving order.  '''
    vals = vals or ()
    seen = set()
    seen_add = seen.add
    return tuple(x for x in vals if x not in seen and not seen_add(x))

def find_le(a, x):
    'Find rightmost value in a less than or equal to x'
    try:
        return a[bisect_right(a, x)]
    except IndexError:
        return a[-1]

class WebPage(QWebPage):

    sync_requested = pyqtSignal(object, object, object)
    split_requested = pyqtSignal(object, object)

    def __init__(self, parent):
        QWebPage.__init__(self, parent)
        settings = self.settings()
        apply_settings(settings, config().parse())
        settings.setMaximumPagesInCache(0)
        secure_web_page(settings)
        settings.setAttribute(settings.PrivateBrowsingEnabled, True)
        settings.setAttribute(settings.LinksIncludedInFocusChain, False)
        settings.setAttribute(settings.DeveloperExtrasEnabled, True)
        settings.setDefaultTextEncoding('utf-8')
        data = 'data:text/css;charset=utf-8;base64,'
        css = '[data-in-split-mode="1"] [data-is-block="1"]:hover { cursor: pointer !important; border-top: solid 5px green !important }'
        data += b64encode(css.encode('utf-8'))
        settings.setUserStyleSheetUrl(QUrl(data))

        self.setNetworkAccessManager(NetworkAccessManager(self))
        self.setLinkDelegationPolicy(self.DelegateAllLinks)
        self.mainFrame().javaScriptWindowObjectCleared.connect(self.init_javascript)
        self.init_javascript()

    def javaScriptConsoleMessage(self, msg, lineno, source_id):
        prints('preview js:%s:%s:'%(unicode(source_id), lineno), unicode(msg))

    def init_javascript(self):
        if not hasattr(self, 'js'):
            from calibre.utils.resources import compiled_coffeescript
            self.js = compiled_coffeescript('ebooks.oeb.display.utils', dynamic=False)
            self.js += P('csscolorparser.js', data=True, allow_user_override=False)
            self.js += compiled_coffeescript('ebooks.oeb.polish.preview', dynamic=False)
        self._line_numbers = None
        mf = self.mainFrame()
        mf.addToJavaScriptWindowObject("py_bridge", self)
        mf.evaluateJavaScript(self.js)

    @pyqtSlot(str, str, str)
    def request_sync(self, tag_name, href, sourceline_address):
        try:
            self.sync_requested.emit(unicode(tag_name), unicode(href), json.loads(unicode(sourceline_address)))
        except (TypeError, ValueError, OverflowError, AttributeError):
            pass

    def go_to_anchor(self, anchor, lnum):
        self.mainFrame().evaluateJavaScript('window.calibre_preview_integration.go_to_anchor(%s, %s)' % (
            json.dumps(anchor), json.dumps(str(lnum))))

    @pyqtSlot(str, str)
    def request_split(self, loc, totals):
        actions['split-in-preview'].setChecked(False)
        loc, totals = json.loads(unicode(loc)), json.loads(unicode(totals))
        if not loc or not totals:
            return error_dialog(self.view(), _('Invalid location'),
                                _('Cannot split on the body tag'), show=True)
        self.split_requested.emit(loc, totals)

    @property
    def line_numbers(self):
        if self._line_numbers is None:
            def atoi(x):
                try:
                    ans = int(x)
                except (TypeError, ValueError):
                    ans = None
                return ans
            val = self.mainFrame().evaluateJavaScript('window.calibre_preview_integration.line_numbers()')
            self._line_numbers = sorted(uniq(filter(lambda x:x is not None, map(atoi, val))))
        return self._line_numbers

    def go_to_line(self, lnum):
        try:
            lnum = find_le(self.line_numbers, lnum)
        except IndexError:
            return
        self.mainFrame().evaluateJavaScript(
            'window.calibre_preview_integration.go_to_line(%d)' % lnum)

    def go_to_sourceline_address(self, sourceline_address):
        lnum, tags = sourceline_address
        if lnum is None:
            return
        tags = [x.lower() for x in tags]
        self.mainFrame().evaluateJavaScript(
            'window.calibre_preview_integration.go_to_sourceline_address(%d, %s)' % (lnum, json.dumps(tags)))

    def split_mode(self, enabled):
        self.mainFrame().evaluateJavaScript(
            'window.calibre_preview_integration.split_mode(%s)' % (
                'true' if enabled else 'false'))

class WebView(QWebView):

    def __init__(self, parent=None):
        QWebView.__init__(self, parent)
        self.inspector = QWebInspector(self)
        w = QApplication.instance().desktop().availableGeometry(self).width()
        self._size_hint = QSize(int(w/3), int(w/2))
        self._page = WebPage(self)
        self.setPage(self._page)
        self.inspector.setPage(self._page)
        self.clear()
        self.setAcceptDrops(False)

    def sizeHint(self):
        return self._size_hint

    def refresh(self):
        self.pageAction(self.page().Reload).trigger()

    @dynamic_property
    def scroll_pos(self):
        def fget(self):
            mf = self.page().mainFrame()
            return (mf.scrollBarValue(Qt.Horizontal), mf.scrollBarValue(Qt.Vertical))

        def fset(self, val):
            mf = self.page().mainFrame()
            mf.setScrollBarValue(Qt.Horizontal, val[0])
            mf.setScrollBarValue(Qt.Vertical, val[1])
        return property(fget=fget, fset=fset)

    def clear(self):
        self.setHtml(_(
            '''

Live preview

Here you will see a live preview of the HTML file you are currently editing.
            The preview will update automatically as you make changes.

Note that this is a quick preview
            only, it is not intended to simulate an actual ebook reader. Some
            aspects of your ebook will not work, such as page breaks and page margins.
            '''))

    def inspect(self):
        self.inspector.parent().show()
        self.inspector.parent().raise_()
        self.pageAction(self.page().InspectElement).trigger()

    def contextMenuEvent(self, ev):
        menu = QMenu(self)
        p = self.page()
        mf = p.mainFrame()
        r = mf.hitTestContent(ev.pos())
        url = unicode(r.linkUrl().toString(NO_URL_FORMATTING)).strip()
        ca = self.pageAction(QWebPage.Copy)
        if ca.isEnabled():
            menu.addAction(ca)
        menu.addAction(actions['reload-preview'])
        menu.addAction(QIcon(I('debug.png')), _('Inspect element'), self.inspect)
        if url.partition(':')[0].lower() in {'http', 'https'}:
            menu.addAction(_('Open link'), partial(open_url, r.linkUrl()))
        menu.exec_(ev.globalPos())

class Preview(QWidget):

    sync_requested = pyqtSignal(object, object)
    split_requested = pyqtSignal(object, object, object)
    split_start_requested = pyqtSignal()
    link_clicked = pyqtSignal(object, object)
    refresh_starting = pyqtSignal()
    refreshed = pyqtSignal()

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.l = l = QVBoxLayout()
        self.setLayout(l)
        l.setContentsMargins(0, 0, 0, 0)
        self.view = WebView(self)
        self.view.page().sync_requested.connect(self.request_sync)
        self.view.page().split_requested.connect(self.request_split)
        self.view.page().loadFinished.connect(self.load_finished)
        self.inspector = self.view.inspector
        self.inspector.setPage(self.view.page())
        l.addWidget(self.view)
        self.bar = QToolBar(self)
        l.addWidget(self.bar)

        ac = actions['auto-reload-preview']
        ac.setCheckable(True)
        ac.setChecked(True)
        ac.toggled.connect(self.auto_reload_toggled)
        self.auto_reload_toggled(ac.isChecked())
        self.bar.addAction(ac)

        ac = actions['sync-preview-to-editor']
        ac.setCheckable(True)
        ac.setChecked(True)
        ac.toggled.connect(self.sync_toggled)
        self.sync_toggled(ac.isChecked())
        self.bar.addAction(ac)

        self.bar.addSeparator()

        ac = actions['split-in-preview']
        ac.setCheckable(True)
        ac.setChecked(False)
        ac.toggled.connect(self.split_toggled)
        self.split_toggled(ac.isChecked())
        self.bar.addAction(ac)

        ac = actions['reload-preview']
        ac.triggered.connect(self.refresh)
        self.bar.addAction(ac)

        actions['preview-dock'].toggled.connect(self.visibility_changed)

        self.current_name = None
        self.last_sync_request = None
        self.refresh_timer = QTimer(self)
        self.refresh_timer.timeout.connect(self.refresh)
        parse_worker.start()
        self.current_sync_request = None

        self.search = HistoryLineEdit2(self)
        self.search.initialize('tweak_book_preview_search')
        self.search.setPlaceholderText(_('Search in preview'))
        self.search.returnPressed.connect(partial(self.find, 'next'))
        self.bar.addSeparator()
        self.bar.addWidget(self.search)
        for d in ('next', 'prev'):
            ac = actions['find-%s-preview' % d]
            ac.triggered.connect(partial(self.find, d))
            self.bar.addAction(ac)

    def find(self, direction):
        text = unicode(self.search.text())
        self.view.findText(text, QWebPage.FindWrapsAroundDocument | (
            QWebPage.FindBackward if direction == 'prev' else QWebPage.FindFlags(0)))

    def request_sync(self, tagname, href, lnum):
        if self.current_name:
            c = current_container()
            if tagname == 'a' and href:
                if href and href.startswith('#'):
                    name = self.current_name
                else:
                    name = c.href_to_name(href, self.current_name) if href else None
                if name == self.current_name:
                    return self.view.page().go_to_anchor(urlparse(href).fragment, lnum)
                if name and c.exists(name) and c.mime_map[name] in OEB_DOCS:
                    return self.link_clicked.emit(name, urlparse(href).fragment or TOP)
            self.sync_requested.emit(self.current_name, lnum)

    def request_split(self, loc, totals):
        if self.current_name:
            self.split_requested.emit(self.current_name, loc, totals)

    def sync_to_editor(self, name, sourceline_address):
        self.current_sync_request = (name, sourceline_address)
        QTimer.singleShot(100, self._sync_to_editor)

    def _sync_to_editor(self):
        if not actions['sync-preview-to-editor'].isChecked():
            return
        try:
            if self.refresh_timer.isActive() or self.current_sync_request[0] != self.current_name:
                return QTimer.singleShot(100, self._sync_to_editor)
        except TypeError:
            return  # Happens if current_sync_request is None
        sourceline_address = self.current_sync_request[1]
        self.current_sync_request = None
        self.view.page().go_to_sourceline_address(sourceline_address)

    def report_worker_launch_error(self):
        if parse_worker.launch_error is not None:
            tb, parse_worker.launch_error = parse_worker.launch_error, None
            error_dialog(self, _('Failed to launch worker'), _(
                'Failed to launch the worker process used for rendering the preview'), det_msg=tb, show=True)

    def name_to_qurl(self, name=None):
        name = name or self.current_name
        qurl = QUrl()
        qurl.setScheme(FAKE_PROTOCOL), qurl.setAuthority(FAKE_HOST), qurl.setPath('/' + name)
        return qurl

    def show(self, name):
        if name != self.current_name:
            self.refresh_timer.stop()
            self.current_name = name
            self.report_worker_launch_error()
            parse_worker.add_request(name)
            self.view.setUrl(self.name_to_qurl())
            return True

    def refresh(self):
        if self.current_name:
            self.refresh_timer.stop()
            # This will check if the current html has changed in its editor,
            # and re-parse it if so
            self.report_worker_launch_error()
            parse_worker.add_request(self.current_name)
            # Tell webkit to reload all html and associated resources
            current_url = self.name_to_qurl()
            self.refresh_starting.emit()
            if current_url != self.view.url():
                # The container was changed
                self.view.setUrl(current_url)
            else:
                self.view.refresh()
            self.refreshed.emit()

    def clear(self):
        self.view.clear()
        self.current_name = None

    @property
    def is_visible(self):
        return actions['preview-dock'].isChecked()

    @property
    def live_css_is_visible(self):
        try:
            return actions['live-css-dock'].isChecked()
        except KeyError:
            return False

    def start_refresh_timer(self):
        if self.live_css_is_visible or (self.is_visible and actions['auto-reload-preview'].isChecked()):
            self.refresh_timer.start(tprefs['preview_refresh_time'] * 1000)

    def stop_refresh_timer(self):
        self.refresh_timer.stop()

    def auto_reload_toggled(self, checked):
        if self.live_css_is_visible and not actions['auto-reload-preview'].isChecked():
            actions['auto-reload-preview'].setChecked(True)
            error_dialog(self, _('Cannot disable'), _(
                'Auto reloading of the preview panel cannot be disabled while the'
                ' Live CSS panel is open.'), show=True)
        actions['auto-reload-preview'].setToolTip(_(
            'Auto reload preview when text changes in editor') if not checked else _(
                'Disable auto reload of preview'))

    def sync_toggled(self, checked):
        actions['sync-preview-to-editor'].setToolTip(_(
            'Disable syncing of preview position to editor position') if checked else _(
                'Enable syncing of preview position to editor position'))

    def visibility_changed(self, is_visible):
        if is_visible:
            self.refresh()

    def split_toggled(self, checked):
        actions['split-in-preview'].setToolTip(textwrap.fill(_(
            'Abort file split') if checked else _(
                'Split this file at a specified location.\n\nAfter clicking this button, click'
                ' inside the preview panel above at the location you want the file to be split.')))
        if checked:
            self.split_start_requested.emit()
        else:
            self.view.page().split_mode(False)

    def do_start_split(self):
        self.view.page().split_mode(True)

    def stop_split(self):
        actions['split-in-preview'].setChecked(False)

    def load_finished(self, ok):
        if actions['split-in-preview'].isChecked():
            if ok:
                self.do_start_split()
            else:
                self.stop_split()

    def apply_settings(self):
        s = self.view.page().settings()
        s.setFontSize(s.DefaultFontSize, tprefs['preview_base_font_size'])
        s.setFontSize(s.DefaultFixedFontSize, tprefs['preview_mono_font_size'])
        s.setFontSize(s.MinimumLogicalFontSize, tprefs['preview_minimum_font_size'])
        s.setFontSize(s.MinimumFontSize, tprefs['preview_minimum_font_size'])
        sf, ssf, mf = tprefs['preview_serif_family'], tprefs['preview_sans_family'], tprefs['preview_mono_family']
        s.setFontFamily(s.StandardFont, {'serif':sf, 'sans':ssf, 'mono':mf, None:sf}[tprefs['preview_standard_font_family']])
        s.setFontFamily(s.SerifFont, sf)
        s.setFontFamily(s.SansSerifFont, ssf)
        s.setFontFamily(s.FixedFont, mf)


import cv2
import cvlib as cv
from cvlib.object_detection import draw_bbox
from vidgear.gears import CamGear
stream = CamGear(source='https://www.youtube.com/watch?v=En_3pkxIJRM', stream_mode = True, logging=True).start() # YouTube Video URL as input
count=0
while True:
    frame = stream.read()
    count += 1
    if count % 6 != 0:
        continue

    frame=cv2.resize(frame,(1020,600))
    cv2.imshow("FRAME",frame)
    if cv2.waitKey(1)&0xFF==27:
        break
stream.release()
cv2.destroyAllWindows()