import pygame
from levels import *
from constants import *
from player import Player
from sounds import Sound

class Game:
    def __init__(self):
        pygame.init()
        self.background_sound = Sound()

        pygame.key.set_repeat(50, 50)
        size = [SCREEN_WIDTH, SCREEN_HEIGHT]

        self.screen = pygame.display.set_mode(size)
        pygame.display.set_caption(TITLE)

        self.clock = pygame.time.Clock()
        self.font_name = pygame.font.match_font(FONT)

        self.running = True
        self.isover = False
        self.gameispaused = False
        self.levels = {
            1: Level_01,
            2: Level_02,
            3: Level_03,
            4: Level_04,
            5: Level_05,
            6: Level_06,
            7: Level_07,
            8: Level_08,
            9: Level_09,
            10: Level_10}

        self.show_start_screen()

    def new(self, level = 0):
        self.player = Player()
        self.active_sprite_list = pygame.sprite.Group()
        self.active_sprite_list.add(self.player)
        self.level = level + 1
        self.current_level = self.levels[self.level](self.player)
        self.player.level = self.current_level
        self.background_sound.next_song()
        self.run()

    def run(self):
        self.playing = True
        while self.playing:
            self.events()
            self.update()
            self.draw()
        self.end_game()

    def update(self):
        if self.player.iskill:
            self.playing = False
            self.isover = True
            self.gameover()
            return

        if not self.gameispaused and self.running:
            self.active_sprite_list.update()
            self.current_level.update()
            # If the player gets near the right side, shift the world left (-x)
            if self.player.rect.right >= 500:
                diff = self.player.rect.right - 500
                self.player.rect.right = 500
                self.current_level.shift_world(-diff)

            # If the player gets near the left side, shift the world right (+x)
            if self.player.rect.left <= 120:
                diff = 120 - self.player.rect.left
                self.player.rect.left = 120
                self.current_level.shift_world(diff)

            # If the player gets to the end of the level, go to the next level
            current_position = (self.player.rect.x
                                + self.current_level.world_shift)
            if current_position < self.current_level.level_limit:
                self.player.rect.x = 120
                if self.level < len(self.levels) - 1:
                    self.level += 1
                    self.current_level = self.levels[self.level](self.player)
                    self.player.level = self.current_level
                else:
                   self.end_screen();
        else:
            return

    def events(self):
        for bullet in self.player.bullets:
            for enemies in self.current_level.enemy_list:
                if (bullet.y - bullet.radius < enemies.rect.y + 147
                    and bullet.y + bullet.radius > enemies.rect.y):
                    if (bullet.x + bullet.radius > enemies.rect.x
                        and bullet.x - bullet.radius < enemies.rect.x + 52):
                        enemies.loseenergy(self.player.power)
                        if bullet in self.player.bullets:
                            self.player.bullets.remove(bullet)
            if bullet.x < SCREEN_WIDTH and bullet.x > 0:
                bullet.x += bullet.vel
            else:
                if bullet in self.player.bullets:
                    self.player.bullets.remove(bullet)

        for event in pygame.event.get():
            if event.type == pygame.USEREVENT:
                self.background_sound.next_song()
            if event.type == pygame.QUIT:
                if self.playing:
                    self.playing = False
                self.running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_p:
                    self.gameispaused = True
                    self.pause_screen()

                if event.key == pygame.K_LEFT:
                    self.player.sprint(self.player.direction)
                    self.player.go_left()

                if event.key == pygame.K_RIGHT:
                    self.player.sprint(self.player.direction)
                    self.player.go_right()

                if event.key == pygame.K_UP:
                    self.last_key_pressed = pygame.K_UP
                    if self.level < 2:
                        self.draw_text(GRAVITY_WARN,
                                       24,
                                       RED,
                                       SCREEN_WIDTH/2,
                                       SCREEN_HEIGHT/2)

                        self.draw_text(OPTIONS,
                                       22,
                                       RED,
                                       SCREEN_WIDTH/2,
                                       SCREEN_HEIGHT * 3/4)

                        pygame.display.flip()
                        self.wait_for_key()
                    else:
                        self.player.jump()

                if event.key == pygame.K_SPACE:
                    self.player.increasepower()
                    self.player.shoot()

                if event.key == pygame.K_DOWN:
                    self.player.invisibility()

            if event.type == pygame.KEYUP:
                self.player.stop()

    def draw(self):
        self.screen.fill(BLACK)
        self.current_level.draw(self.screen)
        font = pygame.font.SysFont(FONT, 20, True)

        if not self.player.invisible:
            self.active_sprite_list.draw(self.screen)
            text = font.render(HEALTH .format(self.player.health),
                               1,
                               RED)

            self.screen.blit(text,
                             (self.player.rect.x -10,
                              self.player.rect.y -20))

            text = font.render(PRESS_ME,
                               1,
                               WHITE)

            self.screen.blit(text,
                             (SCREEN_WIDTH - 200, 10))

        for bullet in self.player.bullets:
            bullet.draw(self.screen)

        self.clock.tick(FPS)

        for enemies in self.current_level.enemy_list:
            enemies.draw(self.screen)
            if enemies.power is not 0:
                text = font.render(LEVEL .format(enemies.power),
                                   1,
                                   WHITE)

                self.screen.blit(text,
                                 (enemies.rect.x- 10,
                                  enemies.rect.y - 20))

        pygame.display.flip()
        pygame.display.update()

    def show_start_screen(self):
        self.screen.fill(WHITE)

        self.draw_text(TITLE,
                       48,
                       BLACK,
                       SCREEN_WIDTH /2,
                       SCREEN_HEIGHT / 4)

        self.draw_text(START,
                       32,
                       BLACK,
                       SCREEN_WIDTH / 2,
                       SCREEN_HEIGHT / 2)

        self.draw_text(TIP_LVL,
                       12,
                       BLACK,
                       SCREEN_WIDTH / 5,
                       SCREEN_HEIGHT - 21)

        pygame.display.flip()
        self.wait_for_key()

    def gameover(self):
        self.background_sound.stop_music()
        self.screen.fill(WHITE)
        self.draw_text(GAME_OVER,
                       48,
                       BLACK,
                       SCREEN_WIDTH /2,
                       SCREEN_HEIGHT / 4)

        self.draw_text(OPTIONS,
                       22,
                       BLACK,
                       SCREEN_WIDTH / 2,
                       SCREEN_HEIGHT * 3 / 4)

        pygame.display.flip()
        self.wait_for_key()

    def pause_screen(self):
        self.current_level.tip(self.screen)
        self.draw_text(GAME_PAUSED,
                       22,
                       WHITE,
                       SCREEN_WIDTH /2,
                       SCREEN_HEIGHT/4)

        self.draw_text(OPTIONS,
                       22,
                       WHITE,
                       SCREEN_WIDTH /2,
                       SCREEN_HEIGHT * 1/2)

        pygame.display.flip()
        self.wait_for_key()

    def wait_for_key(self):
        waiting = True
        while waiting:
            self.clock.tick(FPS)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    waiting = False
                    self.running = False
                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_q:
                        self.running = False
                        self.playing = False
                        waiting = False

                    if event.key == pygame.K_RETURN:
                        waiting = False
                        if self.gameispaused:
                            self.gameispaused = False
                        if self.isover:
                            self.isover = False
                            self.new()

    def end_screen(self):
        self.screen.fill(WHITE)
        self.isover = True
        self.draw_text(GAME_WIN,
                       40,
                       BLACK,
                       SCREEN_WIDTH/2,
                       SCREEN_HEIGHT/2)

        self.draw_text(OPTIONS,
                       22,
                       BLACK,
                       SCREEN_WIDTH / 2,
                       SCREEN_HEIGHT * 3 / 4)

        pygame.display.flip()
        self.wait_for_key()

    def draw_text(self, text, size, color, x, y):
        font = pygame.font.Font(self.font_name, size)
        text_surface = font.render(text, True, color)
        text_rect = text_surface.get_rect()
        text_rect.midtop = (x, y)
        self.screen.blit(text_surface, text_rect)

    def end_game(self):
        if self.isover and not self.running:
            pygame.quit()


