#!/usr/bin/env python
"""
The 'templates' directory contains two Jinja2 templates for rendering the
graph:

* `index.html` - the skeleton which only loads the CSS files, and then includes
  the output of the second template:
* `graph.html` - this is the template which actually renders a graph.

This module is responsible for preparing and rendering the templates.
"""

from collections import namedtuple, defaultdict
import datetime
from flask import render_template
from WateringSite.contributionchart import dateutils
from WateringSite.contributionchart import parser
from WateringSite.contributionchart import statistics
from WateringSite.contributionchart import bp
GridCell = namedtuple('GridCell', ['date', 'contributions'])

def create_graph(devices, eventsdict):
    """
    Prepare the `index.html` template.
    """
    graphs = []
    contributions = defaultdict(int)
    for Device in devices:
        contributions = parser.parse_events(Device.watering_events)

        graph = {"data": gridify_contributions(contributions), "cell_class": _cell_class(contributions.values()),
                 "longest_streak": statistics.longest_streak(
                     [key for key, val in contributions.items() if val > 0]
                 ), "current_streak": statistics.current_streak(
                [key for key, val in contributions.items() if val > 0]
            ), "sum": sum(contributions.values()), "device_name": Device.device_name, "last_date": (
                    [""] + sorted([key for key, v in contributions.items() if v])
            )[-1]}

        graphs.append(graph)

    weekdays = dateutils.weekday_initials()
    for idx in [0, 2, 4, 6]:
        weekdays[idx] = ""

    months = [
        cell.date.strftime("%b")
        for cell in gridify_contributions(contributions)[0]
    ]
    months = filter_months(months)

    return render_template('index.html', graphs=graphs, devices=devices,
                           today=dateutils.today(),
                           start=dateutils.start(),
                           weekdays=weekdays,
                           months=months, events=eventsdict)

def gridify_contributions(contributions):
    """
    The contributions graph has seven rows (one for each day of the week).
    It spans a year. Given a dict of date/value pairs, rearrange these results
    into seven rows of "cells", where each cell records a date and a value.
    """
    start = dateutils.start()
    today = dateutils.today()

    graph_entries = []

    # The first row is a Sunday, so go back to the last Sunday before the start
    if start.weekday() == 6:
        first_date = start
    else:
        first_date = start - datetime.timedelta(start.weekday() + 1 % 7)
    next_date = first_date

    first_row_dates = [first_date]
    while (next_date <= today) and (next_date + datetime.timedelta(7) <= today):
        next_date += datetime.timedelta(7)
        first_row_dates.append(next_date)

    # Now get contribution counts for each of these dates, and save the row
    first_row = [
        GridCell(date, contributions[date]) for date in first_row_dates
    ]
    graph_entries.append(first_row)

    # For each subsequent day of the week, use the first row as a model: add
    # the appropriate number of days and count the contributions
    for i in range(1, 7):
        row_dates = [day + datetime.timedelta(i) for day in first_row_dates]
        next_row = [
            GridCell(date, contributions[date]) for date in row_dates
        ]
        graph_entries.append(next_row)

    return graph_entries

@bp.app_template_filter('tooltip')
def tooltip_text(cell):
    """
    Returns the tooltip text for a cell.
    """
    if cell.contributions == 0:
        count = "No waterings"
    elif cell.contributions == 1:
        count = "1 watering"
    else:
        count = "%d waterings" % cell.contributions
    date_str = dateutils.display_date(cell.date)
    return "%s on %s" % (count, date_str)

def _cell_class(values):
    """
    Returns a function which determines how a cell is highlighted.
    """
    quartiles = statistics.quartiles(values)

    def class_label(cell):
        if cell.date > dateutils.today() or cell.date < dateutils.start():
            return "empty"
        elif cell.contributions == 0:
            return "grad0"
        elif cell.contributions <= quartiles[1]:
            return "grad1"
        elif cell.contributions <= quartiles[2]:
            return "grad2"
        elif cell.contributions <= quartiles[3]:
            return "grad3"
        else:
            return "grad4"
    return class_label

def filter_months(months):
    """
    We only want to print each month heading once, over the first column
    which contains days only from that month. This function filters a list of
    months so that only the first unique month heading is shown.
    """
    for idx in reversed(range(len(months))):
        if months[idx] == months[idx - 1]:
            months[idx] = ""

    # If the same month heading appears at the beginning and end of the year,
    # then only show it at the end of the year
    if months.count(months[0]) > 1:
        months[0] = ""
    if months.count(months[-1]) > 1:
        months[-1] = ""

    # Since each month takes up cells, we delete an empty space for each month
    # heading
    indices = [idx for idx, month in enumerate(months) if month]
    for idx in reversed(indices):
        if idx != len(months) - 1:
            del months[idx+1]

    return months


import os
import sys
import argparse
from torch import nn
from fedlab.core.network import DistNetwork
from fedlab.contrib.algorithm.basic_server import AsyncServerHandler
from fedlab.core.server.manager import AsynchronousServerManager
from fedlab.models import MLP
import torch
from torchvision import datasets, models, transforms
import torchvision
import torchvision.transforms as transforms
import random
import torch
from torchvision import datasets, models, transforms
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader, random_split

def load_dataset():
    # Suas duas strings
    string1 = "biglycan"
    string2 = "breakhis"

    # Escolha aleatoriamente entre as duas strings
    name = random.choice([string1, string2])

    # Caminho para o diretório do conjunto de dados
    data_dir = "./dataset/"+str(name)

    # Transformações de pré-processamento que você deseja aplicar às imagens
    transform = transforms.Compose([
        transforms.Resize((224, 224)),
        transforms.ToTensor(),  # Converte a imagem para tensor
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # Normaliza os valores dos pixels
    ])

    # Carregar o conjunto de dados
    dataset = datasets.ImageFolder(root=data_dir, transform=transform)

    # Dividir o conjunto de dados em treinamento e validação
    train_size = int(0.8 * len(dataset))
    val_size = len(dataset) - train_size
    train_dataset, val_dataset = random_split(dataset, [train_size, val_size])

    # Criar DataLoader para treinamento e validação
    batch_size = 32
    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=True)
    print("Train Loader: "+str(type(train_loader)))
    return train_loader, val_loader

def evaluate_model(val_loader, model):
    with torch.no_grad():
        model.eval()

        for inputs, labels in val_loader:
            outputs = model(inputs)
            _, predicted = torch.max(outputs, 1)  # Supondo classificação binária
            total += labels.size(0)
            correct += (predicted == labels).sum().item()

    accuracy = correct / total
    print(f'Acurácia no conjunto de validação: {100 * accuracy:.2f}%')

def select_model(name):
    # ShuffleNet
    if name == 'ShuffleNet':
        model_ft = models.shufflenet_v2_x1_0(pretrained=True)
        # Congele todos os parâmetros do modelo (ou deixe-os descongelados, dependendo de sua escolha)
        for param in model_ft.parameters():
            param.requires_grad = True  # Defina como False para congelar
        num_ftrs = model_ft.fc.in_features
        model_ft.fc = nn.Linear(num_ftrs, 2)
        input_size = 224
        return model_ft

    elif name == 'AlexNet':
        ###AlexNet###
        feature_extract = True
        model_ft = models.alexnet(pretrained=True)
        set_parameter_requires_grad(model_ft, feature_extract)
        num_ftrs = model_ft.classifier[6].in_features
        model_ft.classifier[6] = nn.Linear(num_ftrs, 4)
        input_size = 224
        return model_ft

    elif name == 'Resnet18':
        ###Resnet18###
        feature_extract = True
        model_ft = models.resnet18(pretrained=True)
        set_parameter_requires_grad(model_ft, feature_extract)
        num_ftrs = model_ft.fc.in_features
        model_ft.fc = nn.Linear(num_ftrs, 4)
        input_size = 224

    elif name == 'SqueezeNet':
        ###SqueezeNet###
        model_ft = models.squeezenet1_0(pretrained=True)
        set_parameter_requires_grad(model_ft, True)
        model_ft.classifier[1] = nn.Conv2d(512, 4, kernel_size=(1,1), stride=(1,1))
        model_ft.num_classes = 4
        input_size = 224
        return model_ft

    elif name == 'VGG11_b':
        ###VGG11_b###
        use_pretrained = True
        feature_extract = True
        model_ft = models.vgg11_bn(pretrained=use_pretrained)
        set_parameter_requires_grad(model_ft, feature_extract)
        num_ftrs = model_ft.classifier[6].in_features
        model_ft.classifier[6] = nn.Linear(num_ftrs, 4)
        input_size = 224
        return model_ft

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Distbelief training example')

    parser.add_argument('--ip', type=str, default='127.0.0.1')
    parser.add_argument('--port', type=str, default='3002')
    parser.add_argument('--world_size', type=int)
    args = parser.parse_args()

    #model = MLP(784, 10)
    model = select_model('ShuffleNet')

    handler = AsyncServerHandler(model, global_round=5)
    handler.setup_optim(0.5)

    network = DistNetwork(address=(args.ip, args.port),
                          world_size=args.world_size,
                          rank=0)
    Manager = AsynchronousServerManager(handler=handler, network=network)

    Manager.run()

    train_loader, val_loader = load_dataset()
    evaluate_model(val_loader, model)


import pygame

from resources import constants

"""
Keeps the value of each color/sprite for the current theme
"""

pygame.init()

class sprite(pygame.sprite.Sprite):
	"""
	Keeps the sprite image and its size
	"""
	def __init__(self, path, scale = 1.0):
		"""
		:param path: Name of the archive in the computer
		:param scale: Diminishes the image
		"""
		self.img = pygame.image.load('resources/sprites/' + path)
		self.rec = self.img.get_rect()
		self.img = pygame.transform.scale(self.img, (int(self.rec.width * scale), int(self.rec.height * scale)))

#Basic Theme
backgroundColor = (245, 245, 255)

#button
offButtonSprite = sprite('Basic/grey_off_button.png')
offButtonSpriteMini = sprite('Basic/small_grey_off_button.png')
offButtonColor = None
offButtonTextColor = constants.DARK_GREEN
onButtonSprite = sprite('Basic/black_on_button.png')
onButtonSpriteMini = sprite('Basic/small_black_on_button.png')
onButtonColor = None
onButtonTextColor = constants.MED_GREEN
onButtonActualStage = constants.BLUE
offButtonActualStage = (120, 120, 255)

#label
labelBackColor = backgroundColor
labelTextColor = constants.BLACK
labelTextLowColor = constants.GRAY
labelTextLLColor = (220, 220, 220) #Super low
titleBackColor = (240, 240, 255)

#Slider Bar
sliderPointerSpriteOff = offButtonSpriteMini
sliderPointerSpriteOn = onButtonSpriteMini
sliderBackColor = constants.BLACK
sliderPointerColorOn = constants.BLACK
sliderPointerColorOff = constants.BLACK

#engine
text_color = constants.BLACK
conqColor = constants.GREEN
procColor = constants.LIGHT_GREEN
freeColor = constants.WHITE
ballColor = constants.BLUE
heroColor = constants.RED

#icons
sound_on = sprite('sound_on.png')
sound_off = sprite('sound_off.png')

#sounds
menu_song = 'resources/sounds/menu.mid'
game_song = 'resources/sounds/game.mid'
rank_song = 'resources/sounds/rank.mid'
lose_song = 'resources/sounds/lose.mid'
win_song = 'resources/sounds/win.mid'
conquering_song = 'resources/sounds/conquering.wav'
conquered_song = 'resources/sounds/conquered.wav'


'''
函数说明:
Author: hongqing
Date: 2021-07-15 10:58:38
LastEditTime: 2021-07-23 16:22:37
'''
import numpy as np
from torch.nn.functional import one_hot

class Util:
    def __init__(self,nRow=5,nCol=6,colorSize=6):
        self.rowSize = nRow
        self.colSize = nCol
        self.colorSize=colorSize
        self.limit=3
    #重复版面优化
    def boardTrans(self,s):
        record = []
        pos= []
        for i in s:
            if(not i in record):
                record.append(i)
                pos.append(np.where(s==i))
                if(len(record)==self.colorSize):
                    break
        index = 0
        res = np.zeros(s.shape[0])
        for i in pos:
            index+=1
            for j in i:
                res[j]=index
        return res

    def getLimit(self,targetPos):
        res = []
        x,y = targetPos
        size = (self.colSize-1)*self.rowSize
        if(y<self.colSize-1):
            res.append(x*(self.colSize-1)+y)
        if(y>0):
            res.append(x*(self.colSize-1)+y-1)
        if(x<self.rowSize-1):
            res.append(size + x*self.colSize + y)
        if(x>0):
            res.append(size + (x-1)*self.colSize + y)
        return res
    #3x3
    def getLimitTiny(self,targetPos):
        res = []
        x,y = targetPos
        size = (self.colSize-1)*self.rowSize
        if(y<self.colSize-1):
            res.append(x*(self.colSize-1)+y)
        if(y>0):
            res.append(x*(self.colSize-1)+y-1)
        if(x<self.rowSize-1):
            res.append(size + x*self.colSize + y)
        if(x>0):
            res.append(size + (x-1)*self.colSize + y)
        return res

    def onehot(self,data,colorsize=6):
        res = np.array([])
        for i in data:
            tmp=np.zeros(colorsize)
            tmp[int(i-1)]=1
            res=np.concatenate((res,tmp),0)
        return res

    #重复版面优化2d 去除无用combo
    def boardTrans2d(self,s,prune=False):
        record = []
        pos= []
        for k in s:
            for i in k:
                if(not i in record):
                    record.append(i)
                    pos.append(np.where(s==i))
                    if(len(record)==self.colorSize):
                        break
        index = 0
        res = np.zeros(s.shape)
        pruned = 0
        for i in pos:
            if(prune):
                if(len(i[0])<self.limit):
                    pruned +=1
                    continue
            index+=1
            for j in range(i[0].shape[0]):
                x=i[0][j]
                y=i[1][j]
                res[x][y]=index
        return res,pruned

    # 补0
    def padding(self,s):
        row,col = s.shape
        pad = np.zeros((col-row,col))
        return np.vstack((s,pad))

    def one_hot2d(self,s):
        pos = {}
        res = np.zeros((self.colorSize,s.shape[0],s.shape[1]))
        for i in range(1,self.colorSize+1):
            pos = np.where(s==i)
            for j in range(len(pos[0])):
                x=pos[0][j]
                y=pos[1][j]
                res[i-1][x][y]=1
        return res

    # 自动优化器
    def autoOptim(self,s):
        if(self.rowSize>self.colSize):
            return
        s,pruned = self.boardTrans2d(s,True)
        # self.colorSize-=pruned
        if(self.rowSize<self.colSize):
            s = self.padding(s)

        transS = self.one_hot2d(s)
        return transS,self.colorSize


from objParser import objParser
from boundingbox import *

__all__ = ['polyShape']

class polyShape:
	def __init__(self, name, vertices, faces):
		self.name = name
		self.vertices = vertices
		self.edges = []
		self.faces = faces
		self.colors = []
		self.obj2World = Matrix()
		self.bboxObj = BoundingBox()
		self.bboxWorld = BoundingBox()
		self.calcBboxObj()
		self.normals = None

	def calcBboxObj(self):
		for vertex in self.vertices:
			self.bboxObj.expand(vertex)

	@staticmethod
	def parseObjFile(name, file):
		objects = []
		elem = objParser(file)
		for obj in elem.objects:
			vertices = []
			for v in obj[0]:
				vertices.append(Point3f(v[0], v[1], v[2]))
			object = polyShape(obj[2], vertices, obj[1])
			objects.append(object)
		return objects


import math
def prime(x):
    for i in range(2, int(math.sqrt(x)+2)):
        if (x % i) == 0:
            return False
    return True

n = int(input())
p = 0
i = 1
end = False

while not end:
    #print(i)
    if prime(i):
        p += 1
        #print("prime #{}".format(p))
    if (p == n):
        print(str(i))
        end = True
    i += 1


from django.shortcuts import render, redirect, get_object_or_404
from main.models import User
from main.forms import CustomUserForm
from django.contrib.auth.models import Group
from django.contrib import messages
from django.contrib.auth.decorators import login_required

@login_required
def user_lists(request):
    group = request.user.groups.all()[0].name
    users = User.objects.all().exclude(groups__name='client')
    # usergroup = request.user.groups.all()[0].name
    context = {
        'users': users,'group': group, 'title': 'Users List',
    }
    return render(request, 'employee/users_list.html', context)

@login_required
def user_add(request):
    group = request.user.groups.all()[0].name
    form = CustomUserForm()
    if request.method == 'POST':
        form = CustomUserForm(request.POST)
        if form.is_valid():
            instance = form.save(commit=False)
            gp = request.POST.get('groups')
            group = Group.objects.get(id=gp)
            instance.set_password('edtl#2022')
            instance.save()
            instance.groups.add(group)
            messages.success(
                request, f'User {instance.email} Successfully Created')
            return redirect('admin-user-lists')
    context = {
        'form': form,'group': group, 'title': 'Add User',
    }
    return render(request, 'employee/add.html', context)

@login_required
def user_update(request, hashid):
    group = request.user.groups.all()[0].name
    object = get_object_or_404(User, hashed=hashid)
    if request.method == 'POST':
        form = CustomUserForm(request.POST, instance=object)
        if form.is_valid():
            instance = form.save(commit=False)
            instance.groups.clear()
            gp = request.POST.get('groups')
            group = Group.objects.get(id=gp)
            instance.groups.add(group)
            instance.save()
            messages.success(
                request, f'User {instance.email} Successfully Update')
            return redirect('admin-user-lists')
    else:
        form = CustomUserForm(instance=object)
    context = {
        'form': form,'group': group, 'title': 'Update User',
    }
    return render(request, 'employee/add.html', context)

@login_required
def user_activate(request, hashid):
    object = get_object_or_404(User, hashed=hashid)
    object.is_active = True
    object.save()
    messages.success(request, f'User {object.email} Successfully Activate')
    return redirect('admin-user-lists')

@login_required
def user_deactivate(request, hashid):
    object = get_object_or_404(User, hashed=hashid)
    object.is_active = False
    object.save()
    messages.warning(request, f'User {object.email} Successfully Deactivate')
    context = {}
    return redirect('admin-user-lists')


from functools import wraps
from contextlib import contextmanager
import sys
import logging

import rq
import rq.job
from rq.utils import ColorizingStreamHandler
from rq.contrib.sentry import register_sentry

from cubicweb.cwconfig import CubicWebConfiguration

from cubicweb_francearchives import admincnx as orig_admincnx, init_bfss

@contextmanager
def admincnx(appid_or_cnx, loglevel=None):
    if isinstance(appid_or_cnx, str):
        with orig_admincnx(appid_or_cnx, loglevel) as cnx:
            yield cnx
    else:
        assert (
            appid_or_cnx.vreg.config.mode == "test"
        ), "expected to be a connection only in test mode"
        yield appid_or_cnx

def rqjob(task):
    @wraps(task)
    def task_wrapper(appid, *args, **kwargs):
        job = rq.get_current_job()
        with admincnx(appid, loglevel="warning") as cnx:
            init_bfss(cnx.repo)
            rqtask = cnx.find("RqTask", eid=int(job.id)).one()
            irqjob = rqtask.cw_adapt_to("IRqJob")
            try:
                result = task(cnx, *args, **kwargs)
            except Exception:
                logging.getLogger("rq.task").exception("An error has occurred.")
                cnx.rollback()
                irqjob.handle_failure(*sys.exc_info())
                cnx.commit()
                raise
            else:
                irqjob.handle_finished()
                cnx.commit()
        return result

    return task_wrapper

class RedisHandler(logging.Handler):
    def emit(self, record):
        job = rq.get_current_job()
        if job is not None:
            key = "rq:job:{0}:log".format(job.id)
            pipe = job.connection.pipeline()
            msg = self.format(record)
            if isinstance(msg, str):
                msg = msg.encode("utf-8")
            pipe.append(key, msg)
            # keep RQ logs 24h in case of non-default timeout
            pipe.expire(key, 86400)
            pipe.execute()

def update_progress(job, progress_value):
    job.meta["progress"] = progress_value
    job.save_meta()
    return progress_value

def config_from_appid(appid_or_cnx):
    if isinstance(appid_or_cnx, str):
        return CubicWebConfiguration.config_for(appid_or_cnx)
    assert appid_or_cnx.vreg.config.mode == "test", "expected to be a connection only in test mode"
    return appid_or_cnx.vreg.config

def work(appid, burst=False, worker_class=rq.Worker):
    logger = logging.getLogger("rq.worker")
    if not logger.handlers:
        logger.setLevel(logging.INFO)
        formatter = logging.Formatter(fmt="%(asctime)s %(message)s", datefmt="%H:%M:%S")
        handler = ColorizingStreamHandler()
        handler.setFormatter(formatter)
        logger.addHandler(handler)
    task_logger = logging.getLogger("rq.task")
    task_logger.setLevel(logging.DEBUG)
    handler = RedisHandler()
    handler.setFormatter(
        logging.Formatter(fmt="%(levelname)s %(asctime)s %(module)s %(process)d %(message)s\n")
    )
    task_logger.addHandler(handler)

    class Job(rq.job.Job):
        @property
        def args(self):
            return (appid,) + super(Job, self).args

    cwconfig = config_from_appid(appid)
    worker = worker_class("default", job_class=Job)
    sentry_dsn = cwconfig.get("sentry-dsn")
    if sentry_dsn:
        register_sentry(sentry_dsn)
    worker.work(burst=burst)


import spacy
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

# Load the spaCy model
nlp = spacy.load("de_core_news_sm")

# Read the CSV file
df = pd.read_csv("C:/Users/ASUS/OneDrive/Desktop/articleInfo/image_data.csv", encoding="utf8")

# Perform named entity recognition on the "image_titels" column
entities = []
for text in df["image_titels"].astype(str):
    doc = nlp(text)
    for ent in doc.ents:
        entities.append(ent.text)

# Get the top 10 entities
top_entities = pd.Series(entities).value_counts().nlargest(10)

# Create a bar chart of the top 10 entities
fig, ax = plt.subplots()
ax.bar(top_entities.index, top_entities.values)
ax.set_xlabel("Entities")
ax.set_ylabel("Frequency")
ax.set_title("Top 10 Entities in Image Titles")

# Rotate the x-axis labels
plt.xticks(rotation=45, ha="right")

# Adjust the y-axis to show only whole numbers
ax.yaxis.set_major_locator(ticker.MaxNLocator(integer=True))

# Save the chart as a PNG file
plt.savefig("C:/Users/ASUS/OneDrive/Desktop/articleInfo/entity_chart.png", bbox_inches="tight")


import numpy as np
from django.db.models import Count
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
from rrhh.models import MonedaLink, EntregaMoneda, CanjeMonedas
from users.serializers import linkcoins_serializers

class LinkcoinsViewset(viewsets.GenericViewSet):
    queryset = MonedaLink.objects.all()
    permission_classes = (AllowAny,)

    @action(detail=True, methods=["GET"])
    def reporte(self, request, pk=None):
        quey_canje = CanjeMonedas.objects.filter(usuario__identificacion=pk)
        monedas_generadas = MonedaLink.objects.filter(usuario_portador__identificacion=pk).count()
        monedas_recibidas = EntregaMoneda.objects.filter(usuario_recibe__identificacion=pk).count()
        monedas_canjeadas = sum(np.array(quey_canje.values_list('monedas', flat=True)))
        canjes_pendientes = quey_canje.filter(entregado='NO').count()
        ultimo_canje = quey_canje.order_by('-fecha').first()
        ultimo_canje = ultimo_canje.premio if ultimo_canje else ""

        response = {
            'monedas_generadas' : monedas_generadas,
            'monedas_recibidas' : monedas_recibidas,
            'monedas_canjeadas' : monedas_canjeadas,
            'canjes_pendientes' : canjes_pendientes,
            'ultimo_canje' : ultimo_canje,
        }

        return Response(response, status=status.HTTP_200_OK)

    @action(detail=True, methods=["GET"])
    def reporte_entrega(self, request, pk=None):
        quey_canje = EntregaMoneda.objects.filter(moneda__usuario_portador__identificacion=pk).annotate(cantidad=Count('mensaje')).order_by('-fecha')
        serializer = linkcoins_serializers.EntregasSerializer(quey_canje, many=True)
        response = {'entrega':serializer.data}
        return Response(response, status=status.HTTP_200_OK)


# -*- coding: utf-8 -*-
"""
Created on Sun Aug 28 18:05:18 2022

@author: timve
"""

import numpy as np
from datetime import datetime
import pathlib
import matplotlib.pyplot as plt

def load(filename):
        data = np.load(str(pathlib.Path().resolve()) + '/data/' + str(filename) + '.npz')
        return data

n = 7
data_kin = []
data_tel = []

for i in range(1,n+1):
    try:
        data_kin.append(load(f"dual_{i}_kin_dem"))
    except:
        data_kin.append(0)

    try:
        data_tel.append(load(f"dual_{i}_tel_dem"))
    except:
        data_tel.append(0)