from helpers import *
import cv2
import tensorflow as tf
import json
import sys

# Checking for incorrect usage
if len(sys.argv) != 2:
    print("Usage: python main.py path_to_image")
    exit(-1)
image_file = sys.argv[1]

# These are set to the default names from exported models, update as needed.
INPUT_TENSOR_NAME = 'image_tensor:0'
OUTPUT_TENSOR_NAMES = ['detected_boxes:0', 'detected_scores:0', 'detected_classes:0']
filename = "Object_Identification_Model/model.pb"
labels_filename = "Object_Identification_Model/labels.txt"

# Create tf graph and return list of labels
labels = create_tf_graph(filename, labels_filename)
image = cv2.imread(image_file)
if image is None:
    print("Invalid Path")
    exit(-1)
image = resize_down_to_1600_max_dim(image)
# Create clone to visualize on
clone = image.copy()
# Necessary preprocessing
network_input_size = 320
augmented_image = cv2.resize(image, (network_input_size, network_input_size))
# Extracting probabilities and box bounds
pred = predict_from_graph(OUTPUT_TENSOR_NAMES, augmented_image, INPUT_TENSOR_NAME)
final = []
# Scaling percentage box bounds
h, w = image.shape[:2]
for i in pred[0]:
    for j in range(4):
        if j % 2 == 0:
            i[j] *= w
        else:
            i[j] *= h
        if i[j] < 0:
            i[j] = 0
coords = pred[0]
# Applying non-maxima suppression
ind = tf.image.non_max_suppression(pred[0], pred[1], len(coords), iou_threshold=0.8,
                                   score_threshold=float('-inf'), name=None)
# Only taking into account images with a high probability
for i in ind:
    j = pred[1][i]
    if j > 0.6:
        j = [j, pred[0][i], i]
        final.append(j)
coords_list = []
# Creating a final list of box bounds which only included those of selected boxes
for j in final:
    coords_list.append(list(coords[j[2]]))
# Order boxes according to their rows and columns
# Rows and columns of each box stored in loc
loc, coords_list = order_boxes(coords_list)
# Extracting all lettuce images from main image
images = []
for i in coords_list:
    images.append(image[int(i[1]):int(i[3]), int(i[0]):int(i[2])])
if len(images) == 0:
    print("No lettuces detected")
    exit(-1)
# Calculating green intensity of each leaf
green_intensity = []
for i in images:
    total = 0
    count = 0
    for j in i:
        for x in j:
            if int(x[1]) > 0.75*(int(x[0])+int(x[2])):
                total += x[1]
                count += 1
    avg = total/count
    if avg > 220:
        avg = 220
    green_intensity.append(1-avg/220)
# Calculating the relative size of each lettuce
sizes = []
total = 0
for i in images:
    total += i.shape[0] * i.shape[1]