plt.figure(0)
print('d')
for i ,d in enumerate(data_kin):
    plt.plot(d['recorded_traj_dual'][0], label=i)
    print(len(d['recorded_traj_dual'][0]))
plt.legend()

plt.figure(1)
print('t')
for i, t in enumerate(data_tel):
    if t != 0:
        plt.plot(t['recorded_traj_dual'][0], label=i)
        print(len(t['recorded_traj_dual'][0]))
    else:
        print(0)
        pass
plt.legend()

#%%
import scipy.stats as st
a=[965, 1795, 1180, 1205]#1795, 1180 , 1205]
b=[8028,4730, 5294, 9430] #my idea is to put 10000 for the example that failed
(stat, p) = st.ttest_rel(a,b)

#%%
import scipy.stats as st
a=[1116, 965, 1188, 827, 1795, 1180, 1205]#1795, 1180 , 1205]
b=[1.5*9430, 8028, 1.5*9430, 1.5*9430, 4730, 5294, 9430] #my idea is to put 10000 for the example that failed
(stat, p) = st.ttest_rel(a,b)

#%%

import plotly.graph_objects as go

categories = ['Mental Demand', 'Physical Demand', 'Temporal Demand', 'Effort', 'Frustration']

fig = go.Figure()

fig.add_trace(go.Scatterpolar(
      r=[3.57, 9, 6.86, 4.29, 2.86],
      theta=categories,
      fill='toself',
      name='Kinesthetic Teaching'
))
fig.add_trace(go.Scatterpolar(
      r=[16.43, 3.86, 10.57, 16.57, 11.71],
      theta=categories,
      fill='toself',
      name='Teleoperated Teaching'
))

fig.update_layout(
  polar=dict(
    radialaxis=dict(
      visible=True,
      range=[0, 20]
    )),
  showlegend=False
)

fig.show()
# %%


from django.conf import settings
from utils import restful
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
import os

@csrf_exempt  # 防止post时引发403错误
def upload_view(request):
    if request.method == 'POST':
        f = request.FILES.get('file')
        name = f.name
        path = os.path.join(settings.MEDIA_ROOT, name)

        with open(path, 'wb') as fp:
            for chunk in f.chunks():
                fp.write(chunk)
        return JsonResponse({
            'location': settings.MEDIA_URL + name
        })
    else:
        return restful.methoderror('请求方式错误！')


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

from collections import Counter

class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        if len(s1) > len(s2):
            return False
        s1_counter = Counter(s1)
        s2_counter = Counter(s2[:len(s1)])
        if s1_counter == s2_counter:
            return True
        for i in range(len(s2) - len(s1)):
            s2_counter[s2[i]] -= 1
            if s2_counter[s2[i]] == 0:
                del s2_counter[s2[i]]
            s2_counter[s2[i + len(s1)]] += 1
            if s1_counter == s2_counter:
                return True
        return False

def test_checkInclusion():
    s = Solution()
    assert s.checkInclusion("ab", "eidbaooo") == True
    assert s.checkInclusion("ab", "eidboaoo") == False
    assert s.checkInclusion("adc", "dcda") == True
    assert s.checkInclusion("abcd", "abcdabcdabcdabcdabcdabcdabcdabc") == True
    assert s.checkInclusion("hello", "ooolleoooleh") == False
    print("========================== Test Passed ==========================")

if __name__ == '__main__':
    test_checkInclusion()


import logging
import unittest

import ddt

from co2mpas import tkui, __main__ as cmain
import os.path as osp
import tkinter as tk

cmain.init_logging(level=logging.WARNING)

log = logging.getLogger(__name__)

mydir = osp.dirname(__file__)

@ddt.ddt
class Test(unittest.TestCase):

    @ddt.data(
        ("", ()),
        ("""Some clean text.""", ()),
        ("""A [broken] (link) cause of spaces.""", ()),
        ("""A [img:broken] (image) cause of spaces.""", ()),

        ("""[  img:  test  ](  s p a c e s  ).""",
         (
             ('img:', 'test', 's p a c e s'),
         )
         ),

        ("""[ some &^& sdragbge ](  a &(& DDJ&*( bad url ).""",
         (
             (None, 'some &^& sdragbge', 'a &(& DDJ&*( bad url'),
         )
         ),

        ("""[Einstein](https://en.wikipedia.org/wiki/Einstein) on the [img:beach](images/keratokampos.png).""",
         (
             (None, 'Einstein', 'https://en.wikipedia.org/wiki/Einstein'),
             ('img:', 'beach', 'images/keratokampos.png'),
         )
         ),

        ("""Hi [wdg:foo](bar) there [img:abc](def) and [mplah](blah).""",
         (
             ('wdg:', 'foo', 'bar'),
             ('img:', 'abc', 'def'),
             (None, 'mplah', 'blah'),
         )
         ),

        ("""] (Hi [ wdg: foo] there [img: abc ] and [ mplah ].""",
         (
             ('wdg:', 'foo', None),
             ('img:', 'abc', None),
             (None, 'mplah', None),
         )
         ),

        ("[foo] (bar)", ((None, 'foo', None), )),
        ("[wdg:foo] (bar)", (('wdg:', 'foo', None), )),
        ("[foo](bar\ntender)", ((None, 'foo', None), )),
        ("[img:foo](bar\ntender)", (('img:', 'foo', None), )),

)
    def test_makdown_parsing_regex(self, case):
        txt, exp_groups_seq = case
        exp_nmatches = len(exp_groups_seq)
        regex = tkui._img_in_txt_regex

        nmatches = 0
        for nmatches, (m, exp_groups) in enumerate(zip(regex.finditer(txt), exp_groups_seq), 1):
            self.assertEqual(m.groups(), exp_groups)

        self.assertEqual(nmatches, exp_nmatches)

    @ddt.data(
        'asd [ foo f',
        'asd ( foo f',
        'asd ( foo )f',
        'asd  foo )f',
        'asd  foo ]f',
        ' [bar)sf',
        ' (bar)sf',
        ' [img:bar)sf',
        ' [wdg:bar)sf',

        'NL? [wdg:foo \n bar] 1',

        '\\[wdg:escaped] 1',
        '\\[wdg:escaped](url) 2',
    )
    def test_makdown_parsing_regex_bad(self, txt):
        regex = tkui._img_in_txt_regex

        self.assertIsNone(regex.search(txt))

#    def test_smoketest(self):
#        root = tk.Tk()
#        try:
#            app = tkui.TkUI(root)
#            root.after_idle(app._do_about)
#            root.after(3000, root.quit)
#            app.mainloop()
#        finally:
#            try:
#                root.destroy()
#            except tk.TclError:
#                pass

    def test_about(self):
        root = tk.Tk()
        try:
            tkui.show_about(root, verbose=True)
            root.after(700, root.quit)
            root.mainloop()
        finally:
            try:
                root.destroy()
            except tk.TclError:
                pass


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
qcorr simple

Based on Claude's suggestion, recalculate the
stochastic forcing amplitude based on a simpler approach using
T', Qnet, and Lambda'

For Qnet
- Removes mean
- Removes seasonal cycle

Created on Thu Feb 10 08:43:38 2022