avg = total/len(images)
for i in images:
    area = i.shape[0] * i.shape[1]
    if area > 1.25*avg:
        sizes.append("Large")
    elif area < 0.75*avg:
        sizes.append("Small")
    else:
        sizes.append("Medium")
# These are set to the default names from exported models, update as needed.
output_layer = 'loss:0'
input_node = 'Placeholder:0'
filename = "Image_Classification_Model/model.pb"
labels_filename = "Image_Classification_Model/labels.txt"
# Load graph and extract labels
labels = create_tf_graph(filename, labels_filename)
pred = []
for j in images:
    # Necessary preprocessing
    img = resize_down_to_1600_max_dim(j)
    h, w = img.shape[:2]
    min_dim = min(w, h)
    max_square_image = crop_center(img, min_dim, min_dim)
    augmented_image = resize_to_256_square(max_square_image)
    with tf.compat.v1.Session() as sess:
        input_tensor_shape = sess.graph.get_tensor_by_name('Placeholder:0').shape.as_list()
    network_input_size = input_tensor_shape[1]
    # Crop the center for the specified network_input_Size
    augmented_image = crop_center(augmented_image, network_input_size, network_input_size)
    predictions = predict_from_graph([output_layer], augmented_image, input_node)
    # Convert numpy array to list
    predictions = predictions.tolist()
    # Take the most likely result into account
    prob = max(predictions[0])
    for i in range(len(predictions[0])):
        if predictions[0][i] == prob:
            ind = i
    # If diseased probability is low, output as mixed
    if labels[ind] == "Diseased" and prob < 0.5:
        label = "Mixed"
    else:
        label = labels[ind]
    pred.append((label, prob))
# Resize to fit visualization on screen
if clone.shape[0] > 800 or clone.shape[1] > 800:
    scale = 800/max(clone.shape)
    clone = cv2.resize(clone, (int(clone.shape[1]*scale), int(clone.shape[0]*scale)))
scale = clone.shape[0]/image.shape[0]
for i in range(len(coords_list)):
    for j in range(len(coords_list[i])):
        coords_list[i][j] *= scale
output_info = []
# Output to json and visualize as rectangles
for i in range(len(coords_list)):
    output_info.append({
        "Coordinates": coords_list[i],
        "Object_Identification_Probability": float(final[i][0]),
        "Status": pred[i][0], "Classification_Probability": pred[i][1],
        "Row": loc[i][0],
        "Column": loc[i][1],
        "Green_Intensity": green_intensity[i],
        "Size": sizes[i]})
    if pred[i][0] == 'Healthy':
        color = (0, 255, 0)
    elif pred[i][0] == 'Mixed':
        color = (0, 255, 255)
    else:
        color = (0, 0, 255)
    cv2.rectangle(clone, (int(coords_list[i][0]), int(coords_list[i][1])),
                  (int(coords_list[i][2]), int(coords_list[i][3])), color, 2)
    cv2.putText(clone, pred[i][0], (int(coords_list[i][0]), int(coords_list[i][1])+10),
                cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 0), 2)
    cv2.putText(clone, str(loc[i][0]) + ":" + str(loc[i][1]),
                (int(coords_list[i][0]), int(coords_list[i][1]) + 30),
                cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 0), 2)
with open("output_info.json", "w") as write_file:
    json.dump(output_info, write_file, indent=4)
cv2.imshow('Visual Representation', clone)
cv2.waitKey(0)
cv2.imwrite('Visual_Representation.png', clone)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Jun 19 11:54:08 2020