@author: gliu
"""

import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import sys
import cmocean
from tqdm import tqdm
import xarray as xr

#%% Set Paths, Import Custom Modules
stormtrack = 0

if stormtrack == 0:
    projpath   = "/Users/gliu/Downloads/02_Research/01_Projects/01_AMV/02_stochmod/"
    datpath     = projpath + '01_Data/model_output/'
    rawpath     = projpath + '01_Data/model_input/'
    outpathdat  = datpath + '/proc/'
    figpath     = projpath + "02_Figures/20220519/"

    sys.path.append("/Users/gliu/Downloads/02_Research/01_Projects/01_AMV/02_stochmod/03_Scripts/stochmod/model/")
    sys.path.append("/Users/gliu/Downloads/02_Research/01_Projects/01_AMV/00_Commons/03_Scripts/")

elif stormtrack == 1:
    datpath     = "/stormtrack/data3/glliu/01_Data/02_AMV_Project/02_stochmod/Model_Data/model_output/"
    rawpath     = "/stormtrack/data3/glliu/01_Data/02_AMV_Project/02_stochmod/Model_Data/model_input/"
    outpathdat  = datpath + '/proc/'

    sys.path.append("/home/glliu/00_Scripts/01_Projects/00_Commons/")
    sys.path.append("/home/glliu/00_Scripts/01_Projects/01_AMV/02_stochmod/stochmod/model/")

from amv import proc,viz
import scm
import tbx

proc.makedir(figpath)
#%% Used Edits

lonf       = -30
latf       = 50

mconfig    = "FULL"
frcname    = "flxeof_090pct_FULL-PIC_eofcorr2"
input_path = rawpath

debug   = True
netcdf  = True # Load netCDFs saved from Investigate_Forcing.ipynb. False only supports FULL
"""
#%% Next Few Sections, Load in the Data...
"""

flip360=True # change longitude back to degrees east for final output

# Lag in T for damping term
# 0   = lbd*T(t)
# 1   = lbd*T(t-1)
# 0.5 = lbd*[T(t-1)+T(t)]/2
rolln    = 0
mconfigs = ("SLAB","FULL")

for mconfig in mconfigs:
    #%% Load in the Temperature Anomalies
    # [lon x lat x time]

    # Load in from dataset
    ds      = xr.open_dataset(datpath+"../CESM_proc/TS_anom_PIC_%s.nc" % (mconfig))
    T        = ds.TS.values
    lon360   = ds.lon.values
    ds.close()

    # Transpose dimensions
    T        = T.transpose(2,1,0) # [time x lat x lon] --> [lon x lat x time]
    lon180,T = proc.lon360to180(lon360,T)

    # Get dimension lengths
    nlon,nlat,ntime = T.shape
    nyrs            = int(ntime/12)

    #%% Load in Qnet

    # Load in from NumPY (Need to update this)
    if netcdf:
        ds = xr.open_dataset(datpath+"../CESM_proc/NHFLX_PIC_%s.nc" % mconfig)
        Q = ds.NHFLX.values
    else:
        Q   = np.load(datpath+"../NHFLX_PIC_Full.npy") # [year x month x lat x lon]
    Q   = Q.reshape(ntime,nlat,nlon) # [time x lat x lon]
    Q   = Q.transpose(2,1,0) # [lon x lat x time]

    # Flip to lon 180
    _,Q = proc.lon360to180(lon360,Q)

    # Remove Time Mean
    Q   = Q - Q.mean(2)[:,:,None]

    # Remove Scycle
    Qseas,Q = proc.calc_clim(Q,2,returnts=1)
    Q       = Q - Qseas[:,:,None,:]
    Q = Q.reshape(nlon,nlat,ntime)

    #%% Use the function used for sm_rewrite.py, load in lambda
    # [lon x lat x month]
    inputs = scm.load_inputs('SLAB_PIC',frcname,input_path,load_both=True)
    lon,lat,h,kprevall,dampingslab,dampingfull,alpha,alpha_full = inputs
    if mconfig == 'SLAB':
        lbd = dampingslab
    elif mconfig == 'FULL':
        lbd = dampingfull

    # Tile Lambda
    lbd = np.tile(lbd,nyrs)

    # ($$) Run up to here to visualize different lags evlow
    #%% Compute Stochastic Forcing
    """
    Qnet = -lambda*T + F'

    F' = Qnet + lambda*T

    """
    # Test the phase
    fig,ax =plt.subplots(1,1)
    test = np.arange(0,12,1)
    ax.plot(test,label='normal',color='k')
    ax.plot(np.roll(test,-1),label="-1",color='b')
    ax.plot(np.roll(test,1),label="1",color='r')
    ax.legend()
    ax.grid(True)
    ax.set_xlim([0,3])

    # Uh oh what lag of lambda to use? (Jump below to $$)

    if rolln == 0.5: # ([T(t) + T(t-1)]/2)
        dampterm = (np.roll(T,1,axis=2)+T)/2 * lbd
    else:
        dampterm = np.roll(T,rolln,axis=2) * lbd
    Fprime = Q + dampterm

    # Plot some test plots
    if debug:
        plt.pcolormesh(Fprime[...,0].T,vmin=-400,vmax=400),plt.colorbar()
        plt.show()
        plt.pcolormesh(Q[...,0].T,vmin=-400,vmax=400),plt.colorbar()
        plt.show()
        plt.pcolormesh(dampterm[...,0].T,vmin=-50,vmax=50),plt.colorbar()
        plt.show()

    #%% Do some Exploratory Analysis
    normspec = False
    labels    = ("$Q_{net}$","F'","$\lambda T$","-$\lambda T$ + F'")
    klon,klat = proc.find_latlon(lonf,latf,lon180,lat)
    locstring = "Lon %.f, Lat %.f" % (lon180[klon],lat[klat])
    ecolors   = ("mediumblue","firebrick","magenta","cyan")

    # 1) Compute the power spectra
    nsmooth = 100
    pct     = 0.00
    dtplot  = 3600*24*365
    xtks    = [1/100,1/50,1/20,1/10,1/2,1/1]
    xper    = [int(1/x) for x in xtks]
    xlm     = [xtks[0],xtks[-1]]

    inflx     = [Q[klon,klat,:],Fprime[klon,klat,:],dampterm[klon,klat,:],Fprime[klon,klat,:]-dampterm[klon,klat,:]]
    specs,freqs,CCs,dofs,r1s = scm.quick_spectrum(inflx,nsmooth,pct)
    if normspec:
        ylm = [0,3]
        specs = [specs[i]/np.var(inflx[i]) for i in range(len(inflx))]
    else:
        ylm = [0,1000]

    fig,ax = plt.subplots(1,1,figsize=(8,3))
    for i in range(len(inflx)-1):
        if i == (len(inflx)-1):
            ls = 'dashed'
        else:
            ls = 'solid'
        ax.plot(freqs[i]*dtplot,specs[i]/dtplot,label=labels[i],lw=3,ls=ls,color=ecolors[i])

    plotspec = specs[1] + specs[2]
    #ax.plot(freqs[i]*dtplot,plotspec/dtplot,label=labels[i] + "(Add Spectra)",lw=3,ls=ls)
    ax.legend()
    ax.set_xticks(xtks)
    ax.set_xticklabels(xper,rotation=45)
    ax.set_xlim(xlm)
    ax.set_ylim(ylm)
    ax.set_title("Power Spectra @ %s  \n CESM1-%s" % (locstring,mconfig) )
    ax.set_xlabel("Period (Years)")
    ax.set_ylabel("Power ($W/m^{2}/cpy$)")
    ax.grid(True,ls='dotted')
    plt.savefig("%sQnet_Power_Spectra_CESM1-%s.png"% (figpath,mconfig),dpi=150)

    #%% Save the updated forcing for the EOF Analysis

    """
    Fprime is [lon x lat x time]

    """
    # Flip back to lon 360
    if flip360:
        lon360,Fprime = proc.lon180to360(lon180,Fprime)
        lonsave = lon360
    else:
        lonsave = lon180

    #
    Fprime = proc.flipdims(Fprime) #  Flip to [time x lat x lon]
    times   = xr.cftime_range(start="0400-01-01",periods=Fprime.shape[0],freq="MS")

    # Save as a netCDF
    savename = "%s../Fprime_PIC_%s_rolln%s.nc" % (datpath,mconfig,str(rolln))
    proc.numpy_to_da(Fprime,times,lat,lonsave,'Fprime',savenetcdf=savename)

# ---------------------------------------------------------------------------
#%% Test different lags. Run up to the symbol ($$) above (loaded in all data)
# ---------------------------------------------------------------------------

rollns = (0,0.5,1) #
labels = ("T(t)","T(t-1/2)","T(t-1)")

dampterms = []
Fprimes   = []

for n in tqdm(range(len(rollns))):
    rolln = rollns[n]

    if rolln == 0.5: # ([T(t) + T(t-1)]/2)
        dampterm = (np.roll(T,1,axis=2)+T)/2 * lbd
    else:
        dampterm = np.roll(T,rolln,axis=2) * lbd
    Fprime = Q + dampterm

    Fprimes.append(Fprime)
    dampterms.append(dampterm)

#%% Make spectra for each one

klon,klat = proc.find_latlon(lonf,latf,lon180,lat)
locstring = "Lon %.f, Lat %.f" % (lon180[klon],lat[klat])
ecolors   = ("magenta","orange","cornflowerblue")
vnames    = ("F'","Damping_Term")
invars    = [Fprimes,dampterms]

# 1) Compute the power spectra
nsmooth = 100
pct     = 0.10
dtplot  = 3600*24*365
xtks    = [1/100,1/50,1/20,1/10,1/2,1/1]
xper    = [int(1/x) for x in xtks]
xlm     = [xtks[0],xtks[-1]]

for v in range(2):
    invar = invars[v]
    inflx     = [f[klon,klat,:] for f in invar]
    nsmooths  = nsmooth*np.ones(len(inflx))
    specs,freqs,CCs,dofs,r1s = scm.quick_spectrum(inflx,nsmooths,pct)

    if v ==0:
        ylm = [175,600]
    else:
        ylm = [50,775]

    fig,ax = plt.subplots(1,1,figsize=(8,3))
    for i in range(len(inflx)):
        if i == (len(inflx)):
            ls = 'dashed'
        else:
            ls = 'solid'
        ax.plot(freqs[i]*dtplot,specs[i]/dtplot,label=labels[i],lw=3,ls=ls,color=ecolors[i])

    plotspec = specs[1] + specs[2]
    #ax.plot(freqs[i]*dtplot,plotspec/dtplot,label=labels[i] + "(Add Spectra)",lw=3,ls=ls)
    ax.legend()
    ax.set_xticks(xtks)
    ax.set_xticklabels(xper,rotation=45)
    ax.set_xlim(xlm)
    ax.set_ylim(ylm)
    ax.set_title("%s Power Spectra @ %s  \n CESM1-%s" % (vnames[v],locstring,mconfig) )
    ax.set_xlabel("Period (Years)")
    ax.set_ylabel("Power ($W/m^{2}/cpy$)")
    ax.grid(True,ls='dotted')
    plt.savefig("%s%s_Power_Spectra_CESM1-%s.png"% (figpath,vnames[v],mconfig),dpi=150)


from urllib.request import urlopen
from bs4 import BeautifulSoup
import json
import datetime
import pprint
import sys
pp = pprint.PrettyPrinter(indent=4)

def main(): # Main function
	current_year = int(datetime.datetime.now().year)
	for year in range(1898, current_year+1):
		sys.stdout = open('DataSets//IMDB_Top_50_' + str(year) + '.json', 'w')
		url = "http://www.imdb.com/search/title?release_date=" + str(year) + "," + str(year) + "&title_type=feature"
		html = urlopen(url)
		soup = BeautifulSoup(html.read(), features="html.parser")
		dataset_top50 = {}
		id = 1
		movies_list = soup.findAll('div', attrs={'class': 'lister-item-content'})
		for each in movies_list:

			# Prototype of each movie item
			movie_item = {
				'name': '',
				'certificate': '',
				'runtime': '',
				'genre': '',
				'description': '',
				'director': '',
				'stars': []
				# 'votes': '',
				# 'gross': ''
			}

			if each.find('h3', attrs={'class': 'lister-item-header'}).find('a').text:
				name_value = each.find('h3', attrs={'class': 'lister-item-header'}).find('a').text.strip()
				movie_item['name'] = name_value

			p_list = each.findAll('p')

			if p_list[0]:
				if p_list[0].find('span', attrs={'class': 'certificate'}):
					certificate_value = p_list[0].find('span', attrs={'class': 'certificate'}).text.strip()
					movie_item['certificate'] = certificate_value

				if p_list[0].find('span', attrs={'class': 'runtime'}):
					runtime_value = p_list[0].find('span', attrs={'class': 'runtime'}).text.strip()
					movie_item['runtime'] = runtime_value

				if p_list[0].find('span', attrs={'class': 'genre'}):
					genre_value = p_list[0].find('span', attrs={'class': 'genre'}).text.strip()
					movie_item['genre'] = genre_value

			if p_list[1]:
				description_value = p_list[1].text.strip()
				movie_item['description'] = description_value

			# if p_list[2]:
			# 	director_value = p_list[2].findAll('a')[0].text.strip()
			# 	movie_item['director'] = director_value
			# 	stars_list = p_list[2].findAll('a')[1:]
			# 	stars_value = []
			# 	for each in stars_list:
			# 		stars_value += [each.text.strip()]

			# 	movie_item['stars'] = stars_value

			# if len(p_list) == 4:
			# 	votes_value = p_list[3].findAll('span', attrs={'name': 'nv'})[0].text.strip()
			# 	movie_item['votes'] = votes_value
			# 	gross_value = p_list[3].findAll('span', attrs={'name': 'nv'})[1].text.strip()
			# 	movie_item['gross'] = gross_value

			dataset_top50[id] = movie_item
			id += 1

		pp.pprint(dataset_top50)
		print(json.dumps(dataset_top50, indent=4))

	# End of the main function

main() # Call of the main function


# -*- coding: utf-8 -*-
"""
Created on Sat Oct  8 16:49:36 2022