@author: dohertyguirand
"""

from bert import Ner
import urllib.request
import io
import PyPDF2 as p2

import sys
sys.stdout = open('ex13', 'w')

url = 'https://pdf.usaid.gov/pdf_docs/PA00WPD5.pdf'

open = urllib.request.urlopen(url).read()
memoryFile = io.BytesIO(open)
pdfread = p2.PdfFileReader(memoryFile)
docInfo = pdfread.getNamedDestinations()
print(docInfo)
#model = Ner("out_large/")

i = 0
fullText = ""
textArr = []
#while i< pdfread.getNumPages():
pageinfo = pdfread.getPage(2)
newText = str(pageinfo.extractText())
fullText +=newText

'''textArr.append(newText)
    i = i + 1'''

foundTitles = []
relevantTitles = [" COP", " DCdocOP", " AOR", " COR", " AOR/COR", " Chief of Party", " CHIEF OF PARTY", " Deputy Chief of Party", " DEPUTY CHIEF OF PARTY", " Evaluation Specialist", " Evaluation Team Leader", " National Expert", " Research Consultant", " Field Researcher"]
'''for i in textArr:
    pageArr = i.split("\n")
    for k in pageArr:
        for t in relevantTitles:
            if t in k:
                foundTitles.append(k)
print(foundTitles)'''
'''dic = {}
n = 500
chunks = [fullText[i:i+n] for i in range(0,len(fullText), n)]

for c in chunks:
    output = model.predict(c)
    print(output)
    line = ""
    tag = ""
    for i in output:
        if "PER" in i['tag']:
            print(i)
            if(i['tag'][0:1] == "B"):
                if line != "":
                    dic[line] = i['tag']
                line = ""

            line += " " + i['word']
            tag = i['tag']

for i in dic:
    print(i)
    print("\n")'''


import dash_bootstrap_components as dbc
import pandas as pd
import plotly.express as px
from dash import html, dcc
import plotly.io as pio
pio.templates.default = "simple_white"

class FastViewCo2(object):
    def __init__(self, data):
        self.df_co2 = data
        Un_Kt = 1000
        co2_country = data.groupby("name")['CO2'].sum()
        co2_country_acum = sum(co2_country)
        co2_country_df = pd.DataFrame(co2_country).reset_index()
        co2_country_df['% Representation'] = (co2_country_df['CO2'] / co2_country_acum) * 100
        co2_country_df['CO2'] = co2_country_df['CO2'] / Un_Kt
        co2_country_df = co2_country_df.sort_values(by='% Representation', ascending=False)

        co2_country_df['acumulado'] = co2_country_df['% Representation'].cumsum()
        co2_country_df = co2_country_df.reset_index()
        co2_country_df = co2_country_df

        ten_top = co2_country_df.iloc[10, 4]
        ten_top = str(f'{ten_top:.2f}' + '%')

        top_countries = list(co2_country_df['name'].head(8))
        g20_df = data[data['name'].isin(top_countries)]

        self.co2_country_df = co2_country_df
        self.ten_top = ten_top
        self.top_countries = top_countries
        self.g20_df = g20_df

    def get_fig_geo_co2(self):
        data = self.df_co2
        fig_geo_co2 = px.choropleth(data, locations='code',
                                    animation_frame='year',
                                    color='CO2',
                                    hover_name='name',
                                    color_continuous_scale='temps_r'
                                    )
        fig_geo_co2.update_layout(height=350)
        return fig_geo_co2

    def get_fig_countries_co2(self):
        fig_countries_co2 = px.area(self.g20_df.sort_values(by='CO2', ascending=False),
                                    x="year",
                                    y="CO2",
                                    color="name",
                                    line_group="name")
        fig_countries_co2.update_layout(height=350, )
        return fig_countries_co2

    def get_fig_pie_co2(self):
        fig_pie_co2 = px.pie(self.co2_country_df.head(10).sort_values(by='CO2', ascending=False),
                             values='% Representation', names='name',
                             hover_data=['name'], labels={'% Representation': '%'})
        fig_pie_co2.update_traces(textposition='inside', textinfo='label+value')
        return fig_pie_co2

    def get_fig_scatter(self):
        fig_scatter = px.scatter(
            self.df_co2, x='GDP', y='CO2',
            animation_frame='year',
            animation_group='CO2',
            size='pop',
            color='code_region',
            hover_name='name',
            log_x=True,
            range_x=[100, 100000],
            range_y=[100, 12000000]
        )
        return fig_scatter

    def get_fig_area_case_ukraine(self):
        case_ukraine = px.area(self.df_co2[self.df_co2['name'] == 'Ukraine'],
                               x="year",
                               y="CO2",
                               color="name",
                               line_group="name")
        return case_ukraine

    def get_html_components(self):
        return dbc.CardBody([
            dbc.Row([
                dbc.Col([html.Label("Overall view", className="align-middle")])],
                style={
                    "background-color": "#EEFFD6",
                    'height': '35px',
                    'border-radius': '5px',
                    'padding': '5px 0px',
                    'text-align': 'left'
                }
            ),
            dbc.Row([
                dbc.Col([dcc.Graph(id='id-geo-co2', figure=self.get_fig_geo_co2())], width=6),
                dbc.Col([dcc.Graph(id='id-area-country-co2', figure=self.get_fig_countries_co2())], width=6),
            ]),
            dbc.Row(
                [dbc.Col(html.Div('Comparative with other economics indicators'))],
                style={
                    "background-color": "#EEFFD6",
                    'height': '35px',
                    'border-radius': '5px',
                    'padding': '5px 0px',
                    'text-align': 'left',
                }
            ),
            dbc.Row([
                dbc.Col(
                    [
                        html.Label('% Emitions top ten', className='card-tittle'),
                        html.H4(self.ten_top)
                    ],
                    style={
                        'border-radius': '5px',
                        'margin-top': '30px',
                        'padding': '30px 0 0 30px'
                    },
                    width=2),
                dbc.Col(
                    [
                        dcc.Graph(
                            id='id-pie-co2',
                            config={'displayModeBar': False},
                            figure=self.get_fig_pie_co2())
                    ],
                    width=4),
                dbc.Col(
                    [
                        dcc.Graph(
                            id='id-scatter-co2',
                            config={'displayModeBar': False},
                            figure=self.get_fig_scatter())
                    ],
                    width=6),
            ]),
            dbc.Row([
                dbc.Col(html.Div('Case Ukraine'),)],
                style={
                    "background-color": "#EEFFD6",
                    'height': '35px',
                    'border-radius': '5px',
                    'padding': '5px 0px',
                    'text-align': 'left',
                }
            ),
            dbc.Row(
                [
                    dbc.Col(
                        [
                            dcc.Graph(
                                id='id-area-case-ukraine',
                                config={'displayModeBar': False},
                                figure=self.get_fig_area_case_ukraine())
                        ],
                        width=12),
            ]),
        ])


class TLRuleFrench0001 (TLRuleAbstract):
	profile = 1
	def createTitleDescription(self):
		self.title="An non-breakable space before [;], [:], [!], [?], and closing "+\
			"guillemets."
		self.description=	\
			"Put an non-breakable space [⎵] before some ponctuation : [;], [:], "+\
			"[!], [?] or [%s]. The exepctions are numbers before [;:] "%self.language.quotes[1]+\
			"and puntucations [!?] after [!?].\n"+\
			"example :	'Bonjour! ' → 'Bonjour⎵!'\n"+\
			"			'Bonjour; ' → 'Bonjour⎵;'\n"+\
			"			'Bonjour: ' → 'Bonjour⎵:'\n"+\
			"			'Bonjour? ' → 'Bonjour⎵?'\n"+\
			"			'Bonjour ! ' → 'Bonjour⎵!'\n"+\
			"			'Bonjour ? ' → 'Bonjour⎵?'\n"+\
			"			'10:30' → '10:30' (same)\n"+\
			"			'10;30' → '10;30' (same)\n"+\
			"			'Pardon⎵?!' → 'Pardon⎵?!' (same)\n"

	def correct(self,last_char,next_char,cursor):
		if next_char in (';:!?'+self.language.quotes[1]):
			if  next_char in ';:' and last_char in [str(i) for i in range(10)]:
				return False
			if  next_char in '?!' and last_char in '?!':
				return False
			if last_char==' ':
				cursor.deletePreviousChar()
				COTextCursorFunctions.insertText(cursor,u'\u00A0')
				return True
			if last_char!=u'\u00A0':
				COTextCursorFunctions.insertText(cursor,u'\u00A0')
				return True
		return False

class TLRuleFrench0002 (TLRuleAbstract):
	title="No non-breakable space if it is not before a ponctuation or after "+\
			"an oppening guillemet or after a dialog dash, or a number."
	description=	\
		"Usually we prevent using an non-breakable space [⎵] if it is not "+\
		"before a ponctuation like [;], [:], [!], [?], or a closing "+\
		"guillemet or a dialog dash [–] or a number. It can also be used after "+\
		"an opening guillemet. It replaces the non-breakable space by a "+\
		"simple space.\n"+\
		"example :	'Je⎵suis' → 'Je suis'\n"+\
		"			'«⎵Bonjour' → '«⎵Bonjour' (same)\n"+\
		"			'Bonjour⎵!' → 'Bonjour⎵!' (same)\n"+\
		"			'–⎵Salut' → '–⎵Salut' (same)\n"+\
		"			'200⎵000' → '200⎵000' (same)"
	profile = 1
	def correct(self,last_char,next_char,cursor):
		if last_char==u'\u00A0' and (next_char not in \
											[u';',u':',u'!',u'?',u'\u00BB']+\
											[str(i) for i in range(10)]):
			last_last_char=self.language.lastChar(cursor,n=2)
			# we check it caused by an oppening "guillemet":
			if last_last_char not in [u'\u00AB' , u'\u2014']:
				cursor.deletePreviousChar()
				COTextCursorFunctions.insertText(cursor,u' ')
				return True
		return False

class TLRuleFrench0003 (TLRuleAbstract):
	title="No space before a point or a comma."
	description=	\
		"It deletes a space or an non-breakable space [⎵] before a comma.\n"+\
		"example :	'Très bien .' → 'Très bien.'\n"+\
		"			'Très bien⎵.' → 'Très bien.'\n"+\
		"			'Charles , toi et moi.' → 'Charles, toi et moi.'\n"
	profile = 0

	def correct(self,last_char,next_char,cursor):
		if last_char in [u' ', u'\u00A0'] and next_char in [u'.',u',']:
			cursor.deletePreviousChar()
			return True
		return False

# class TLRuleFrench0007 (TLRuleCommonQuote0001):
# 	quotes = ("\u00AB\u00A0","\u00A0\u00BB")
# 	title="Replace the char [\"] by a opening or closing guillemet"
# 	description=	\
# 		"When pressing the char [\"], it replace by : an opening guillemet "+\
# 		"[«] if it is preceded by a space, an non-breakable space [⎵] or a "+\
# 		"newline ; a closing guillemet [»] otherwise. It also insert an "+\
# 		"non-breakable space after the opening guillemet and before the "+\
# 		"closing guillemet.\n"+\
# 		"example :	'\"Bonjour' → '«⎵Bonjour'"+\
# 		"			'Salut.\"' → 'Salut.⎵»'"

class TLRuleFrench0004 (TLRuleAbstract):
	title="An non-breakable space before after a diolog dash."
	description=	\
		"It puts an non-breakable space [⎵] after a diolog dash [—] (or "+\
		"replace the simple space that was there).\n\
		example :	'— Bonjour' → '—⎵Bonjour'\n\
					'—Bonjour' → '—⎵Bonjour"
	profile = 1

	def correct(self,last_char,next_char,cursor):
		if last_char==u'\u2014' and next_char!=u'\u00A0':
			if next_char==' ':
				cursor.deleteChar()
				COTextCursorFunctions.insertText(cursor,u'\u00A0')
				return True
			if next_char!=u'\u00A0':
				COTextCursorFunctions.insertText(cursor,u'\u00A0')
				return True
		return False

class TLWordCorrectionRuleFrench001 (TLRuleAbstract):
	title=u"Replace the [oe] by [œ] and [OE] or [Oe] by [Œ]"
	description=	\
		"In French, most of the word with 'oe' have an elision"
	profile = 1

	def correct(self,last_word,cursor):
		if last_word.find(u'oe')!=-1:
			if last_word not in {'moelle'}:
				return last_word.replace(u'oe',u'\u0153')
		elif last_word.find(u'Oe')!=-1:
				return last_word.replace(u'Oe',u'Œ')
		elif last_word.find(u'OE')!=-1:
				return last_word.replace(u'OE',u'Œ')

		return False

def plugin_dialogCorrection(language,cursor):
	for block,_ in COTextCursorFunctions.yieldBlock(cursor):
		cur_tmp=QtGui.QTextCursor(block)
		next_char=language.nextChar(cur_tmp)
		if next_char=='\u2014':
			cur_tmp.deleteChar()
		else:
			cur_tmp.insertText('\u2014')
		language.correct_between_chars(cur_tmp)

language = Language(
	name="French",
	code="fr",
	code_enchant="fr_FR",
	afterCharRules=[
						TLRuleCommon0001,
						TLRuleCommon0002,
						TLRuleCommon0003,
						TLRuleCommon0004,
						TLRuleCommon0005,
						TLRuleCommon0006,
						TLRuleCommon0007,
						TLRuleCommon0008,
						TLRuleCommon0009,
						TLRuleCommon0010,
						TLRuleCommon0011,
						TLRuleFrench0001,
						TLRuleFrench0002,
						TLRuleFrench0003,
						TLRuleFrench0004,
						],
	afterWordRules = [ TLWordCorrectionRuleFrench001 ],
	shortcuts_insert={
			(QtCore.Qt.CTRL+QtCore.Qt.Key_7		,QtCore.Qt.SHIFT+QtCore.Qt.Key_A)	:"\u00C0",
			(QtCore.Qt.CTRL+QtCore.Qt.Key_Comma	,QtCore.Qt.SHIFT+QtCore.Qt.Key_C)	:"\u00C7",
			(QtCore.Qt.CTRL+QtCore.Qt.Key_4		,QtCore.Qt.SHIFT+QtCore.Qt.Key_E)	:"\u00C9",
			(QtCore.Qt.CTRL+QtCore.Qt.Key_7		,QtCore.Qt.SHIFT+QtCore.Qt.Key_E)	:"\u00C8",
			(QtCore.Qt.CTRL+QtCore.Qt.Key_Space	,)									:"\u00A0"}
			,
	shortcuts_correction_plugins={
		(QtCore.Qt.CTRL+QtCore.Qt.Key_D,)	: plugin_dialogCorrection ,
		# (QtCore.Qt.CTRL+QtCore.Qt.Key_L,)	: self.delete_bloc       ,
		},
	delimiters = {
				'«':(u'«\u00A0',u'\u00A0»'),
				'"':(u'«\u00A0',u'\u00A0»'),
				'(':('(',')'),
				'[':('[',']'),
				},
	quotes = ("«","»"),
	inside_quotes = "\u00A0",

		)


from django.forms import ModelForm
from django.http import HttpResponse, HttpResponseNotFound, HttpResponseGone
from django.shortcuts import render, redirect, get_object_or_404
import datetime

from app.models import Book

class BookForm(ModelForm):
    class Meta:
        model = Book
        fields = ['name', 'pages', 'date_written', 'type']

def home(request):
    html = """

Django CRUD Example

    Book list

    """
    return HttpResponse(html)

def book_list(request, template_name='book_list.html'):
    books = Book.objects.all()
    data = {}
    data['object_list'] = books
    return render(request, template_name, data)

def book_list_range(request, y1, m1, d1, y2, m2, d2, template_name='book_list.html'):
    date1 = datetime.date(int(y1), int(m1), int(d1))
    date2 = datetime.date(int(y2), int(m2), int(d2))
    books = Book.objects.exclude(date_written__lt=date1).exclude(date_written__gt=date2)
    print(len(books), date1, date2)
    data = {}
    data['object_list'] = books
    data['date_range_start'] = date1
    data['date_range_end'] = date2
    return render(request, template_name, data)

def book_create(request, template_name='book_form.html'):
    form = BookForm(request.POST or None)
    if form.is_valid():
        form.save()
        return redirect('book_list')
    return render(request, template_name, {'form':form})

def book_update(request, pk):
    book= get_object_or_404(Book, pk=pk)
    form = BookForm(request.POST or None, instance=book)
    print(request.POST);
    if form.is_valid():
        form.save()
        return HttpResponse(status=200)
    return HttpResponse(status=400)

def book_delete(request, pk):
    book= get_object_or_404(Book, pk=pk)
    if request.method=='DELETE':
        book.delete()
        return HttpResponse(status=204)
    return HttpResponse(status=405)


class Solution(object):
    def largestNumber(self, cost, target):
        """
        :type cost: List[int]
        :type target: int
        :rtype: str
        """
        res = self.dfs(cost, target, {})
        return str(res) if res > 0 else '0'

    def dfs(self, cost, t, dp):
        if t == 0:
            return 0
        if t in dp:
            return dp[t]

        cur = float('-inf')
        for d in range(1, 10):
            if t >= cost[d - 1]:
                cur = max(cur,
                          self.dfs(cost, t - cost[d - 1], dp) * 10 + d)
        dp[t] = cur
        return cur


class Solution:
    def vowelStrings(self, words: List[str], queries: List[List[int]]) -> List[int]:
        n = len(words)
        vowels = {'a', 'e', 'i', 'o', 'u'}
        pre = [0 for _ in range(n)]
        if words[0][0] in vowels and words[0][-1] in vowels:
            pre[0] = 1

        for i in range(1, n):
            if words[i][0] in vowels and words[i][-1] in vowels:
                pre[i] = pre[i - 1] + 1
            else:
                pre[i] = pre[i - 1]
        # print(pre)

        res = []
        for l, r in queries:
            start = 0 if l == 0 else pre[l - 1]
            end = pre[r]
            res.append(end - start)

        return res


from .models import Comment, Post
from django import forms
from django.utils.text import slugify
from PIL import Image
import io

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('body', 'image')
        widgets = {
            'image': forms.FileInput(attrs={'class': 'btn, btn-sm'}),
        }
        labels = {
            'body': 'Comment',
            'image': 'Upload image'
        }

    def clean_image(self):
        image = self.cleaned_data.get('image', False)
        if image:
            img = Image.open(image)
            max_size = (800, 800)  # Max size (width, height)
            img.thumbnail(max_size, Image.LANCZOS)
            img_io = io.BytesIO()
            img_format = img.format if img.format else 'JPEG'
            img.save(img_io, format=img_format, quality=60)
            img_io.seek(0)  # Reset file pointer to the beginning
            image.name = 'resized_' + image.name  # Change the image filename
            # Update the image file to the resized image
            image.file = img_io
        return image

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'excerpt', 'content',
                  'featured_image',]
        labels = {
            'excerpt': 'Short Title',
        }

    def clean_title(self):
        title = self.cleaned_data.get('title').capitalize()
        slug = slugify(title)

        unique_slug = slug
        num = 1
        while Post.objects.filter(slug=unique_slug).exists():
            unique_slug = '{}-{}'.format(slug, num)
            num += 1
        self.cleaned_data['slug'] = unique_slug

        return title

class ContactForm(forms.Form):
    name = forms.CharField(
        max_length=80,
        required=True,
        label='Full Name',
        widget=forms.TextInput(attrs={
            'placeholder': 'Ann Smith'
        })
    )
    email = forms.EmailField(
        required=True,
        widget=forms.EmailInput(attrs={
            'placeholder': 'ann.smith@gmail.com'
        })
    )
    message = forms.CharField(
        required=True,
        widget=forms.Textarea(attrs={
            'placeholder': 'What can we assist you with?'
        })
    )


# -*- coding: utf-8 -*
# author: unknowwhite@outlook.com
# wechat: Ben_Xiaobai
# from os import add_dll_directory
import sys
# from threading import Event
# from traceback import print_exception
sys.path.append("./")
sys.setrecursionlimit(10000000)
from configs import admin,kafka
import time
from component.public_func import show_my_memory
from component.db_func import show_project,select_properties,insert_update_access_control_list
import json
import traceback
from configs.export import write_to_log

class access_control:

    def __init__(self,project=None):
        # self.ip_group = {}
        # self.ip = {}
        # self.distinct_id = {}
        self.projects = project if project else {}
        # self.customized = {}
        self.start_time = int(time.time())
        self.check_mem_start = int(time.time())
        self.my_memory = 0
        self.term_times = {'distinct_id':1,'add_on_key':admin.access_control_per_add_on_key,'ip':admin.access_control_distinct_id_per_ip,'ip_group':admin.access_control_distinct_id_per_ip*admin.access_control_ip_per_ip_group,'ip_group_extend':admin.access_control_distinct_id_per_ip*admin.access_control_ip_per_ip_group*admin.access_control_ip_group_per_ip_group_extend}
        self.type_int={'ip':60,'ip_group':61,'distinct_id':62,'add_on_key':63,'ip_group_extend':80}

    def check_mem(self):
        #每30秒检查一次内存占用量
        if int(time.time()-self.check_mem_start) <= 30 and self.projects != {}:
            return self.my_memory
        else:
            self.my_memory = int(show_my_memory())
            self.check_mem_start = int(time.time())
            return self.my_memory

    def refresh_threshold_list(self):
        self.threshold_list = {}
        project_list = show_project()[0]
        for project in project_list:
            if project[0] not in self.threshold_list:
                self.threshold_list[project[0]] = {}
            if project[4]:
                self.threshold_list[project[0]]['default_sum'] = project[4]
            if project[5]:
                self.threshold_list[project[0]]['default_event'] = project[5]
            event_threshold_list = select_properties(project=project[0])[0]
            for item in event_threshold_list:
                if item[0] not in self.threshold_list[project[0]]:
                    self.threshold_list[project[0]][item[0]] = item[1]
        # print(self.threshold_list)

    def insert_data(self,project,key,type_str,event,pv,hour,date):
        insert_update_access_control_list(project=project,key=key,type_int=self.type_int[type_str],event=event,pv=pv,date=date,hour=hour)

    def check_threshold(self,project,event):
        if project:
            if event == 'all':
                if 'all' in self.threshold_list[project]:
                    limit = self.threshold_list[project]['all']
                elif 'default_sum' in self.threshold_list[project]:
                    limit = self.threshold_list[project]['all']['default_sum']
                else:
                    limit =  admin.access_control_sum_count
            elif event != '' or event != ' ':
                if projects_project_event in self.threshold_list[projects_project]:
                    limit = self.threshold_list[projects_project][projects_project_event]
                elif 'default_event' in self.threshold_list[projects_project]:
                    limit = self.threshold_list[projects_project]['default_event']
                else:
                    limit = admin.access_control_event_default

    def etl(self):
        self.refresh_threshold_list()
        date = time.strftime("%Y-%m-%d", time.localtime())
        hour = int(time.strftime("%H", time.localtime()))
        for projects_project in self.projects:
            if projects_project in self.threshold_list:
                for projects_project_event in self.projects[projects_project]:
                    if self.projects[projects_project][projects_project_event] == 'all' :
                        #如果event是all的触发量。如果没有则使用全局总量
                        if 'all' in self.threshold_list[projects_project]:
                            limit = self.threshold_list[projects_project]['all']
                        elif 'default_sum' in self.threshold_list[projects_project]:
                            limit = self.threshold_list[projects_project]['all']['default_sum']
                        else:
                            limit =  admin.access_control_sum_count
                    elif self.projects[projects_project][projects_project_event] != '' :
                        #event不是all的触发量。如果没有，则使用项目阈值，如果再没有，则使用全局事件量
                        if projects_project_event in self.threshold_list[projects_project]:
                            limit = self.threshold_list[projects_project][projects_project_event]
                        elif 'default_event' in self.threshold_list[projects_project]:
                            limit = self.threshold_list[projects_project]['default_event']
                        else:
                            limit = admin.access_control_event_default
                    for term in self.projects[projects_project][projects_project_event]:
                        #比对项目与限制值
                        for content in self.projects[projects_project][projects_project_event][term]:
                            if self.projects[projects_project][projects_project_event][term][content] >= limit*self.term_times[term]*admin.access_control_max_window/3600:
                                self.insert_data(project=projects_project,key=content,type_str=term,event=projects_project_event,pv=self.projects[projects_project][projects_project_event][term][content],hour=hour,date=date)
            elif projects_project:
                for projects_project_event in self.projects[projects_project]:
                    if self.projects[projects_project][projects_project_event] == 'all' :
                        limit =  admin.access_control_sum_count
                    else:
                        limit = admin.access_control_event_default
                    for term in self.projects[projects_project][projects_project_event]:
                        #比对项目与限制值
                        for content in self.projects[projects_project][projects_project_event][term]:
                            if self.projects[projects_project][projects_project_event][term][content] >= limit*self.term_times[term]*admin.access_control_max_window/3600:
                                self.insert_data(project=projects_project,key=content,type_str=term,event=projects_project_event,pv=self.projects[projects_project][projects_project_event][term][content],hour=hour,date=date)
        self.projects = {}
        self.start_time = int(time.time())
        self.my_memory = int(show_my_memory())

    def update_data(self,project,event,term,content):
        if term not in self.projects[project]['all']:
            self.projects[project]['all'][term] = {}
        self.projects[project]['all'][term][content] = self.projects[project]['all'][term][content] + 1 if content in self.projects[project]['all'][term] else 1
        if event:
            if term not in self.projects[project][event]:
                self.projects[project][event][term] = {}
            self.projects[project][event][term][content] = self.projects[project][event][term][content] + 1 if content in self.projects[project][event][term] else 1

    def commit(self,project=None,event=None,ip_commit=None,distinct_id_commit=None,add_on_key_commit=None):
        if ip_commit:
            ip_group_commit = '.'.join(ip_commit.split('.')[0:3])
            ip_group_extend_commit = '.'.join(ip_commit.split('.')[0:2])
            self.update_data(project=project,event=event,term='ip',content=ip_commit)
            self.update_data(project=project,event=event,term='ip_group',content=ip_group_commit)
            self.update_data(project=project,event=event,term='ip_group_extend',content=ip_group_extend_commit)
        if distinct_id_commit:
            self.update_data(project=project,event=event,term='distinct_id',content=distinct_id_commit)
        if add_on_key_commit:
            self.update_data(project=project,event=event,term='add_on_key',content=add_on_key_commit)

    def traffic(self,project=None,event=None,ip_commit=None,distinct_id_commit=None,add_on_key_commit=None):
        if project and project not in self.projects:
            self.projects[project] = {}
        if 'all' not in self.projects[project]:
            self.projects[project]['all'] = {'ip_group':{},'ip':{},'distinct_id':{},'add_on_key':{}}
        if event not in self.projects[project]:
            self.projects[project][event] = {'ip_group':{},'ip':{},'distinct_id':{},'add_on_key':{}}
        if int(time.time())-self.start_time >= admin.access_control_max_window or self.check_mem() >= admin.access_control_max_memory:
            write_to_log(filename='access_control', defname='traffic', result='开始清理:'+str(self.check_mem()))
            self.etl()
            write_to_log(filename='access_control', defname='traffic', result='完成清理:'+str(self.check_mem()))
            self.traffic(project=project,event=event,ip_commit=ip_commit,distinct_id_commit=distinct_id_commit,add_on_key_commit=add_on_key_commit)
        else:
            self.commit(project=project,event=event,ip_commit=ip_commit,distinct_id_commit=distinct_id_commit,add_on_key_commit=add_on_key_commit)
            # print('commit')

if __name__ == "__main__":
    if admin.access_control_commit_mode =='access_control':
        from component.access_control import access_control
        from component.kafka_op import get_message_from_kafka
        ac_access_control = access_control()
        results = get_message_from_kafka(group_id=kafka.client_group_id+'_'+admin.access_control_kafka_client_group_id,client_id=kafka.client_id+'_'+admin.access_control_kafka_client_client_id)
        for item in results :
            group = json.loads(item.value.decode('utf-8'))['group'] if "group" in json.loads(item.value.decode('utf-8')) else None
            data = json.loads(item.value.decode('utf-8'))['data']
            offset = item.offset
            if group == 'event_track':
                try:
                    ac_access_control.traffic(project=data['project'],event=data['data_decode']['event'] if 'event' in data['data_decode'] else None,ip_commit=data['ip'],distinct_id_commit=data['data_decode']['distinct_id'],add_on_key_commit=data['data_decode']['properties'][admin.access_control_add_on_key] if admin.access_control_add_on_key in data['data_decode']['properties'] else None)
                except Exception:
                    error = traceback.format_exc()
                    write_to_log(filename='access_control', defname='main', result=error)