@author: DELL
"""

#Deep learning_gradient decent techniques..

import pandas as pd
df=pd.read_csv("pima-indians-diabetes.csv",delimiter=",")

x=df.iloc[:,0:8]
y=df.iloc[:,8]
#pip install tensorflow
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential

# create model
import numpy as np
model = Sequential()
model.add(Dense(12, input_dim=8,  activation='relu'))
model.add(Dense(1, activation='sigmoid'))

# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fit the model
history = model.fit(x, y, validation_split=0.30, epochs=250, batch_size=100)

# evaluate the model
scores = model.evaluate(x, y)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
history.history.keys()
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()


#!/usr/bin/env python
# encoding: utf-8
"""
@author: HuRuiFeng
@file: 185_spacecraft.py
@time: 2023/8/27 1:29
@project: huawei-od-python
@desc: 185 航天器
"""

def solve_method(nums):
    result = 0
    for i in range(len(nums)):
        for j in range(i + 1, len(nums)):
            area = min(nums[i], nums[j]) * (j - i)
            result = max(result, area)

    return result

if __name__ == '__main__':
    assert solve_method([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]) == 25


"""
licenses_exporter: A prometheus client to export lsmon & lmutil licenses
Tonin 2018. University of Cordoba
"""

import traceback
import subprocess
from prometheus_client import Gauge, start_http_server, REGISTRY, PROCESS_COLLECTOR, PLATFORM_COLLECTOR, GC_COLLECTOR
from selenium import webdriver
from datetime import datetime
import time
import sys
import os
import re
import ruamel.yaml as yaml
import requests
import pandas as pd
import socket

#unregister default metrics
REGISTRY.unregister(PROCESS_COLLECTOR)
REGISTRY.unregister(PLATFORM_COLLECTOR)
REGISTRY.unregister(GC_COLLECTOR)

#Licenses & config file
CONFIG_FILE = 'config.yml'
WRITEHTML = False
DEBUG = False
TRACE = False
VERBOSE = False
SUMMARY = True
if DEBUG: VERBOSE = True

driver = None

def appendFeature(feature_list,feature):
	if feature.name == "NULL":
		return
	else:
		feature_list.append(feature)

def isWindows():
	ret = True if os.name == 'nt' else False
	return ret

def isDocker():
	path = '/proc/self/cgroup'
	return (
		os.path.exists('/.dockerenv') or
		os.path.isfile(path) and any('docker' in line for line in open(path))
	)

def isNan(num):
	return num != num

def value(row,label):
	if type(label) is int:
		return row[int(label)]
	else:
		return row[label]

def trace(label,msg):
	print("TRACE:",label," ",msg)

class User(object):
	def __init__(self, name):
		self.name = name
		self.hostName = None
		self.device = None
		self.date = None

	def printUser(self):
		print("\t",self.name," ",self.hostName," ",self.device," ",self.date)

	def printUserToError(self):
		print("\t",self.name," ",self.hostName," ",self.device," ",self.date, file=sys.stderr)

class Feature(object):
	def __init__(self, name, app, parent):
		self.name = name
		self.maxLicenses = 0
		self.inUse = 0
		self.app = app
		self.parent = parent
		self.userList = []

		#Vemos si tenemos translaciones de etiquetes de features
		try:
			dummy = parent.features['translate']
			self.translatable = True
		except:
			self.translatable = False
			return

		#Realizamos la traduccion del self.name
		if parent.features['translate']['at_stage'] == 1:
			self.translate()

	def translate(self):
			r = re.search(self.parent.features['translate']['search'],self.name)
			if r is not None:
				#Depuramos
				if DEBUG:
					print("DEBUG: Translating feature: ",self.name)
				self.name = self.parent.features['translate']['translations'][r.group('feature_name')] + " " + r.group('feature_suffix')
			else:
				#Si no encontramos traslacion debemos marcarla para borrar
				self.name = "NULL"

	def isUsing(self):
		if self.inUse > 0.0:
			return True
		else:
			return False

	def printFeature(self):
		if not VERBOSE:
			return
		print("app=",self.app," feature=",self.name," max=",self.maxLicenses," current=",self.inUse)
		for user in self.userList:
			user.printUser()

class App(object):
	def __init__(self, parent, argsDict):
		self.parent = parent
		for key,value in argsDict.items():
			setattr(self,key,value)
		#Hacemos lista los strings separados por comas
		try:
			self.features['include'] =  str(self.features['include']).split(",")
		except:
			pass
		try:
			self.users['url']['index'] = str(self.users['url']['index']).split(",")
		except:
			pass
		try:
			self.label['item'] = self.label['item'].split(",")
		except:
			pass

		self.featureList = []
		if(self.type == 'lsmon'):
			self.parse = self.parseLsmon
		elif(self.type == 'lmutil'):
			self.parse = self.parseLmutil
		elif(self.type == 'rlmutil'):
			self.parse = self.parseRlmutil
		elif(self.type == 'web'):
			self.parse = self.parseWeb
		elif(self.type == 'webtable'):
			self.parse = self.parseWebTable
		elif(self.type == 'webtablejs'):
			self.parse = self.parseWebTableJs
		elif(self.type == 'rawsocket'):
			self.parse = self.parseRawSocket
		self.online = False
		driver = None

	def df_parse_features(self,feature_tbl):
		has_features = False
		if DEBUG: print("DEBUG: features_to_include: ",self.features['include'])
		if not feature_tbl.empty:
			#Hemos encontrado cosas
			for index,row in feature_tbl.iterrows():
				if TRACE: trace(self.name,"En bucle iterrows de df_parse_features")
				if not isNan(row[self.features['label']['name']]):
					if TRACE: trace(self.name,"not isNan en  df_parse_features")
					#No siempre tiene que estar product definido, lo ponemos en un try
					try:
						if self.product['include'] is not None:
							if not str(self.product['include']) in str(row[self.product['label']]):
								continue
					except:
						pass
					if DEBUG: print("DEBUG: row[self.feature_label_name: ",row[self.features['label']['name']])
					if row[self.features['label']['name']] in self.features['include'] or self.features['include'][0] == 'ALL':
						if DEBUG:
							print("DEBUG: ",row[self.features['label']['name']]," Total: ",row[self.features['label']['total']]," Usadas: ",row[self.features['label']['used']])
						self.online = True
						feature = Feature(row[self.features['label']['name']],self.name,self)
						appendFeature(self.featureList,feature)
						feature.maxLicenses = float(row[self.features['label']['total']])
						feature.inUse = float(row[self.features['label']['used']])
						if isNan(feature.inUse):
							feature.inUse = 0;
						if self.used_as_free:
							feature.inUse = feature.maxLicenses - feature.inUse
						has_features = True
		return has_features

	def df_parse_users(self,users_tbl,current_feat):
		if not users_tbl.empty:
			for index,row in users_tbl.iterrows():
				if index == self.users['table']['skip_header']:
					continue
				if self.users['table']['method'] == 'search':
					#TODO: En base a codemeter solo sacamos info del hostname, ya lo iremos ampliando
					for feat in self.featureList:
						if feat.name in row[self.users['label']['featurename']]:
							user = User(value(row,self.users['label']['username'])) if self.users['label']['username'] is not None else "None"
							feat.userList.append(user)
							user.hostName = value(row,self.users['label']['hostname']) if self.users['label']['hostname'] is not None else "None"
							user.date = value(row,self.users['label']['date']) if self.users['label']['date'] is not None else "None"
				if self.users['table']['method'] == 'index':
					user = User(value(row,self.users['label']['username']) if self.users['label']['username'] is not None else "None")
					current_feat.userList.append(user)
					user.hostName = value(row,self.users['label']['hostname']) if self.users['label']['hostname'] is not None else "None"
					user.date = value(row,self.users['label']['date']) if self.users['label']['date'] is not None else "None"

	def parseWebFeaturesUrl(self):
		url_range  = self.features['url']['index'] if self.features['url']['index'] is not None else 2
		for i in range(1,url_range):
			if TRACE: trace(self.name," En bucle parseweburl")
			#Componemos la url
			if url_range == 2:
				url = self.features['url']['prefix']
			else:
				url = self.features['url']['prefix'] + str(i) + self.features['url']['suffix']
			if DEBUG: print("URL: ",url)
		return url

	def parseWebUsersUrl(self,i):
		passFeature = False
		#Me salto los features que no se esten usando
		for current_feat in self.featureList:
			if current_feat.name == self.features['include'][self.users['url']['index'].index(i)]:
				if current_feat.isUsing() is False:
					passFeature = True
				else:
					break
		if passFeature:
			return None,None
		if self.users['url']['suffix'] is not None:
			url = self.users['url']['prefix'] + str(i) + self.users['url']['suffix']
		else:
			url = self.users['url']['prefix']
		return current_feat,url

	def parseWebTableJs(self):
		if TRACE: trace(self.name," Entrando en parseWebJS")
		self.featureList = []
		self.online = False

		#Parse features
		url = self.parseWebFeaturesUrl()
		driver = self.parent.driver
		try:
			driver.get(url)
		except Exception as exc:
			#Si se produce una excepcion retornamos
			print("Excepcion en driver.get de pwtJs")
			print("URL: ",url)
			print("Exception: ",exc)
			return
		try:
			table = driver.find_element("id",self.features['js']['id'])
		except Exception as exc:
			print("Excepción en driver.find de PwtJS")
			print("Exception: ",exc)
			return
		try:
			table_html = table.get_attribute(self.features['js']['attr'])
		except Exception as exc:
			print("Excepción en table.get_attribute de PwtJS")
			print("Exception: ",exc)
			return
		try:
			feature_tbl = pd.read_html(table_html)[0]
		except Exception as exc:
			print("Excepcion en read_html de pwtJs")
			print("Exception: ",exc)
			return
		if self.features['js']['iloc'] is not None:
			feature_tbl.columns = feature_tbl.iloc[int(self.features['js']['iloc'])]
			feature_tbl.drop([int(self.features['js']['iloc'])],inplace=True)
		has_features = self.df_parse_features(feature_tbl)
		if DEBUG: print("Has features: ",has_features)
		if not has_features:
			if DEBUG: print("Salgo por not has features")
			return
		#Parse users
		#Lo meto todo en un try por si falla
		try:
			if has_features and self.users['monitor']:
				for i in self.users['url']['index']:
					current_feat,url = self.parseWebUsersUrl(i)
					if url is not None:
						driver.get(url)
						table = driver.find_element("id",self.users['js']['id'])
						table_html = table.get_attribute(self.users['js']['attr'])
						users_tbl = pd.read_html(table_html)[0]
						if self.users['js']['iloc'] is not None:
							users_tbl.columns = users_tbl.iloc[int(self.users['js']['iloc'])]
							users_tbl.drop([int(self.users['js']['iloc'])],inplace=True)
						self.df_parse_users(users_tbl,current_feat)
		except Exception as exc:
			print("Excepcion en parse users de pwtJs")
			print("Exception: ",exc)
			return

	def parseWebTable(self):
		if TRACE: trace(self.name," Entrando en parseWebTable")
		self.featureList = []
		self.online = False

		url = self.parseWebFeaturesUrl()
		#Aquí puede fallar, controlamos el error
		try:
			all_feature_tables = pd.read_html(url)
		except Exception as exc:
			print("Excepción en pd.read_html (features) de parseWebTable")
			print("Excepción: ",exc)
			return

		feature_tbl = all_feature_tables[self.features['table']['index']]
		#monitorizamos las licencias
		has_features = self.df_parse_features(feature_tbl)
		#monitorizamos los usuarios:
		if has_features and self.users['monitor']:
			for i in self.users['url']['index']:
				current_feat,url = self.parseWebUsersUrl(i)
				if url is not None:
					try:
						all_users_table = pd.read_html(url)
					except Exception as exc:
						print("Excepción en pd.read_html (users) de parseWebTable")
						print("Excepción: ",exc)
					return
					users_tbl = all_users_table[self.users['table']['index']]
					self.df_parse_users(users_tbl,current_feat)

	def parseWeb(self):
		if TRACE: trace(self.name," Entrando en parseweb")
		self.featureList = []
		self.online = False

		url = self.parseWebFeaturesUrl()
		if DEBUG: print("URL: ",self.name," ",url)
		#Realizamos el request
		try:
			Response = requests.get(url)
		except Exception as exc:
			print("Excepción en request.get  de parseWeb")
			print("Excepción: ",exc)
			return
		if TRACE: print("TRACE: ",self.name," parseweb despues de request")
		content = Response.content

		if WRITEHTML:
			name = str(i) + ".web"
			file = open(name,"wb")
			file.write(content)
			file.close()
			print("DEBUGURL: ",self.name," ",url)
			print("DEBUGREGEX: ",self.match_exist)

		#Vemos si existe algo para este parametro
		match = re.findall(self.features['match']['exist'], str(content), re.MULTILINE)
		if DEBUG: print("PARSEWEBMATCH: ",self.name," ",match)
		if match:
			if TRACE: trace(self.name,"En if match parseweb")
			feature = Feature(match[0],self.name,self)
			self.online = True
			appendFeature(self.featureList,feature)
			#Existe luego leemos el numero total de licencias y las que estan en uso
			total = re.findall(self.features['match']['total'], str(content), re.MULTILINE)
			inUse = re.findall(self.features['match']['used'], str(content), re.MULTILINE)
			#Tenemos que comprobar que efectivamente hay alguien usándolo, si no, no podemos leer el total de licencias
			try:
				feature.maxLicenses = float(total[0])
				feature.inUse = float(inUse[0])
			except:
				return
			if self.used_as_free:
				feature.inUse = feature.maxLicenses - feature.inUse
				if DEBUG:
					print("Total ",feature.name,": ",feature.maxLicenses)
					print("Inuse ",feature.name,": ",feature.inUse)
			else:
				if DEBUG: print("DEBUG: ",self.name," ",i,"nomatch. Pattern ",self.features['match']['exist'])

	def parseLsmon(self):
		self.featureList = []
		self.online = False
		p = subprocess.Popen([self.parent.LSMONCMD,self.license_server],stdin=subprocess.PIPE,stdout=subprocess.PIPE,universal_newlines=True)
		output = p.stdout
		p.stdin.close()
		for _output in output:
			if type(_output) == type(''):
				lines = _output.split('\n')
				for line in lines:
					if 'Feature name' in line:
						aux = line.split(":",1)[1][1:-3].replace('"','')
						if aux in self.features['include'] or self.features['include'][0] == "ALL":
							feature = Feature(aux, self.name,self)
							self.online = True
							appendFeature(self.featureList,feature)
						else:
							feature = None
					if 'Maximum concurrent user' in line and feature:
						feature.maxLicenses = float(line.split(":",1)[1][1:])
					if 'Unreserved tokens in use' in line and feature:
						feature.inUse = float(line.split(":",1)[1][1:])
					if  'Feature version' in line and feature:
						feature.name = feature.name + line.split(":",1)[1][1:].strip('"')
						if feature.translatable:
							if self.features['translate']['at_stage'] == 2:
								feature.translate()
					if 'User name' in line and feature and self.users['monitor']:
						user = User(line.split(":",1)[1][1:])
						feature.userList.append(user)
					if 'Host name' in line and feature and self.users['monitor']:
						user.hostName =  line.split(":",1)[1][1:]

	def parseLmutil(self):
		self.featureList = []
		self.online = False
		feature = None
		output = subprocess.getstatusoutput(self.parent.LMUTILCMD + ' ' + self.license_server)
		for _output in output:
			if type(_output) == type(''):
				lines = _output.split('\n')
				for line in lines:
					if 'Users of' in line:
						r = re.search('Users of (.*):  \(Total of (.*)licenses? issued;  Total of (.*) licenses? in use\)',line)
						if r is not None:
							if r.group(1) in self.features['include'] or self.features['include'][0] == "ALL":
								feature = Feature(r.group(1), self.name,self)
								self.online = True
								feature.maxLicenses = float(r.group(2))
								feature.inUse = float(r.group(3))
								appendFeature(self.featureList,feature)
							else:
								feature = None
					if ', start' in line and feature and self.users['monitor']:
						r = re.search('^\s+(.*) (.*) (.*) \((.*)\) \((.*)/(.*) (.*)\), start (.*)',line)
						user = User(r.group(1))
						user.hostName = r.group(2)
						user.device = r.group(3)
						user.date = r.group(8)
						feature.userList.append(user)
	def parseRlmutil(self):
		self.featureList = []
		self.online = False
		output = subprocess.getstatusoutput(self.parent.RLMUTILCMD + ' ' + self.license_server)
		for _output in output:
			if type(_output) == type(''):
				lines = _output.split('\n')
				for line in lines:
					feature = None
					if any(label in line for label in self.label['item']):
						feat_name = line.strip().split(" ")[0]
					#monitor features
					if self.label['count'] in line:
						r = re.search('.+count: (.*), (.*) inuse: (.*),',line)
						if r is not None:
							if r.group(1) in self.features['include'] or self.features['include'][0] == "ALL":
									feature = Feature(feat_name, self.name,self)
									self.online = True
									feature.maxLicenses = float(r.group(1))
									feature.inUse = float(r.group(3))
									appendFeature(self.featureList,feature)
							else:
									feature = None
					#monitor users
					if 'handle' in line  and self.users['monitor']:
						r = re.search('^\s+(.*) (.*): (.*)@(.*) (.*) at (.*)  \(handle.*',line)
						user = User(r.group(3))
						user.hostName = r.group(4)
						user.device = r.group(4)
						user.date = r.group(6)
						#tenemos que averiguar a que feature se refiere
						for feat in self.featureList:
							if r.group(1) == feat.name:
								feat.userList.append(user)
	def parseRawSocket(self):
		self.featureList = []
		self.online = False
		if TRACE: trace(self.name,"En parseRawSocket")
		try:
			host = socket.gethostbyname(self.license_server)
		except Exception as exc:
			print("Excepción en gethostbyname  de parRawSocket")
			print("Excepción: ",exc)
			return
		sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		sock.settimeout(self.timeout)
		try:
			if DEBUG:
				print("Conectando a ",host,":",self.license_port)
			sock.connect((host, self.license_port))
			if DEBUG:
				print("Conectado a ",host,":",self.license_port)
			if hasattr(self,'connect_only'):
				pass
			else:
				a = sock.recv(self.recv_bytes)
			feature = Feature(self.name,self.name,self)
			self.online = True
			feature.maxLicenses = 999
			feature.inUse = 888
			appendFeature(self.featureList,feature)
		except Exception as exc:
			print("Excepción en connect de parRawSocket")
			print("Excepción: ",exc)
			pass
		sock.close()

	def printFeatures(self):
		for feature in self.featureList:
			feature.printFeature()
		if self.featureList:
			return True
		else:
			return False

	def updateMetric(self):
		self.parse()
		self.parent.license_server_status.labels(app=self.name,fqdn=self.license_server,
												master='true',port='port',
												version='version').set(self.online)
		for feature in self.featureList:
			self.parent.license_feature_issued.labels(app=feature.app,name=feature.name).set(feature.maxLicenses)
			self.parent.license_feature_used.labels(app=feature.app,name=feature.name).set(feature.inUse)
			for user in feature.userList:
				try:
					self.parent.license_feature_used_users.labels(app=feature.app,name=feature.name,user=user.name,
																host=user.hostName,device=user.device).set(1)
				except Exception as exc:
					print("Excepción en updateMetric de updateMetric")
					print("Excepción: ",exc)
					print("Error en used_users.label", file=sys.stderr)
					user.printUserToError()

class Apps(object):
	def __init__(self,cfgFile):
		self.appList = []
		self.name = "Apps"
		with open(cfgFile, 'r') as yamlFile:
			self.cfg = yaml.safe_load(yamlFile)
		for appCfg in self.cfg['licenses']:
			if self.cfg['onlythis'] is None:
				if not appCfg['skip']:
					app = App(self, appCfg)
					self.appList.append(app)
			else:
				if isinstance(self.cfg['onlythis'],str):
					self.cfg['onlythis'] = self.cfg['onlythis'].split(",")
				if appCfg['name'] in self.cfg['onlythis']:
					app = App(self, appCfg)
					self.appList.append(app)

		self.license_feature_used = Gauge('license_feature_used','number of licenses used',['app','name'])
		self.license_feature_issued = Gauge('license_feature_issued','max number of licenses',['app','name'])
		self.license_feature_used_users = Gauge('license_feature_used_users','license used by user',['app','name','user','host','device'])
		self.license_server_status = Gauge('license_server_status','status of the license server',['app','fqdn','master','port','version'])
		self.PORT = self.cfg['config']['port']
		self.SLEEP = self.cfg['config']['sleep']
		self.LSMONCMD = self.cfg['config']['lsmon_cmd'] if not isWindows() else self.cfg['config']['lsmon_cmd'].replace('/','\\')
		self.LMUTILCMD = self.cfg['config']['lmutil_cmd'] if not isWindows() else self.cfg['config']['lmutil_cmd'].replace('/','\\')
		self.RLMUTILCMD = self.cfg['config']['rlmutil_cmd'] if not isWindows() else self.cfg['config']['rlmutil_cmd'].replace('/','\\')
		self.WEBDRIVER_TYPE = self.cfg['config']['webdriver']['type']
		self.WEBDRIVER_URL = self.cfg['config']['webdriver']['private-url'] if  isDocker() else self.cfg['config']['webdriver']['public-url']

		if TRACE: trace(self.name,"Despues de crear objetos prometheus")
		if self.WEBDRIVER_TYPE == 'local':
			self.driver = webdriver.Chrome()
		elif self.WEBDRIVER_TYPE == 'remote':
			driver_options = webdriver.ChromeOptions()
			self.driver = webdriver.Remote(
				command_executor=f"{self.WEBDRIVER_URL}",
				options=driver_options
			)
			self.driver.set_page_load_timeout(10)
		if TRACE: trace(self.name,"Saliendo de Apps")

	def parse(self):
		for app in self.appList:
			app.parse()

	def printApps(self):
		totalOnline = 0
		totalOffline = 0
		for app in self.appList:
			if app.printFeatures():
				totalOnline = totalOnline + 1
			else:
				totalOffline = totalOffline + 1
		if SUMMARY:
			now = datetime.now()
			dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
			print(dt_string," TOTAL ONLINE: ",totalOnline," TOTAL OFFLINE: ",totalOffline)

	def updateMetric(self):
		self.license_feature_used_users._metrics.clear()
		for app in self.appList:
			app.updateMetric()

if __name__ == '__main__':
	try:
		if TRACE: trace("MAIN ","Antes de Apps")
		apps = Apps(CONFIG_FILE)
	except Exception as exc:
		print("Excepción en configuración: ",exc)
		exit(1)
	start_http_server(apps.PORT)
	while True:
			try:
				if TRACE: trace("MAIN ","Antes de apps.updateMetric")
				apps.updateMetric()
			except Exception as exc:
				print("EXCEPCION NO CONTROLADA: ",exc),
				print(traceback.format_exc())
			if VERBOSE or SUMMARY:
				apps.printApps()
			sys.stdout.flush()
			time.sleep(apps.SLEEP)


import socket
import pygame

# Define client parameters
HOST = '192.168.1.4'  # Server IP address
PORT = 5000  # Port number

# Set up the client socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, PORT))

# Initialize Pygame
pygame.init()
WIDTH, HEIGHT = 800, 600
win = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Car Racing Game")

# Load track image
track_image = pygame.image.load(r'C:\Users\mebra\OneDrive\Desktop\Car Race\img\track.png')  # Replace 'track.png' with the actual image path

# Load car image
car_image = pygame.image.load(r'C:\Users\mebra\OneDrive\Desktop\Car Race\img\Car.png')  # Replace 'car.png' with the actual image path

chat_input = ''

# Game loop
running = True
clock = pygame.time.Clock()
while running:
    clock.tick(60)  # Limit to 60 FPS

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RETURN:
                if chat_input:
                    try:
                        client_socket.sendall(f"CHAT:{chat_input}".encode())
                        chat_input = ''
                    except Exception as e:
                        print(f"Error occurred while sending chat message: {e}")
            elif event.key == pygame.K_BACKSPACE:
                chat_input = chat_input[:-1]
            else:
                chat_input += event.unicode

    keys = pygame.key.get_pressed()
    if keys[pygame.K_UP]:
        player_input = 'UP'
    elif keys[pygame.K_DOWN]:
        player_input = 'DOWN'
    elif keys[pygame.K_LEFT]:
        player_input = 'LEFT'
    elif keys[pygame.K_RIGHT]:
        player_input = 'RIGHT'
    else:
        player_input = ''

    if player_input:
        client_socket.sendall(player_input.encode())

    # Receive game updates from the server
    try:
        game_state = client_socket.recv(1024).decode()

        # Process game state updates
        game_state_data = game_state.split(';')
        player_positions = [tuple(map(int, pos.split(','))) for pos in game_state_data[0].split(':')[1].split(',')]
        player_scores = [int(score) for score in game_state_data[1].split(':')[1].split(',')]

        # Update the game window with the new positions and scores
        win.fill((255, 255, 255))  # Clear the screen

        # Draw the track
        win.blit(track_image, (0, 0))

        # Draw player cars
        for i, pos in enumerate(player_positions):
            # Draw the car image at the player's position
            car_rect = car_image.get_rect(center=pos)
            win.blit(car_image, car_rect)

        # Display player scores
        font = pygame.font.SysFont(None, 24)
        text1 = font.render(f"Player 1 Score: {player_scores[0]}", True, (0, 0, 0))
        text2 = font.render(f"Player 2 Score: {player_scores[1]}", True, (0, 0, 0))
        win.blit(text1, (10, 10))
        win.blit(text2, (10, 40))

        # Display chat input box
        pygame.draw.rect(win, (255, 255, 255), (10, 550, 780, 40))
        pygame.draw.rect(win, (0, 0, 0), (10, 550, 780, 40), 2)
        font = pygame.font.SysFont(None, 24)
        text = font.render(chat_input, True, (0, 0, 0))
        win.blit(text, (20, 560))

        pygame.display.update()
    except ConnectionResetError:
        print("The server has closed the connection.")
        running = False

    except Exception as e:
        print(f"Error occurred during receiving game state: {e}")
        running = False

# Clean up resources
pygame.quit()
client_socket.close()


from .basehandler import BaseHandler
from ppmessage.api.error import API_ERR

from ppmessage.core.constant import API_LEVEL
from ppmessage.core.constant import REDIS_PPKEFU_ONLINE_KEY

import traceback
import datetime
import logging
import json
import redis

class PPConsoleGetRealTimeServiceNumber(BaseHandler):

    def _get(self):
        _request = json.loads(self.request.body)
        _app_uuid = _request.get("app_uuid")

        if _app_uuid == None:
            logging.error("not enough parameter provided.")
            self.setErrorCode(API_ERR.NO_PARA)
            return

        _redis = self.application.redis
        _number = []
        _today = datetime.datetime.now().strftime("%Y-%m-%d")

        for _i in range(24):
            _agents = set()
            _data = {}
            _key = REDIS_PPKEFU_ONLINE_KEY + ".app_uuid." + _app_uuid + ".day." + _today + ".hour." + str(_i)
            _devices = _redis.smembers(_key)
            for _device in _devices:
                _agents.add(_device.split(".")[0])
            _data[str(_i)] = len(_agents)
            _number.append(_data)
        _r = self.getReturnData()
        _r["number"] = _number
        return

    def initialize(self):
        self.addPermission(app_uuid=True)
        self.addPermission(api_level=API_LEVEL.PPCONSOLE)
        return

    def _Task(self):
        self._get()


import os
import random
import boto3
import collections
from enum import Enum
from PIL import Image, ImageDraw, ImageFont
import tweepy
import json
from datetime import datetime, timedelta
import time
import re
import boto3

class State(Enum):
    INCORRECT_POSITION = 0
    CORRECT_POSITION = 1
    NOT_PRESENT = 2
    EMPTY = 3

colors = {
	State.INCORRECT_POSITION: "\x1b[43;30m",
	State.CORRECT_POSITION: "\x1b[42;30m",
	State.NOT_PRESENT: "\033[00m",
	State.EMPTY: "\033[00m"
}

image_colors = {
	State.INCORRECT_POSITION: "#c9b458",
	State.CORRECT_POSITION: "#6aaa64",
	State.NOT_PRESENT: "#86888a",
	State.EMPTY: "#d3d6da",
}

font = ImageFont.truetype('/var/task/package/fonts/HelveticaNeue Bold.ttf', 50)
letter_font = ImageFont.truetype('/var/task/package/fonts/HelveticaNeue Bold.ttf', 20)

SUCESS_MESSAGE = "{} {}! You got it in {}/6 tries!"
INVALID_MESSAGE = "❌ Invalid guess! Try again"
FAIL_MESSAGE = "Nice Try! Max tries exceeded, the word was {}"
GUESS_MESSAGE = "Guess {}/6:"
messages = {
    1: ["🎯", "GENIUS"],
    2: ["🧠", "MAGNIFICENT"],
    3: ["🔥", "IMPRESSIVE"],
    4: ["🏆", "GREAT"],
    5: ["🏅", "NOT BAD"],
    6: ["🤙", "PHEW"]
}

bot_user_id = "1501031219114516482"
s3 = boto3.client('s3')

def get_word_lists():
	solutions_file = open(os.path.join(os.path.dirname(__file__), "/var/task/package/data/solution_list.txt"), "r")
	solutions = solutions_file.read().splitlines()

	guesses_file = open(os.path.join(os.path.dirname(__file__), "/var/task/package/data/guess_list.txt"), "r")
	guesses = guesses_file.read().splitlines()
	guesses = guesses + solutions

	return solutions,guesses

def random_solution(solutions):
	return random.choice(solutions)

def handle_guesses(guesses, solution):
	output_map = {}
	letter_map = {}
	for guess in guesses:
		states = []
		# store pool of incorrect placements & counts
		pool = collections.Counter(s for s, g in zip(solution, guess) if s != g)

		for solution_char, guess_char in zip(solution, guess):
			if solution_char == guess_char:
				letter_map[guess_char] = State.CORRECT_POSITION
				states.append(State.CORRECT_POSITION)
			elif guess_char in solution and pool[guess_char] > 0:
				if guess_char not in letter_map or letter_map[guess_char] != State.CORRECT_POSITION:
					letter_map[guess_char] = State.INCORRECT_POSITION
				pool[guess_char] -= 1
				states.append(State.INCORRECT_POSITION)
			else:
				if guess_char not in letter_map:
					letter_map[guess_char] = State.NOT_PRESENT
				states.append(State.NOT_PRESENT)
		output_map[guess] = states

	return output_map, letter_map

def output(guesses, output_map, letter_map):
	for guess in guesses:
		string = ""
		for letter, state in zip(guess, output_map[guess]):
			string += colors[state] + " " + letter.upper() + " "
		string += colors[State.NOT_PRESENT]

def draw_image(guesses, output_map, letter_map):
	background = Image.new('RGBA', (700, 850), (255, 255, 255, 255))

	for y, guess in enumerate(guesses):
		for x, letter, state in zip(range(len(guess)), guess, output_map[guess]):
			draw_block(background, x, y, letter, state)

	for y in range(len(guesses), 6):
		for x in range(5):
			draw_block(background, x, y, None, State.EMPTY)

	alphabet = ["qwertyuiop","asdfghjkl","zxcvbnm"]
	for y, row in enumerate(alphabet):
		for x, letter in enumerate(row):
			state = letter_map[letter] if letter in letter_map else State.EMPTY
			draw_letter(background, x, y, letter, state)

	return background

def draw_letter(background, x, y, letter, state):
	size = (50, 65)
	spacing = 5
	font.size = 5
	side_spacing = {"x":77, "y":600}

	text_color = "black" if state == State.EMPTY else "white"

	color = image_colors[state]
	x_pos = side_spacing["x"] + (size[0] + spacing)*x
	y_pos = side_spacing["y"] + (size[1] + spacing)*y

	if(y == 1):
		x_pos += (size[0]+spacing)*0.5
	elif y==2:
		x_pos += (size[0]+spacing)*1.5
	block_pos = [x_pos, y_pos, x_pos + size[0], y_pos + size[1]]
	text_pos = (x_pos+size[0]/2,y_pos+size[1]/2)

	ImageDraw.Draw(background).rounded_rectangle(block_pos, fill=color, radius=6)
	ImageDraw.Draw(background).text(text_pos, letter.upper(), font=letter_font, anchor="mm", fill=text_color)

def draw_block(background, x, y, letter, state):
	side_spacing = {"x":130, "y":50}
	spacing = 10
	square_size = 80

	x_pos = side_spacing["x"] + (square_size + spacing)*x
	y_pos = side_spacing["y"] + (square_size + spacing)*y

	block_pos = [x_pos, y_pos, x_pos + square_size, y_pos + square_size]
	text_pos = (x_pos+square_size/2,y_pos+square_size/2)

	color = image_colors[state]

	if(letter):
		ImageDraw.Draw(background).rectangle(block_pos, fill=color)
		ImageDraw.Draw(background).text(text_pos, letter.upper(), font=font, anchor="mm")
	else:
		ImageDraw.Draw(background).rectangle(block_pos, outline=color, width=3)

def get_tweepy_client():
	client = tweepy.Client(
    	consumer_key=os.environ['CONSUMER_KEY'],
    	consumer_secret=os.environ['CONSUMER_KEY_SECRET'],
    	access_token=os.environ['ACCESS_TOKEN'],
    	access_token_secret=os.environ['ACCESS_TOKEN_SECRET'],
    	bearer_token=os.environ['BEARER_TOKEN']
	)

	auth = tweepy.OAuth1UserHandler(
	   os.environ['CONSUMER_KEY'], os.environ['CONSUMER_KEY_SECRET'],
	   os.environ['ACCESS_TOKEN'], os.environ['ACCESS_TOKEN_SECRET']
	)
	api = tweepy.API(auth)

	return client, api

def is_start_tweet(tweet, game_sessions):
	if "new game" not in tweet.text.lower():
		return False
	if str(tweet.author_id) not in game_sessions:
		return True
	session = game_sessions[str(tweet.author_id)]
	if session["new_game_id"] == str(tweet.id) or str(tweet.created_at) < session["created_at"]:
		return False

	return True

def is_guess_tweet(tweet, game_sessions):
	if str(tweet.author_id) not in game_sessions:
		return False
	session = game_sessions[str(tweet.author_id)]
	if(tweet.referenced_tweets is None):
		return False
	if(len(re.sub(r"(?:\@|https?\://)\S+", "", tweet.text).strip()) > 7):
		return False
	if(len(session["guesses"]) >= 6):
		return False

	is_referenced = False
	for referenced_tweet in tweet.referenced_tweets:
		if str(referenced_tweet.id) == session["latest_reply"]:
			is_referenced = True
	return is_referenced

def start_session(api, tweet, user, solution_list):
	message = "New Wordle game started. Start by replying with your first guess!"
	status = api.update_status(status=f"@{user.username} {message}", in_reply_to_status_id=str(tweet.id))
	session = {
		"author_id": str(tweet.author_id),
		"latest_reply": str(status.id),
		"guesses": [],
		"solution": random_solution(solution_list),
		"new_game_id": str(tweet.id),
		"created_at": str(tweet.created_at)
	}
	return session

def guess_response(api, message, tweet, user, image=None):
	response = None
	if(image):
		filename = f'/tmp/out_{tweet.id}.png'
		image.save(filename)
		response = api.update_status_with_media(status=f"@{user.username} {message}", filename=filename, in_reply_to_status_id=tweet.id)
		if os.path.exists(filename):
  			os.remove(filename)
	else:
		response = api.update_status(status=f"@{user.username} {message}", in_reply_to_status_id=tweet.id)
	return response.id

def get_since_time(delta_hours):
	date = datetime.utcnow()
	date = date - timedelta(hours=delta_hours)
	return date

def get_replies(client):
	query = f"-is:retweet (to:{bot_user_id} OR @wordle_io)"
	since_date = get_since_time(0.3)

	tweets = []
	users = {}
	for response in tweepy.Paginator(client.search_recent_tweets, query=query, start_time=since_date,
  			expansions=["author_id","referenced_tweets.id"], tweet_fields=["created_at"], user_fields=["username"], max_results=100):
		if not response.data:
			continue
		for user in response.includes['users']:
			users[user.id] = user
		for tweet in response.data:
			tweets.append(tweet)

	return [(tweet, users[tweet.author_id]) for tweet in tweets]

def valid_guess(guess, guess_list):
	return guess in guess_list

def get_game_sessions():
	try:
		obj = s3.get_object(
			Bucket=os.environ['S3_BUCKET'],
			Key=os.environ['GAME_SESSIONS_KEY']
		)
		sessions_json = obj['Body'].read()
		data = json.loads(sessions_json)
		return data
	except Exception as e:
		print("FATAL ERROR: Failed to load sessions: " + str(e))
		exit()

def store_game_sessions(game_sessions):
	sessions_string = json.dumps(game_sessions)
	s3.put_object(
		Bucket=os.environ['S3_BUCKET'],
    	Key=os.environ['GAME_SESSIONS_KEY'],
    	Body=str(sessions_string)
	)

def clear_old_sessions(game_sessions):
	clear_time = str(get_since_time(48))
	for user_id, session in game_sessions.copy().items():
		if(session["created_at"] < clear_time):
			game_sessions.pop(user_id)

def lambda_handler(event, context):
	solution_list, guess_list = get_word_lists()
	client, api = get_tweepy_client()
	game_sessions = get_game_sessions()
	update = False

	tweets = get_replies(client)
	if not tweets: return

	for tweet, user in tweets:

		print(str(tweet.id) + " " + str(user.username) + " " + tweet.text)

		user_id = str(user.id)
		if is_start_tweet(tweet, game_sessions):
			print(" => new game tweet")
			session = start_session(api, tweet, user, solution_list)
			game_sessions[user_id] = session
			update = True
		elif is_guess_tweet(tweet, game_sessions):
			print(" => new guess tweet")
			guess = re.sub(r"(?:\@|https?\://)\S+", "", tweet.text).strip().lower()
			session = game_sessions[user_id]
			update = True
			if len(guess) != 5 or not valid_guess(guess, guess_list):
				tweet_id = guess_response(api, INVALID_MESSAGE, tweet, user)
				session["latest_reply"] = str(tweet_id)
				game_sessions[user_id] = session
				continue

			session["guesses"].append(guess)
			guesses = session["guesses"]

			output_map, letter_map = handle_guesses(guesses, session["solution"])
			image = draw_image(guesses, output_map, letter_map)

			guess_count = len(guesses)
			message = ""
			game_over = False
			if(guess == session["solution"]):
				message = SUCESS_MESSAGE.format(messages[guess_count][0], messages[guess_count][1], guess_count)
				game_over = True
			elif guess_count >= 6:
				message = FAIL_MESSAGE.format(session["solution"])
				game_over = True
			else:
				message = GUESS_MESSAGE.format(guess_count)

			tweet_id = guess_response(api, message, tweet, user, image)
			session["latest_reply"] = str(tweet_id)
			game_sessions[user_id] = session

	if update:
		clear_old_sessions(game_sessions)
		store_game_sessions(game_sessions)


import random
global count
global state

#1 is dead, 2 is alive
def drawGrid(state):
    black=(0,0,0)
    white=(255,255,255)
    stroke(*black)
    global count
    global state
    if count==0:
        for i in range (50):
            state.append([])
            for j in range(50):
                x=random.randint(1,2)
                if x==2:
                    fill(*white)
                else:
                    fill(*black)
                rect(i*20+1, j*20+1, 20, 20)
                state[i].append(x)
    nextstate=[]
    for i in range(len(state)):
        nextstate.append([])
        for j in range(len(state[i])):
            print(state[i][j])
            data=readGrid(state, i, j)
            if data[0]==5:
                if state[i][j]==1:
                    nextstate[i].append(2)
                else:
                    if data[1]<2:
                        nextstate[i].append(1)
            else:
                if data[1]==2 or data[1]==3:
                    nextstate[i].append(2)
                else:
                    nextstate[i].append(1)
        for i in range (len(nextstate)):
            for j in range(len(nextstate[i])):
                if nextstate[i][j]==2:
                    fill(*white)
                else:
                    fill(*black)
                rect(i*20+1, j*20+1, 20, 20)
        state=nextstate

def readGrid(array, x, y):
    neighbor=[0,0,0,0,0,0,0,0,0]
    if x==0:
        neighbor[0]=-1
        neighbor[1]=-1
        neighbor[2]=-1
    elif x==49:
        neighbor[6]=-1
        neighbor[7]=-1
        neighbor[8]=-1
    if y==0:
        neighbor[0]=-1
        neighbor[3]=-1
        neighbor[6]=-1
    elif y==49:
        neighbor[2]=-1
        neighbor[5]=-1
        neighbor[8]=-1
    count=0
    print(neighbor)
    for i in range(3):
        for j in range(3):
            if neighbor[count]!=-1:
                if count!=4:
                    neighbor[count]=array[x-1+i][j-1+j]
                count+=1
    negonecount=0
    for i in neighbor:
        if i==-1:
            negonecount+=1
    alivecount=0
    for i in range (8):
        if neighbor[i]==2:
            alivecount+=1
    return (negonecount, alivecount)

# def keyPressed():
#     spacebar=True
#     return spacebar

def setup():
    size(1000,1000)
    background(255)
    global count
    count=0
    global state
    state=[]

def draw():
    global count
    global state
    state=drawGrid(state)
    count+=1


from utils.Error import NoneError
from logs.log import module_log
from dataclasses import dataclass
from utils.Tools import is_none

'''
        this module has guardian class that will contain
        all the guardian information that related to the
        student information.
'''

@dataclass
class guardian:

    ##################################[initialising]#####################################################
    def __init__(self,*args):

        if is_none(args): raise NoneError(f'Guardian.py : function - __init__')

        # create the log
        self.__logger:module_log = module_log(log_name = 'guardian.log',disable_log = False)
        # log the creation
        self.__logger.log.debug(f'__init__ <- {args}')

        #initialize
        self.__name:str
        self.__role:str
        self.__contact:str

        #declaration
        self.__name, self.__role, self.__contact = args
        self.__data:dict = {'name':self.__name, 'contact-no':self.__contact, 'role':self.__role}

    ##################################[guardian properties]#####################################################

    @property
    def name(self) -> str:
        self.__logger.log.info( f'property.getter - name -> {self.__name}')
        return self.__name

    @property
    def contact(self) -> str:
        self.__logger.log.info( f'property.getter - contact -> {self.__contact}')
        return self.__contact

    @property
    def role(self) -> str:
        self.__logger.log.info( f'property.getter - role -> {self.__role}')
        return self.__role

    ##################################[guardian information]#####################################################
    @property
    def data(self) -> dict:
        self.__logger.log.info( f'property.getter - data -> {self.__data}')
        return self.__data

    @data.setter
    def data(self,value: dict) -> None:
        if is_none(value): raise NoneError(f'Guardian.py : property.setter - data')
        self.__name,self.__contact,self.__role = value
        self.__data = value

    def __rpr__(self):
        return f'guardian[ {self.__data} ]'

    def __str__(self):
        return f'guardian[ {self.__data} ]'


import uuid
from typing import Dict

import pytest
from temporalio import workflow
from temporalio.client import Client
from temporalio.worker import Replayer, Worker

from hello.hello_failure import SayHelloParams, SayHelloWorkflow, say_hello

async def test_replayer_workflow_complete(client: Client) -> None:
    task_queue_name = str(uuid.uuid4())

    async with Worker(
        client,
        task_queue=task_queue_name,
        workflows=[SayHelloWorkflow],
        activities=[say_hello],
    ):
        async with new_say_hello_worker(client) as worker:
            handle = await client.start_workflow(
                SayHelloWorkflow.run,
                SayHelloParams(name="Temporal"),
                id=f"workflow-{uuid.uuid4()}",
                task_queue=worker.task_queue,
            )
            assert "Hello, Temporal!" == await handle.result()

        await Replayer(workflows=[SayHelloWorkflow]).replay_workflow(
            await handle.fetch_history()
        )

async def test_replayer_workflow_nondeterministic(client: Client) -> None:
    # Run workflow to completion
    async with new_say_hello_worker(client) as worker:
        handle = await client.start_workflow(
            SayHelloWorkflow.run,
            SayHelloParams(name="Temporal", should_cause_nondeterminism=True),
            id=f"workflow-{uuid.uuid4()}",
            task_queue=worker.task_queue,
        )
        await handle.result()
    with pytest.raises(workflow.NondeterminismError):
        await Replayer(workflows=[SayHelloWorkflow]).replay_workflow(
            await handle.fetch_history()
        )

@workflow.defn
class SayHelloWorkflowDifferent:
    @workflow.run
    async def run(self) -> None:
        pass

def new_say_hello_worker(client: Client) -> Worker:
    return Worker(
        client,
        task_queue=str(uuid.uuid4()),
        workflows=[SayHelloWorkflow],
        activities=[say_hello],
    )


# 处理用户的常用词及从用词的出现次数

from collections import Counter
import pymongo
from append_userArticle.jieba_cut import articles_common_words

def user_commWords_weight(user_homepage=None, limit=500, skip=0):
    """
    根据输入的 user_homepage 对用户的文章,利用 jieba库 进行分词，并统计出用户每篇文章常用词、用户前100常用词；
    对应前100常用词的出现次数存入 commonWords_v5 集合
    :param user_homepage:
    :return:
    """

    # 连接 mongoDB数据库
    client = pymongo.MongoClient("mongodb://127.0.0.1:27017/")
    # jianshu_huaxiang 数据库名
    db = client['jianshu_huaxiang']
    # site 集合表名 存放用户文章
    collection_UA = db['site']

    # 常用词 集合表名 存放用户常用词及常用词权重
    collection_CW_v5 = db['commonWords_v5']

    if user_homepage:
        res = collection_UA.find({'user_homepage': user_homepage})
    else:
        res = collection_UA.find().limit(limit).skip(skip)

    # 遍历得到用户对象
    for user in res:
        print(user['nickname'])
        # 作者常用词列表
        user_commonWords = []
        # print(user['user_homepage'])
        # 将数据库当前前用户的 nickname 、user_homepage 拼接成字典类型
        user_infro = {}
        user_infro['nickname'] = user['nickname']
        user_infro['user_homepage'] = user['user_homepage']
        user_infro['gender'] = user['gender']
        # 为处理 文章分词开辟新的 列表空间
        user_infro['article_commonWords'] = []

        # 以用户常用词作为 key, 用户常用词出现的次数作为 value
        user_infro['user_commonWords'] = []

        # 用户信息数据提交数据库，新增至 commonWords 集合
        collection_CW_v5.insert_one(user_infro)

        user_article = user['user_article']
        # 每篇文章的常用词
        top_words = 50
        for piece in range(len(user_article)):
            # 一篇文章的常用词
            user_article_first = user_article[piece]['content']  # 文章内容
            title = user_article[piece]['title']  # 文章标题

            if piece % 10 == 0:
                print("第{piece}篇:".format(piece=piece + 1))
            top_word_list = articles_common_words(user_article_first, top_words)
            article_commonWords = []
            # 遍历 top_word_list列表 整合为str类型对象
            for j in range(len(top_word_list)):
                # print(str(top_word_list[j][0]), end=',')
                article_commonWords.append(top_word_list[j][0])

                # 作者常用词
                user_commonWords.append(top_word_list[j][0])

            # print(' '.join(article_uselyWords))
            # 提交保存当前用户文章的常用词
            article = {}
            article['title'] = title
            # article['common_words'] = str(article_commonWords)
            article['common_words'] = ','.join(article_commonWords)
            user_homepage = user_infro['user_homepage']
            collection_CW_v5.update_one({"user_homepage": user_homepage},
                                        {"$addToSet": {"article_commonWords": {"$each": [article]}}})

        counter = Counter(user_commonWords)
        list_words = counter.most_common()
        # print(list_words[:100])
        user_commonWords_dict = {}
        # list_words 列表套元组 100项中每一项 转为字典对象 存入commonWords_v4 集合表
        for item in list_words[:100]:
            commWord = {}
            # 以用户常用词作为 key, 用户常用词出现的次数作为 value
            commWord[item[0]] = item[1]
            collection_CW_v5.update_one({"user_homepage": user_homepage},
                                        {"$addToSet": {"user_commonWords": {"$each": [commWord]}}})

            user_commonWords_dict[item[0]] = item[1]

        # print(user_commonWords_dict)

        # 把 user_commonWords_dict 更新至 commonWords_v5 集合
        collection_CW_v5.update_one({"user_homepage": user_homepage}, {"$set": {"user_commonWords_dict": user_commonWords_dict}})

if __name__ == '__main__':
    user_homepage = 'https://www.jianshu.com/u/b8f58ffc3272'
    user_commWords_weight(user_homepage)


import logging
import configparser
import os

logger = logging.getLogger(__name__)

FILE_PATH = os.path.join(os.path.dirname(
    os.path.abspath("__file__")), 'util', 'puppy', 'codedog.ini')

class ConfigReader(object):
    """配置文件读取工具类"""

    def __init__(self, cfg_string=None, cfg_file=FILE_PATH, interpolation=None, encoding="utf-8-sig"):
        """
        构造函数
        :param cfg_string: ini格式的字符串
        :param cfg_file: ini文件
        :param interpolation: 变量解析方式,默认为None,不解析变量
        :return:
        """
        self._cfg = configparser.ConfigParser(interpolation=interpolation)
        self._cfg.optionxform = str  # 设置key值区分大小写
        self._cfg_string = cfg_string
        self._cfg_file = cfg_file
        if self._cfg_string:
            self._cfg.read_string(self._cfg_string)
        else:
            self._cfg.read(self._cfg_file, encoding=encoding)

    def get_comments(self):
        """读取文件注释
        """
        comment_lines = []
        with open(self._cfg_file, 'r') as rf:
            new_config_lines = rf.readlines()
        for line in new_config_lines:
            if line.startswith(";"):
                comment_lines.append(line)
        return comment_lines

    def read(self, section_name):
        """
        读取ini格式的配置内容
        :param section_name: 需要读取的块名
        :param cfg_string: str, 配置字符串
        :param cfg_file: str, 配置文件路径
        :return: dict, 配置键值对
        """
        rule_params_dict = {}
        for key, value in self._cfg.items(section_name):
            rule_params_dict[key] = value
        return rule_params_dict

    def get_section_names(self):
        """
        获取所有的section名称
        :return:
        """
        return self._cfg.sections()

class ConfigWriter(object):
    def write(self, section_name, section_dict, comment_str=None):
        """
        将内容写入文件
        :param section_name:
        :param section_dict:
        :param comment_str:
        :return:
        """
        context = ""
        if comment_str:
            context += comment_str
        context += "\n"

        context += "[%s]\n" % section_name

        for key, value in section_dict.items():
            line = format(key, '<12') + ": "
            if value:
                line += value
            line += "\n"
            context += line
        return context
        # with open(file_path, 'w') as wf:
        #     wf.write(context)


from src.customer import Customer
from src.movie import Movie
from src.movie import MOVIE_TYPES
from src.movie import TYPE_NEW_RELEASE
from src.movie import TYPE_REGULAR
from src.movie import TYPE_CHILDREN
from src.movie import TYPE_UNKNOWN
from src.object_mother import ObjectMother
from src.rental import Rental
from unittest import TestCase
import unittest

class TestCustomer(TestCase):
    def setUp(self):
        self.david_name = "David"
        self.john_name = "John"
        self.pat_name = "Pat"
        self.steve_name = "Steve"
        self.david = ObjectMother.customer_with_no_rentals(self.david_name)
        self.john = ObjectMother.customer_with_one_new_release(self.john_name)
        self.pat = ObjectMother.customer_with_one_of_each_rental_type(
                self.pat_name)
        self.steve = ObjectMother.customer_with_one_new_release_and_one_regular(
                self.steve_name)
        self.customers = [self.david, self.john, self.pat, self.steve]

    def rental_info(self, starts_with, ends_with, rentals):
        result = ""
        for rental in rentals:
            result +="{0}{1} {2}{3}\n".format(
                    starts_with,
                    rental.movie.get_title(),
                    rental.get_charge(),
                    ends_with)
        return result

    def exp_statement(self, format_string, customer, rental_info):
        return format_string.format(customer.name, rental_info,
                customer.get_total_charge(), customer.get_total_points())

    def test_get_name(self):
        self.assertEqual(self.david_name, self.david.name)
        self.assertEqual(self.john_name,  self.john.name)
        self.assertEqual(self.pat_name,   self.pat.name)
        self.assertEqual(self.steve_name, self.steve.name)

    def test_statement(self):
        for c in self.customers:
            self.assertEqual(
                    self.exp_statement("Rental record for {0}\n" +
                        "{1}Amount owed is {2}\n" +
                        "You earned {3} frequent renter points",
                        c,
                        self.rental_info("\t", "", c.get_rentals())),
                    c.statement())

    def test_html_statement(self):
        for c in self.customers:
            self.assertEqual(
                    self.exp_statement(
                        "
Rental record for {0}
\n{1}" +
                        "
Amount owed is {2}
\n" +
                        "
You earned {3} frequent renter points
",
                        c,
                        self.rental_info("
", "
", c.get_rentals())),
                    c.html_statement())

    def test_invalid_title(self):
        with self.assertRaises(TypeError):
            ObjectMother.customer_with_no_rentals("Bob").add_rental(
                    Rental(Movie("Crazy, Stupid, Love.", TYPE_UNKNOWN), 4))

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