"""

Consider a string consisting of lowercase English alphabetic letters (i.e., [a-z]) only. We use the following rules
to encode all of its characters into string s: · a is encoded as 1, b is encoded as 2, c is encoded as 3, ...,
and i is encoded as 9. · j is encoded as 10#, k is encoded as 11#, i is encoded as 12#, ..., and z is encoded as 26#.
· If there are two or more consecutive occurrences of any character, then the character count is written within
parentheses (i.e., (c) , where c is an integer denoting the count of consecutive occurrences being encoded)
immediately following the character. For example, consider the following string encodings: o String "abzx" is encoded
as s = "1226#24#". o String "aabccc" is encoded as s = "1(2)23(3)". o String "bajj" is encoded as s = "2110#(2)". o
String "wwxyzwww" is encoded as s = "23#(2)24#25#26#23#(3)°. Complete the frequency function in the editor below. It
has one parameter: a string, s, that was encoded using the rules above and consists of digits (i.e., decimal integers
from 0 to 9), # symbols, and parentheses. It must return an array of 26 integ · The element at index 0 denotes the
frequency of character a in the original string. · The element at index 1 denotes the frequency of character b in the
original string. · The element at index 2 denotes the frequency of character c in the original string. · The element
at index 25 denotes the frequency of character z in the original string. Input Format Locked stub code in the editor
reads encoded string s from stdin and passes it to the function. Constraints · String s consists of decimal integers
from 0 to 9, #s, and O's only. · 1 length of s 105 · It is guaranteed that string s is a valid encoded string. · 2 c
104, where c is a parenthetical count of consecutive occurrences of an encoded character. Output Format The function
must return an array of 26 integers denoting the respective frequencies of each character (i.e., a through z) in the
decoded string. This is printed to stdout by locked stub code in the editor. Sample Input 0 1226#24# Sample Output 0
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1

1226#24#

1245(45)

0 + 1 * 5 = 5

5 + 10 * 4

45

24 => Z
"""

def decode_input(string):
    result = [0] * 26
    i = len(string) - 1
    number = 0
    while i >= 0:
        if string[i] == '#':
            number = int(string[i - 2]) * 10 + int(string[i - 1])
            result[number - 1] += 1
            i -= 3
            number = 0
        elif string[i] == ')':
            # Time to be looking for a opening parentheses
            k = i - 1
            power = 0
            while k > 0 and string[k] != '(':
                number = number + (10 ** power) * int(string[k])
                power += 1
                k -= 1
            i = k - 1
        elif string[i].isdigit():
            # Checks if a number has been found initially
            frequency = 1
            if number > 0:
                frequency = number
            number = int(string[i])
            result[number - 1] += 1 * frequency
            number = 0
            i -= 1

    return result

answer = decode_input('12(2)13#')

print(answer)


from typing import List, Optional, Type
from pydantic import BaseModel, Field, create_model
from sqlalchemy import select
from sqlalchemy.orm import aliased
from Models import ModelRunningAccount, ModelUser
from .PublicSchema import InsertBase, UpdateBase

from .PublicFunctions import (
    format_current_time,
    insert_exclude,
    nullable,
    select_in_exclude,
    select_out_exclude,
    sqlalchemy_to_pydantic,
    update_exclude,
)

ModelRunningAccount_nullable_columns = ["Money", "Param1"]
ModelRunningAccount_nullable_columns.extend(nullable)

ModelRunningAccountUpdateSingleGetSchemaBase = sqlalchemy_to_pydantic(
    ModelRunningAccount,
    update_exclude,
    table_name="ModelRunningAccountUpdateSingleGetSchemaBase",
)

class ModelRunningAccountUpdateSingleGetSchema(
    ModelRunningAccountUpdateSingleGetSchemaBase
):
    ID_User_NoUser: Optional[str] = Field(
        default=None, title="打卡者的学号", description="这是这节课程安排课对应的老师/演讲者的教职工号"
    )

    class Config:
        orm_mode = True

class ModelRunningAccountUpdateMultipleGetSchema(BaseModel):
    data: List[ModelRunningAccountUpdateSingleGetSchema]
    n: int

class ModelRunningAccountUpdateSingleTableSchema(
    ModelRunningAccountUpdateSingleGetSchemaBase
):
    TimeUpdate: int = format_current_time()
    IdManager: int
    IMark: int = 0

class ModelRunningAccountUpdateMultipleTableSchema(BaseModel):
    data: List[ModelRunningAccountUpdateSingleTableSchema]
    n: int

ModelRunningAccountInsertSingleGetSchemaBase = sqlalchemy_to_pydantic(
    ModelRunningAccount,
    insert_exclude,
    ModelRunningAccount_nullable_columns,
    table_name="ModelRunningAccountInsertSingleGetSchemaBase",
)

class ModelRunningAccountInsertSingleGetSchema(
    ModelRunningAccountInsertSingleGetSchemaBase
):
    ID_User_NoUser: Optional[str] = Field(
        default=None, title="打卡者的学号", description="这是这节课程安排课对应的老师/演讲者的教职工号"
    )

    class Config:
        orm_mode = True

class ModelRunningAccountInsertMultipleGetSchema(BaseModel):
    data: List[ModelRunningAccountInsertSingleGetSchema]
    n: int

class ModelRunningAccountInsertSingleTableSchema(
    ModelRunningAccountInsertSingleGetSchemaBase
):
    TimeUpdate: int = format_current_time()
    IdManager: int
    IMark: int = 0

class ModelRunningAccountInsertMultipleTableSchema(BaseModel):
    data: List[ModelRunningAccountInsertSingleTableSchema]
    n: int

ModelRunningAccountSelectOutSingleTableSchemaBase = sqlalchemy_to_pydantic(
    ModelRunningAccount,
    select_out_exclude,
    table_name="ModelRunningAccountSelectOutSingleTableSchemaBase",
)
ModelRunningAccountSelectInSingleTableSchema = sqlalchemy_to_pydantic(
    ModelRunningAccount,
    select_in_exclude,
    [],
    table_name="ModelRunningAccountSelectInSingleTableSchema",
)

class ModelRunningAccountSelectOutSingleTableSchema(
    ModelRunningAccountSelectOutSingleTableSchemaBase
):
    ID_User_Name: Optional[str] = Field(
        default=None, title="打卡签到者的姓名", description="这次打卡签到者的姓名"
    )
    ID_User_NoUser: Optional[str] = Field(
        default=None, title="打卡者的学号", description="这是这次打卡安排课对应的老师/演讲者的教职工号"
    )
    ID_Manager_Name: Optional[str] = Field(
        default=None, title="修改者的姓名", description="这次课程信息最新一次修改的修改者姓名"
    )

    class Config:
        orm_mode = True

user1 = aliased(ModelUser)
##TODO:WARNING:随着sqlalchemy的升级，subquery的查询列的方法会发生改变，会从原来的sub.c.column_name变成sub.column_name
sub_runningaccount = select(ModelRunningAccount).where(ModelRunningAccount.Type == 4097).where(ModelRunningAccount.IMark == 0).subquery()  # type: ignore
sub_user = select(ModelUser.ID, ModelUser.Name, ModelUser.NoUser).where(ModelUser.IMark == 0).subquery()  # type: ignore
user1 = aliased(sub_user)
ModelRunningAccount_sub_stmt = (
    select(
        sub_runningaccount,
        sub_user.c.Name.label("ID_User_Name"),
        sub_user.c.NoUser.label("ID_User_NoUser"),  # type: ignore
        user1.c.Name.label("ID_Manager_Name"),
    )
    .outerjoin(sub_user, sub_user.c.ID == sub_runningaccount.c.ID_User)
    .outerjoin(user1, user1.c.ID == sub_runningaccount.c.IdManager)  # type: ignore
    .subquery()  # type: ignore
)


from flask import Flask, render_template, request, jsonify, url_for, redirect, session
import database
import config
import objects
import random
import json
import time
import linenotify
from datetime import datetime, timedelta
from GLOBAL import *
from web import webapp
import util

app = Flask("App")
app.register_blueprint(webapp, url_prefix='/')

app.config['SECRET_KEY'] = config.SECRET_KEY
connectDevice = dict()
reqtoken = dict()

db = database.database('firebase.json', True)

@app.route("/api/register", methods=["POST"])
def register():
    gettoken = request.form.get('token')
    print(gettoken)
    gettype = request.form.get('type')
    if gettoken == None or gettype == None or len(gettoken) == 0 or len(gettype) == 0:
        return "error"
    else:
        if db.getDevice(gettoken) == None:
            if gettype not in objects.devicestatus:
                print(f"{gettoken} error(unknown type)")
                return "error(unknown type)"

            db.registerDevice(gettoken, gettype)
            connectDevice[gettoken] = db.getDevice(gettoken)
            connectDevice[gettoken].timeupdate()
            db.updateDeviceLogs(
                gettoken, 0,  connectDevice[gettoken].status, "Register to Server")
            print(f"{gettoken} Connect to Server")
            return getdevice()
        else:
            if connectDevice.get(gettoken) == None:
                connectDevice[gettoken] = db.getDevice(gettoken)
                connectDevice[gettoken].timeupdate()
                db.updateDeviceLogs(
                    gettoken, 0,  connectDevice[gettoken].status, "Connected to Server")
                print(f"{gettoken} Register to Server")
            return getdevice()

@app.route('/api/gentoken', methods=["GET"])
def genkey():
    return objects.genToken()

@app.route("/api/setstat", methods=["POST"])
def setstat():
    gettoken = request.form.get('token')
    getstatus = request.form.get('status')
    if gettoken == None or len(gettoken) == 0:
        return "error"
    else:
        if gettoken not in list(connectDevice):
            return "error (not connected)"
        else:
            getstatus = int(getstatus)
            # check status is valid
            objects.devicestatus[connectDevice[gettoken].type][getstatus]
            stat_from = objects.devicestatus[connectDevice[gettoken]
                                             .type][connectDevice[gettoken].status]
            stat_to = objects.devicestatus[connectDevice[gettoken].type][getstatus]
            db.updateDeviceLogs(
                gettoken, 1, connectDevice[gettoken].status, f"Status From {stat_from}({connectDevice[gettoken].status}) To {stat_to}({getstatus})")
            connectDevice[gettoken].update(getstatus)
            return "success"

@app.route("/api/reqdigit", methods=["POST"])
def reqdigit():
    gettoken = request.form.get('token')
    if gettoken == None or len(gettoken) == 0:
        return "error"
    else:
        if gettoken not in list(connectDevice):
            return "error(not connected)"
        else:
            getdigit = random.randint(100000, 999999)
            for i in reqtoken:
                if reqtoken[i][0] == gettoken:
                    del reqtoken[i]
                    reqtoken[getdigit] = (gettoken, objects.getNowTime())
                    return str(getdigit)
            # db.updateDeviceLogs(devicetoken, 0,  connectDevice[devicetoken].status, "Request Token")

            connectDevice[gettoken].timeupdate()
            reqtoken[getdigit] = (gettoken, objects.getNowTime())
            return str(getdigit)

@app.route("/api/reqtoken", methods=["POST"])
def reqtokenf():
    getcode = request.form.get('code')
    if getcode == None or len(getcode) == 0:
        return "error"
    else:
        try:
            getcode = int(getcode)
        except:
            return "error"
        if getcode not in list(reqtoken):
            return "error not in list"
        else:
            gettoken = reqtoken[getcode][0]
            tempdev = db.getDevice(gettoken)
            retdict = {
                "token": str(gettoken),
                "type": str(tempdev.type),
                "lastupdate": str(tempdev.lastupdate),
                "status": str(tempdev.status),
                'setting': tempdev.setting
            }
            return jsonify(retdict)

@app.route("/api/getstat", methods=["POST"])
def getstat():
    gettoken = request.form.get('token')
    if gettoken == None or len(gettoken) == 0:
        return "error"
    else:
        if gettoken not in list(connectDevice):
            return "error(not connected)"
        else:
            try:
                json_object = json.loads(connectDevice[gettoken].rawdata)
                json_object["status"] = connectDevice[gettoken].status
                json_object["status_history"] = connectDevice[gettoken].rawdata_history[0:10]
            except:
                return "empty"

            return jsonify(json_object)

@app.route("/api/update", methods=["POST"])
def update():
    gettoken = request.form.get('token')
    getdata = request.form.get('data')

    if gettoken == None or len(gettoken) == 0 or getdata == None:
        return "error"
    else:
        if gettoken not in list(connectDevice):
            return "error(not connected)"
        else:
            connectDevice[gettoken].timeupdate()
            connectDevice[gettoken].rawdata = getdata
            if len(connectDevice[gettoken].rawdata_history) <= 60:
                connectDevice[gettoken].rawdata_history.append(getdata)
            else:
                connectDevice[gettoken].rawdata_history.pop(60)
                connectDevice[gettoken].rawdata_history.insert(0, getdata)

            if connectDevice[gettoken].cache["datacount"] < 60:

                connectDevice[gettoken].cache["datacount"] += 1
            else:
                history_list = []
                average_history = {}

                for hisi in connectDevice[gettoken].rawdata_history:
                    hisi = json.loads(hisi)
                    history_list.append(hisi)
                    for item in objects.deviceCalc[connectDevice[gettoken].type]:
                        if item not in average_history:
                            average_history[item] = 0
                        average_history[item] += hisi[item]

                for item in objects.deviceCalc[connectDevice[gettoken].type]:
                    average_history[item] /= len(history_list)
                    average_history[item] = round(average_history[item], 2)

                db.updateDeviceHistory(gettoken, average_history)
                connectDevice[gettoken].cache["datacount"] = 0

            if connectDevice[gettoken].cache["needupdate"]:
                connectDevice[gettoken].cache["needupdate"] = False
                return "UPD"

            return str(connectDevice[gettoken].status)

@app.route("/api/getdevice", methods=["POST"])
def getdevice():
    gettoken = request.form.get('token')
    if gettoken == None or len(gettoken) == 0:
        return "error"
    else:
        tempdev = db.getDevice(gettoken)
        if tempdev:
            retdict = {
                "token": str(gettoken),
                "type": str(tempdev.type),
                "lastupdate": str(tempdev.lastupdate),
                "status": str(tempdev.status),
                'setting': tempdev.setting
            }
            return jsonify(retdict)
        else:
            return "error"

@app.route('/api/set', methods=["POST"])
def setsetting():
    gettoken = request.form.get('token')
    device = db.getDevice(gettoken)
    if device == None:
        return "error"
    settinglist = objects.deviceDefaultSetting[device.type].keys()
    getsetting = {}
    for setting in settinglist:
        getrest = request.form.get(setting)
        if getrest != None:
            getsetting[setting] = getrest

    if connectDevice.get(gettoken):
        connectDevice[gettoken].cache["needupdate"] = True

    if db.setDeviceSetting(gettoken, getsetting):
        return "success"
    else:
        return "error"

@app.route('/api/getsetting', methods=["POST"])
def getsetting():
    gettoken = request.form.get('token')
    device = db.getDevice(gettoken)
    if device == None:
        return "error"
    # db.getDeviceSetting
    settinglist = objects.deviceDefaultSetting[device.type].keys()
    getsetting = {}
    for setting in settinglist:
        getsetting[setting] = device.setting.get(setting)

    return jsonify(getsetting)

@app.route('/api/regline', methods=["POST"])
def line_send():
    user_mid = request.form.get('user_mid')
    msg = request.form.get('msg')
    device_token = request.form.get('device_token')
    print(user_mid, msg, device_token)

    linenotify.send_message_to_friend(user_mid, msg)
    db.regLine(device_token, user_mid)

    return "ok"

@app.route('/api/unregline', methods=["POST"])
def line_unreg():
    device_token = request.form.get('device_token')
    db.unregLine(device_token)

    return "ok"

@app.route('/api/gethistory', methods=["POST"])
def getHistory():
    gettoken = request.form.get('token')
    start_date = request.form.get(
        'startdate')
    end_date = request.form.get(
        'enddate')
    if gettoken == None or start_date == None or end_date == None:
        return "error"
    else:
        device = db.getDevice(gettoken)
        if device == None:
            return "error"
        try:
            start_date = int(start_date)
            end_date = int(end_date)
            print(start_date,end_date)

        except:
            return "error"

        # to datetime
        start_time = datetime.fromtimestamp(start_date)
        end_time = datetime.fromtimestamp(end_date)
        end_time = end_time + timedelta(days = 1)
        start_time.replace(hour=0, minute=0, second=0)
        end_time.replace(hour=23, minute=59, second=59)
        time_range = (end_time - start_time).days

        # to stamp
        start_date_int = int(start_time.timestamp())
        end_date_int = int(end_time.timestamp())

        # 計算時間間隔數量
        if time_range <= 5:
            interval_size_seconds = 3600 * time_range  # 1小時 * 天數
        else:
            interval_size_seconds = int((end_date_int-start_date_int) / (24+abs(8 * (time_range - 5))))

        history = db.getHistoryInRange(gettoken, start_date_int, end_date_int)
        interval_averages = util.calculate_averages_in_intervals(
            history, interval_size_seconds, start_time, end_time)

        return jsonify({"history": interval_averages})

@app.route('/api')
def indexapi():
    return 'alive'

def updateDeviceStatus():
    for devicetoken in list(connectDevice):
        if connectDevice[devicetoken].istimeout():
            print('device: %s is timeout' % devicetoken)
            db.updateDeviceLogs(
                devicetoken, 0,  connectDevice[devicetoken].status, "Connect Lost")
            connectDevice.pop(devicetoken)

    for reqtokenid in list(reqtoken):
        if objects.getNowTime() - reqtoken[reqtokenid][1] > 60:
            print('reqtoken: %s is timeout' % reqtokenid)
            del reqtoken[reqtokenid]

def main():
    rt = objects.RepeatedTimer(5, updateDeviceStatus)
    if __name__ == "__main__":
        try:
            rt.start()
            app.run("0.0.0.0", port=5000, debug=True)
        finally:
            rt.stop()
            print("exit")
            exit()

if __name__ == "__main__":
    main()


# imports
from pyautogui import *
import time

# sounds

def treble1(wait, qtd):
	for times in range(0, qtd):
		time.sleep(wait)
		hotkey('s', 'f', 'j')

def treble2(wait, qtd):
	for times in range(0, qtd):
		time.sleep(wait)
		hotkey('a', 'f', 'j')

def treble3(wait, qtd):
	for times in range(0, qtd):
		time.sleep(wait)
		hotkey('a', 'f', 'h')

def bass1(qtd):
	for times in range(0, qtd):
		hotkey('6', 'e')

def bass2(qtd):
	for times in range(0, qtd):
		hotkey('7', 'r')

def bass3(qtd):
	for times in range(0, qtd):
		hotkey("3", "0")

# rythms

def main_rythm(reps):
	for i in range(0, reps):
		treble1(0.2, 8)
		treble2(0.2, 3)
		treble3(0.2, 5)

def main_bass1(reps):
	for i in range(0, reps):
		bass1(1)
		time.sleep(2)
		bass2(1)
		time.sleep(0.5)
		bass3(1)
		time.sleep(2)
		bass3(1)
		time.sleep(0.5)

# run

for s in range(0, 16):
	time.sleep(1)
	print(s)

main_bass1(2)
main_rythm(10)


import cv2
import numpy as np
import torch
from RT.models.utils import blob
from RT.models.torch_utils import det_postprocess
from RT.models.cudart_api import TRTEngine
from RT.models import EngineBuilder
import streamlit as st
import tempfile
from PIL import Image

class Deployment:
    def __init__(self):
        self.model = "models/yolov8n.engine"
        self.colors = [(255,0,0),(0,0,255),(0,0,0)]

    def ImageBox(self, image):

        new_shape=(640, 640)
        width, height, channel = image.shape

        ratio = min(new_shape[0] / width, new_shape[1] / height)
        new_unpad = int(round(height * ratio)), int(round(width * ratio))
        dw, dh = (new_shape[0] - new_unpad[0])/2, (new_shape[1] - new_unpad[1])/2

        if (height, width) != new_unpad:
            image = cv2.resize(image, new_unpad, interpolation=cv2.INTER_LINEAR)

        top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
        left, right = int(round(dw - 0.1)), int(round(dw + 0.1))

        image = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT, value = self.colors[-1])

        return image, ratio, (dw, dh)

    def face_detection_for_image_with_engine(self, image):

        model = TRTEngine(self.model)

        img, ratio, dwdh = self.ImageBox(image)
        tensor = blob(img, return_seg=False)
        tensor = torch.asarray(tensor)

        dwdh = np.array(dwdh * 2, dtype=np.float32)

        results = model(tensor)

        bboxes, scores, labels = det_postprocess(results)
        bboxes = (bboxes-dwdh)/ratio

        for (bbox, score, label) in zip(bboxes, scores, labels):
            bbox = bbox.round().astype(np.int32).tolist()
            cv2.rectangle(image, (bbox[0],bbox[1]) , (bbox[2],bbox[3]) , self.colors[1], 2)

        return image

def run_tensorrt(image, enggine_path):

    deployment = Deployment()

    predicted_image = deployment.face_detection_for_image_with_engine(image)
    return predicted_image

def main():
    DEFAULT_VIDEO_PATH = "/home/hasan/Public/yolo_with_streamlit/data/sample_videos/sample.mp4"

# Create a video file uploader
    st.header("Upload a video for inference")
    uploaded_file = st.file_uploader("Choose a video...", type=["mp4", "avi", "mov"])

    # Create a radio button for selecting between default video and uploaded video
    video_selection = st.radio(
        "Select video for inference:",
        ("Use default video", "Use uploaded video")
    )

    # If the user chooses to use the default video
    if video_selection == "Use default video":
        video_path = DEFAULT_VIDEO_PATH

    # If the user chooses to use the uploaded video
    elif video_selection == "Use uploaded video" and uploaded_file is not None:
        tfile = tempfile.NamedTemporaryFile(delete=False)
        tfile.write(uploaded_file.read())
        video_path = tfile.name

    # If there's a video to process, do the inference
    if video_path is not None:
        # Load the video with cv2
        cap = cv2.VideoCapture(video_path)
        outputing = st.empty()
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break

            # Run the inference
            output = run_tensorrt(image=frame, enggine_path='models/yolov8n.engine')

            # Convert the output to an image that can be displayed
            output_image = Image.fromarray(cv2.cvtColor(output, cv2.COLOR_BGR2RGB))

            # Display the image
            outputing.image(output_image)

        cap.release()
    else:
        st.write("Please upload a video file or choose to use the default video.")

if __name__ == "__main__":
    while True:
        try:
            main()
        except:
            continue


from cement import App, TestApp, init_defaults
from cement.core.exc import CaughtSignal
from .core.exc import ChordyApplicationError
from .controllers.base import Base

# configuration defaults
CONFIG = init_defaults('chordy', 'log.logging')
CONFIG['chordy']['foo'] = 'barh'
CONFIG['log.logging']['level'] = 'ERROR'

class ChordyApplication(App):
    """Chordy Application primary application."""

    class Meta:
        label = 'chordy'

        # configuration defaults
        config_defaults = CONFIG

        # call sys.exit() on close
        exit_on_close = True

        # load additional framework extensions
        extensions = [
            'yaml',
            'colorlog',
            'jinja2',
            'tabulate'
        ]

        # configuration handler
        config_handler = 'yaml'

        # configuration file suffix
        config_file_suffix = '.yml'

        # set the log handler
        log_handler = 'colorlog'

        # set the output handler
        output_handler = 'tabulate'

        # register handlers
        handlers = [
            Base
        ]

class ChordyApplicationTest(TestApp,ChordyApplication):
    """A sub-class of ChordyApplication that is better suited for testing."""

    class Meta:
        label = 'chordy'

def main():
    with ChordyApplication() as app:
        try:
            app.args.add_argument('--ip', required=True, action='store', dest='ip', help='Server IP address')
            app.args.add_argument('-p', '--port', required=True, action='store', type=int, dest='port', help='Server port number')
            app.run()

        except AssertionError as e:
            print('AssertionError > %s' % e.args[0])
            app.exit_code = 1

            if app.debug is True:
                import traceback
                traceback.print_exc()

        except ChordyApplicationError as e:
            print('ChordyApplicationError > %s' % e.args[0])
            app.exit_code = 1

            if app.debug is True:
                import traceback
                traceback.print_exc()

        except CaughtSignal as e:
            # Default Cement signals are SIGINT and SIGTERM, exit 0 (non-error)
            print('\n%s' % e)
            app.exit_code = 0

if __name__ == '__main__':
    main()


def muestraLista(lista):
    for i in range(len(lista)):
        print("[%s]"%lista[i],end="")
    print()
    return

def muestraMatriz(matriz):
    for i in range(len(matriz)):
        for j in range(len(matriz[i])):
            print("[%s]"%matriz[i][j],end="")
        print()
    print()
    return

#IMPORTS
import random

#preguntaremos en español
palabras=[['sombrero','hat'],['sol','sun'],['tierra','land'],['country','pais']]
possibleTranslations=[
    ['hat','sun','too',0],
    ['hair','hearth','sun',0],
    ['brash','fat','land',0],
    ['pais','patria','ciudad',0]
    ]
vidas=5
puntaje=0
string="""Bienvenido a tu juego don adivinador,
Un juego en el que podras divertirte adivinando
La opcion correcta.
Numero de vidas=5
"""
print(string)
while  len(palabras)>0 and vidas>0:
    ran=random.randint(0,len(palabras)-1)#randomico desde el 0 hasta el numero de palabras
    print("\nCual es la traduccion para: %s?"%palabras[ran][0])
    print("1. %s     2. %s       3. %s"%(possibleTranslations[ran][0],possibleTranslations[ran][1],possibleTranslations[ran][2]))
    option=input("Escribe la palabra correcta: ")
    if palabras[ran][1]==option:
        puntaje+=1
        print("SI, adivinaste!!!")
    else:
        vidas-=1
        print("NO, fallaste :-( \a")
    possibleTranslations[ran][3]+=1
    if possibleTranslations[ran][3]>=3:
        del palabras[ran]
        del possibleTranslations[ran]

print("\nFin del juego :-(")
print("Numero de vidas: %d/5"%vidas)
print("Tu puntaje: %d"%puntaje)
print("Palabras sin completar: %d"%len(palabras))


# global
import ivy
from ivy.func_wrapper import with_supported_dtypes
from ivy.functional.frontends.paddle.func_wrapper import (
    to_ivy_arrays_and_back,
)

@with_supported_dtypes(
    {"2.5.1 and below": ("complex64", "complex128")},
    "paddle",
)
@to_ivy_arrays_and_back
def fft(x, n=None, axis=-1.0, norm="backward", name=None):
    ret = ivy.fft(ivy.astype(x, "complex128"), axis, norm=norm, n=n)
    return ivy.astype(ret, x.dtype)

@with_supported_dtypes(
    {
        "2.5.1 and below": (
            "int32",
            "int64",
            "float32",
            "float64",
        )
    },
    "paddle",
)
@to_ivy_arrays_and_back
def fftfreq(n, d=1.0, dtype=None, name=None):
    if d * n == 0:
        raise ValueError("d or n should not be 0.")

    if dtype is None:
        dtype = ivy.default_dtype()
    val = 1.0 / (n * d)
    pos_max = (n + 1) // 2
    neg_max = n // 2
    indices = ivy.arange(-neg_max, pos_max, dtype=dtype)
    indices = ivy.roll(indices, -neg_max)
    return ivy.multiply(indices, val)

@with_supported_dtypes(
    {
        "2.5.1 and below": (
            "int32",
            "int64",
            "float32",
            "float64",
            "complex64",
            "complex128",
        )
    },
    "paddle",
)
@to_ivy_arrays_and_back
def fftshift(x, axes=None, name=None):
    shape = x.shape

    if axes is None:
        axes = tuple(range(x.ndim))
        shifts = [(dim // 2) for dim in shape]
    elif isinstance(axes, int):
        shifts = shape[axes] // 2
    else:
        shifts = ivy.concat([shape[ax] // 2 for ax in axes])

    roll = ivy.roll(x, shifts, axis=axes)

    return roll

@with_supported_dtypes(
    {"2.5.1 and below": ("complex64", "complex128")},
    "paddle",
)
@to_ivy_arrays_and_back
def hfft(x, n=None, axes=-1, norm="backward", name=None):
    """Compute the FFT of a signal that has Hermitian symmetry, resulting in a real
    spectrum."""
    # Determine the input shape and axis length
    input_shape = x.shape
    input_len = input_shape[axes]

    # Calculate n if not provided
    if n is None:
        n = 2 * (input_len - 1)

    # Perform the FFT along the specified axis
    result = ivy.fft(x, axes, n=n, norm=norm)

    return ivy.real(result)

@with_supported_dtypes(
    {"2.5.1 and below": "complex64"},
    "paddle",
)
@to_ivy_arrays_and_back
def hfft2(x, s=None, axis=(-2, -1), norm="backward"):
    # check if the input tensor x is a hermitian complex
    if not ivy.allclose(ivy.conj(ivy.matrix_transpose(x)), x):
        raise ValueError("Input tensor x must be Hermitian complex.")

    fft_result = ivy.fft2(x, s=s, dim=axis, norm=norm)

    # Depending on the norm, apply scaling and normalization
    if norm == "forward":
        fft_result /= ivy.sqrt(ivy.prod(ivy.shape(fft_result)))
    elif norm == "ortho":
        fft_result /= ivy.sqrt(ivy.prod(ivy.shape(x)))

    return ivy.real(fft_result)  # Return the real part of the result

@with_supported_dtypes(
    {"2.5.1 and below": ("complex64", "complex128")},
    "paddle",
)
@to_ivy_arrays_and_back
def ifft(x, n=None, axis=-1.0, norm="backward", name=None):
    ret = ivy.ifft(ivy.astype(x, "complex128"), axis, norm=norm, n=n)
    return ivy.astype(ret, x.dtype)

@with_supported_dtypes(
    {"2.5.1 and below": ("complex64", "complex128")},
    "paddle",
)
@to_ivy_arrays_and_back
def ifftn(x, s=None, axes=None, norm="backward", name=None):
    ret = ivy.ifftn(ivy.astype(x, "complex128"), s=s, axes=axes, norm=norm)
    return ivy.astype(ret, x.dtype)

@with_supported_dtypes(
    {
        "2.5.1 and below": (
            "int32",
            "int64",
            "float32",
            "float64",
        )
    },
    "paddle",
)
@to_ivy_arrays_and_back
def ifftshift(x, axes=None, name=None):
    shape = x.shape

    if axes is None:
        axes = tuple(range(x.ndim))
        shifts = [-(dim // 2) for dim in shape]
    elif isinstance(axes, int):
        shifts = -(shape[axes] // 2)
    else:
        shifts = ivy.concat([-shape[ax] // 2 for ax in axes])

    roll = ivy.roll(x, shifts, axis=axes)

    return roll

@with_supported_dtypes(
    {
        "2.5.1 and below": (
            "int32",
            "int64",
            "float32",
            "float64",
        )
    },
    "paddle",
)
@to_ivy_arrays_and_back
def ihfft2(x, s=None, axes=(-2, -1), norm="backward", name=None):
    # check if the input array is two-dimensional and real
    if len(ivy.array(x).shape) != 2 or ivy.is_complex_dtype(x):
        raise ValueError("input must be a two-dimensional real array")

    # cast the input to the same float64 type so that there are no backend issues
    x_ = ivy.astype(x, ivy.float64)

    ihfft2_result = 0
    # Compute the complex conjugate of the 2-dimensional discrete Fourier Transform
    if norm == "backward":
        ihfft2_result = ivy.conj(ivy.rfftn(x_, s=s, axes=axes, norm="forward"))
    if norm == "forward":
        ihfft2_result = ivy.conj(ivy.rfftn(x_, s=s, axes=axes, norm="backward"))
    if norm == "ortho":
        ihfft2_result = ivy.conj(ivy.rfftn(x_, s=s, axes=axes, norm="ortho"))

    if x.dtype == ivy.float32 or x.dtype == ivy.int32 or x.dtype == ivy.int64:
        return ivy.astype(ihfft2_result, ivy.complex64)
    if x.dtype == ivy.float64:
        return ivy.astype(ihfft2_result, ivy.complex128)

@with_supported_dtypes(
    {"2.5.1 and below": ("complex64", "complex128")},
    "paddle",
)
@to_ivy_arrays_and_back
def irfft(x, n=None, axis=-1.0, norm="backward", name=None):
    if n is None:
        n = 2 * (x.shape[axis] - 1)

    pos_freq_terms = ivy.take_along_axis(x, range(n // 2 + 1), axis)
    neg_freq_terms = ivy.conj(pos_freq_terms[1:-1][::-1])
    combined_freq_terms = ivy.concat((pos_freq_terms, neg_freq_terms), axis=axis)
    time_domain = ivy.ifft(combined_freq_terms, axis, norm=norm, n=n)
    if ivy.isreal(x):
        time_domain = ivy.real(time_domain)
    return time_domain

@with_supported_dtypes(
    {
        "2.5.1 and below": (
            "int32",
            "int64",
            "float16",
            "float32",
            "float64",
            "complex64",
            "complex128",
        )
    },
    "paddle",
)
@to_ivy_arrays_and_back
def irfft2(x, s=None, axes=(-2, -1), norm="backward"):
    # Handle values if None
    if s is None:
        s = x.shape
    if axes is None:
        axes = (-2, -1)

    # Calculate the normalization factor 'n' based on the shape 's'
    n = ivy.prod(ivy.array(s))

    result = ivy.ifftn(x, dim=axes[0], norm=norm)

    # Normalize the result based on the 'norm' parameter
    if norm == "backward":
        result /= n
    elif norm == "forward":
        result *= n
    elif norm == "ortho":
        result /= ivy.sqrt(n)
    return result

@with_supported_dtypes(
    {"2.5.1 and below": ("complex64", "complex128")},
    "paddle",
)
@to_ivy_arrays_and_back
def irfftn(x, s=None, axes=None, norm="backward", name=None):
    x = ivy.array(x)

    if axes is None:
        axes = list(range(len(x.shape)))

    include_last_axis = len(x.shape) - 1 in axes

    if s is None:
        s = [
            x.shape[axis] if axis != (len(x.shape) - 1) else 2 * (x.shape[axis] - 1)
            for axis in axes
        ]

    real_result = x
    remaining_axes = [axis for axis in axes if axis != (len(x.shape) - 1)]

    if remaining_axes:
        real_result = ivy.ifftn(
            x,
            s=[s[axes.index(axis)] for axis in remaining_axes],
            axes=remaining_axes,
            norm=norm,
        )

    if include_last_axis:
        axis = len(x.shape) - 1
        size = s[axes.index(axis)]
        freq_domain = ivy.moveaxis(real_result, axis, -1)
        slices = [slice(None)] * ivy.get_num_dims(freq_domain)
        slices[-1] = slice(0, size // 2 + 1)
        pos_freq_terms = freq_domain[tuple(slices)]
        slices[-1] = slice(1, -1)
        neg_freq_terms = ivy.conj(pos_freq_terms[tuple(slices)][..., ::-1])
        combined_freq_terms = ivy.concat((pos_freq_terms, neg_freq_terms), axis=-1)
        real_result = ivy.ifftn(combined_freq_terms, s=[size], axes=[-1], norm=norm)
        real_result = ivy.moveaxis(real_result, -1, axis)

    if ivy.is_complex_dtype(x.dtype):
        output_dtype = "float32" if x.dtype == "complex64" else "float64"
    else:
        output_dtype = "float32"

    result_t = ivy.astype(real_result, output_dtype)
    return result_t

@with_supported_dtypes({"2.5.1 and below": ("float32", "float64")}, "paddle")
@to_ivy_arrays_and_back
def rfft(x, n=None, axis=-1, norm="backward", name=None):
    return ivy.dft(x, axis=axis, inverse=False, onesided=True, dft_length=n, norm=norm)

@to_ivy_arrays_and_back
def rfftfreq(n, d=1.0, dtype=None, name=None):
    dtype = ivy.default_dtype()
    val = 1.0 / (n * d)
    pos_max = n // 2 + 1
    indices = ivy.arange(0, pos_max, dtype=dtype)
    return indices * val


r"""
Set of homomorphisms between two affine schemes

For schemes `X` and `Y`, this module implements the set of morphisms
`Hom(X,Y)`. This is done by :class:`SchemeHomset_generic`.

As a special case, the Hom-sets can also represent the points of a
scheme. Recall that the `K`-rational points of a scheme `X` over `k`
can be identified with the set of morphisms `Spec(K) \to X`. In Sage
the rational points are implemented by such scheme morphisms. This is
done by :class:`SchemeHomset_points` and its subclasses.

.. note::

    You should not create the Hom-sets manually. Instead, use the
    :meth:`~sage.structure.parent.Hom` method that is inherited by all
    schemes.

AUTHORS:

- William Stein (2006): initial version.
"""

#*****************************************************************************
#       Copyright (C) 2006 William Stein <wstein@gmail.com>
#
#  Distributed under the terms of the GNU General Public License (GPL)
#  as published by the Free Software Foundation; either version 2 of
#  the License, or (at your option) any later version.
#                  http://www.gnu.org/licenses/
#*****************************************************************************

from sage.rings.all import ZZ
from sage.rings.rational_field import is_RationalField
from sage.categories.fields import Fields
from sage.categories.number_fields import NumberFields
from sage.rings.finite_rings.finite_field_constructor import is_FiniteField
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
import sage.schemes.generic.homset

#*******************************************************************
# Affine varieties
#*******************************************************************
class SchemeHomset_points_spec(sage.schemes.generic.homset.SchemeHomset_generic):
    """
    Set of rational points of an affine variety.

    INPUT:

    See :class:`SchemeHomset_generic`.

    EXAMPLES::

        sage: from sage.schemes.affine.affine_homset import SchemeHomset_points_spec
        sage: SchemeHomset_points_spec(Spec(QQ), Spec(QQ))
        Set of rational points of Spectrum of Rational Field
    """

    def _element_constructor_(self, *args, **kwds):
        """
        The element constructor.

        EXAMPLES::

            sage: X = Spec(QQ)
            sage: ring_hom = QQ.hom((1,), QQ);  ring_hom
            Ring endomorphism of Rational Field
              Defn: 1 |--> 1
            sage: H = X.Hom(X)
            sage: H(ring_hom)
            Affine Scheme endomorphism of Spectrum of Rational Field
              Defn: Ring endomorphism of Rational Field
                      Defn: 1 |--> 1

        TESTS::

            sage: H._element_constructor_(ring_hom)
            Affine Scheme endomorphism of Spectrum of Rational Field
              Defn: Ring endomorphism of Rational Field
                      Defn: 1 |--> 1
        """
        return sage.schemes.generic.homset.SchemeHomset_generic._element_constructor_(self, *args, **kwds)

    def _repr_(self):
        """
        Return a string representation of a homset.

        OUTPUT: A string.

        EXAMPLES::

            sage: from sage.schemes.affine.affine_homset import SchemeHomset_points_spec
            sage: S = SchemeHomset_points_spec(Spec(QQ), Spec(QQ))
            sage: S._repr_()
            'Set of rational points of Spectrum of Rational Field'
        """
        return 'Set of rational points of '+str(self.codomain())

#*******************************************************************
# Affine varieties
#*******************************************************************
class SchemeHomset_points_affine(sage.schemes.generic.homset.SchemeHomset_points):
    """
    Set of rational points of an affine variety.

    INPUT:

    See :class:`SchemeHomset_generic`.

    EXAMPLES::

        sage: from sage.schemes.affine.affine_homset import SchemeHomset_points_affine
        sage: SchemeHomset_points_affine(Spec(QQ), AffineSpace(ZZ,2))
        Set of rational points of Affine Space of dimension 2 over Rational Field
    """

    def points(self, **kwds):
        r"""
        Return some or all rational points of an affine scheme.

        Over a finite field, all points are returned. Over an infinite field, all points satisfying the bound
        are returned. For a zero-dimensional subscheme, all points are returned regardless of whether the field
        is infinite or not.

        For number fields, this uses the
        Doyle-Krumm algorithm 4 (algorithm 5 for imaginary quadratic) for
        computing algebraic numbers up to a given height [Doyle-Krumm]_.

        The algorithm requires floating point arithmetic, so the user is
        allowed to specify the precision for such calculations.
        Additionally, due to floating point issues, points
        slightly larger than the bound may be returned. This can be controlled
        by lowering the tolerance.

        INPUT:

        - ``bound`` - a real number

        - ``tolerance`` - a rational number in (0,1] used in doyle-krumm algorithm-4

        - ``precision`` - the precision to use for computing the elements of bounded height of number fields.

        OUTPUT:

        - a list of rational points of a affine scheme

        EXAMPLES: The bug reported at #11526 is fixed::

            sage: A2 = AffineSpace(ZZ, 2)
            sage: F = GF(3)
            sage: A2(F).points()
            [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

            sage: R = ZZ
            sage: A.<x,y> = R[]
            sage: I = A.ideal(x^2-y^2-1)
            sage: V = AffineSpace(R, 2)
            sage: X = V.subscheme(I)
            sage: M = X(R)
            sage: M.points(bound=1)
            [(-1, 0), (1, 0)]

        ::

            sage: u = QQ['u'].0
            sage: K.<v> = NumberField(u^2 + 3)
            sage: A.<x,y> = AffineSpace(K, 2)
            sage: len(A(K).points(bound=2))
            1849

        ::

            sage: A.<x,y> = AffineSpace(QQ, 2)
            sage: E = A.subscheme([x^2 + y^2 - 1, y^2 - x^3 + x^2 + x - 1])
            sage: E(A.base_ring()).points()
            [(-1, 0), (0, -1), (0, 1), (1, 0)]
        """
        B = kwds.pop('bound', 0)
        tol = kwds.pop('tolerance', 1e-2)
        prec = kwds.pop('precision', 53)

        X = self.codomain()

        from sage.schemes.affine.affine_space import is_AffineSpace
        if not is_AffineSpace(X) and X.base_ring() in Fields():
            # Then X must be a subscheme
            dim_ideal = X.defining_ideal().dimension()
            if dim_ideal < 0: # no points
                return []
            if dim_ideal == 0: # if X zero-dimensional
                N = len(X.ambient_space().gens())
                S = X.defining_polynomials()[0].parent()
                R = PolynomialRing(S.base_ring(), 's', N, order='lex')
                phi = S.hom(R.gens(),R)
                J = R.ideal([phi(t) for t in X.defining_polynomials()])
                D = J.variety()
                points = []
                for d in D:
                    P = [d[t] for t in R.gens()]
                    points.append(X(P))
                points.sort()
                return points
        R = self.value_ring()
        if is_RationalField(R) or R == ZZ:
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified"%B)
            from sage.schemes.affine.affine_rational_point import enum_affine_rational_field
            return enum_affine_rational_field(self,B)
        if R in NumberFields():
            if not B > 0:
                raise TypeError("a positive bound B (= %s) must be specified"%B)
            from sage.schemes.affine.affine_rational_point import enum_affine_number_field
            return enum_affine_number_field(self, bound=B, tolerance=tol, precision=prec)
        elif is_FiniteField(R):
            from sage.schemes.affine.affine_rational_point import enum_affine_finite_field
            return enum_affine_finite_field(self)
        else:
            raise TypeError("unable to enumerate points over %s"%R)


# Script to test the Bag of words representation in Parser.py using a Multnomial Bayes classifier

import Parser
from sklearn.naive_bayes import MultinomialNB
import numpy

train_data = Parser.TRAIN_SPARSE
train_targets = Parser.TRAIN_TARGET

test_data = Parser.TEST_SPARSE
test_targets = Parser.TEST_TARGET

Amap = Parser.author_target_map
vect = Parser.count_vect

clf = MultinomialNB()
clf.fit(train_data, train_targets)

train_predictions = clf.predict(train_data)
test_predictions = clf.predict(test_data)

print("Beat accuracy of MNB on Training Data",numpy.mean(train_predictions == train_targets))
print("Beta accuracy of MNB on Test Data",numpy.mean(test_predictions == test_targets))


from __future__ import annotations

from NodeGraphQt import BaseNode
from taskprocessor.ui import (ActionDataType, ActionDefinition, ActionRuntime)
from taskprocessor.ui.nodes import (NODE_COLORS, NODE_IO_TYPE_COLORS)
from taskprocessor.ui.widgets import IntWidget, FloatWidget, PathWidget

def node_prototype_constructor(self):
    super(self.__class__, self).__init__()
    self.action: ActionRuntime | None = None

class BaseNodeTP(BaseNode):
    __identifier__ = 'taskprocessor'

    NODE_NAME = 'Base Node TP'

    ACTION_NAME = 'base_node_tp'

    def __init__(self):
        super(BaseNodeTP, self).__init__()
        self.action: ActionRuntime | None = None
        self.is_initialized: bool = False

    @staticmethod
    def create_node_class_from_def(action_def: ActionDefinition):
        class_name = action_def.name.title().strip().replace('_', '')
        node_class = type(class_name, (BaseNodeTP,), {
            "__init__": node_prototype_constructor,

            "NODE_NAME": action_def.label,
            "ACTION_NAME": action_def.name
        })
        return node_class

    def initialize(self, action: ActionRuntime):
        self.action = action

        self.set_name(str(action.id).title().replace('_', ' '))

        node_color = NODE_COLORS[action.definition.get_main_engine()]
        self.set_color(node_color[0], node_color[1], node_color[2])

        # Add input ports
        for (index, i) in enumerate(action.definition.inputs):
            name = str(action.get_input_id(index))
            self.add_input(name=name, color=NODE_IO_TYPE_COLORS[i.type], display_name=False)

        # Add output ports
        for (index, o) in enumerate(action.definition.outputs):
            name = str(action.get_output_id(index))
            self.add_output(name=name, color=NODE_IO_TYPE_COLORS[o.type], display_name=False)

        # Add widgets. (This is done in the end to avoid layout alignment issues)
        for (index, i) in enumerate(action.definition.inputs):
            name = str(action.get_input_id(index))
            if i.type == ActionDataType.String:
                self.add_text_input(name, i.label, i.value, tab="widgets")
            elif i.type == ActionDataType.Path:
                path_widget = PathWidget(parent=self.view, name=name, label=i.label, text=i.value)
                self.add_custom_widget(path_widget, tab="widgets")
            elif i.type == ActionDataType.Integer:
                int_widget = IntWidget(parent=self.view, name=name, label=i.label, value=i.value)
                self.add_custom_widget(int_widget, tab="widgets")
            elif i.type == ActionDataType.Float:
                float_widget = FloatWidget(parent=self.view, name=name, label=i.label, value=i.value)
                self.add_custom_widget(float_widget, tab="widgets")
            elif i.type == ActionDataType.Boolean:
                self.add_checkbox(name, i.label, i.value, tab="widgets")

        self.draw()
        self.is_initialized = True


from typing import List
from fetchai.ledger.api import LedgerApi
from fetchai.ledger.contract import Contract
from fetchai.ledger.crypto import Entity, Address

HOST = "ledger_node"

CONTRACT_TEXT = """
@init
function setup(owner : Address)
  var rentalStarting = State<UInt64>("startTimeStamp");

  var price = State<UInt64>("pricePerMin");
  var owner_balance = State<UInt64>(owner);
  owner_balance.set(1000000u64);
  var depositeAmount = State<UInt64>("deposite");
  depositeAmount.set(0u64);
endfunction
@action
function transfer(from: Address, to: Address, amount: UInt64)
  // define the accounts
  var from_account = State<UInt64>(from);
  var to_account = State<UInt64>(to); // if new sets to 0u
  // Check if the sender has enough balance to proceed
  if (from_account.get() >= amount)
    // update the account balances
    from_account.set(from_account.get() - amount);
    to_account.set(to_account.get(0u64) + amount);
  endif
endfunction
@action
function setEscrew(from: Address, amount: UInt64, inputRentalStarting: UInt64, inputPrice: UInt64)
  // define the accounts
  var price = State<UInt64>("pricePerMin");
  price.set(inputPrice);

  var rentalStarting = State<UInt64>("startTimeStamp");
  rentalStarting.set(inputRentalStarting);
  var from_account = State<UInt64>(from);
  var escrew_holdings = State<UInt64>("escrew");
  // Check if the sender has enough balance to proceed
  if (from_account.get() >= amount)
    // update the account balances
    from_account.set(from_account.get() - amount);
    escrew_holdings.set(escrew_holdings.get(0u64) + amount);
  endif
endfunction
@action
function releaseEscrew(to: Address, rentalEnds: UInt64)
  //another parameter
  // define the accounts
  var to_account = State<UInt64>(to);
  var escrew_holdings = State<UInt64>("escrew");
  // Check if the sender has enough balance to proceed
  var amount: UInt64;
  var finAmt: UInt64;
  amount = escrew_holdings.get();

  var price = State<UInt64>("pricePerMin");
  var rentalStarting = State<UInt64>("startTimeStamp");
  var totalMinutes = rentalEnds-rentalStarting.get();
  //finAmt = to_account.get(0u64) + amount;
  to_account.set(finAmt);

  escrew_holdings.set(escrew_holdings.get(0u64) - amount);
endfunction
@query

function balance(address: Address) : UInt64
  var account = State<UInt64>(address);
  return account.get(0u64);
endfunction
"""

SYNERGYSTIC = """
@problem
function createProblem(data : Array<StructuredData>) : Array<Int32>
  var myArray = Array<Int32>(data.count());
  for (i in 0:data.count() - 1)
    myArray[i] = data[i].getInt32("value");
  endfor
  return myArray;
endfunction
@objective
function evaluateWork(problem :  Array<Int32>, solution : Int32 ) : Int64
  return toInt64(0);
endfunction
@work
function doWork(problem : Array<Int32>, nonce : UInt256) :  Int32
  var result = 0;
  for (i in 0:4)
    result += (abs(problem[i]) - abs(problem[i+5]));
  endfor
  return result;
endfunction
@clear
function applyWork(problem : Int32, solution : Int32)
  var result = State<Int32>("solution");
  result.set(solution);
endfunction
"""

def print_address_balances(api: LedgerApi,
                           contract: Contract,
                           addresses: List[Address]):
    for idx, address in enumerate(addresses):
        continue
        print('Address{}: {:<6d} bFET {:<10d} TOK'.format(idx,
                                                          api.tokens.balance(address),
                                                          contract.query(api,
                                                                         'balance',
                                                                         address=Address(address))))

def submitSynergy(entity, values):
    api = LedgerApi(HOST, 8100)
    synergy_contract = SynergeticContract(SYNERGYSTIC)
    print(synergy_contract.digest)

    api.sync(api.contracts.create(entity, synergy_contract, 4096))

    api.sync([api.synergetic.submit_data(entity, synergy_contract.digest, value=value) for value in values])

    return synergy_contract

def generateEntity():
    print('Creating private key...')

    # create our first private key pair
    entity1 = Entity()

    # save the private key to disk
#    with open('private.key', 'w') as private_key_file:
#         entity1.dump(private_key_file)

    print('Creating private key...complete')

    # build the ledger API
    api = LedgerApi(HOST, 8100)

    print('Creating initial balance...')

    # create wealth so that we have the funds to be able to create contracts on the network
    api.sync(api.tokens.wealth(entity1, 100000))

    print('Creating initial balance...complete')
    return entity1

def deployContract(entity):
    api = LedgerApi(HOST, 8100)

    # create the smart contract
    contract = Contract(CONTRACT_TEXT)

    print('Deploying contract...')

    # deploy the contract to the network
    api.sync(api.contracts.create(entity, contract, 6000))

    print('Deploying contract...complete')

    return contract

def setEscrew(entity, contract, amount):
    api = LedgerApi(HOST, 8100)
    fet_tx_fee = 40
    print('-- BEFORE --')
    print_address_balances(api, contract, [entity])
    api.sync(contract.action(api, 'setEscrew', fet_tx_fee,
                              [entity], Address(entity),
                              amount))
    print('-- AFTER --')
    print_address_balances(api, contract, [entity])

def releaseEscrew(entity1, contract, entity2):
    api = LedgerApi(HOST, 8100)
    fet_tx_fee = 40
    api.sync(contract.action(api, 'releaseEscrew', fet_tx_fee,
                             [entity1], entity2,
                             ))
    print("Escrew Released.")
    # print_address_balances(api, contract,[entity1, entity2])

if __name__ == "__main__":
    ent = generateEntity()
    deployContract(ent)


"""
Unit tests for the 'get_data' function.
"""

import unittest

from yahdlc import FRAME_DATA, FCSError, MessageError, frame_data, get_data

class TestGetData(unittest.TestCase):
    """
    Unit tests for the 'get_data' function.
    """

    def test_get_data_invalid_inputs(self):
        """
        Call "get_data" with invalid inputs.
        """

        with self.assertRaises(TypeError):
            get_data(12)
        with self.assertRaises(MessageError):
            get_data("")
        with self.assertRaises(MessageError):
            get_data("test")

    def test_get_data_corrupted_frame(self):
        """
        Call "get_data" with a corrupted frame as input.
        """

        data = bytearray(frame_data("test", FRAME_DATA, 0))
        data[7] ^= 0x01
        data = bytes(data)

        with self.assertRaises(FCSError):
            try:
                get_data(data)
            except FCSError as err:
                self.assertEqual(err.args[0], 0)
                raise

        data = bytearray(frame_data("test", FRAME_DATA, 2))
        data[7] ^= 0x01
        data = bytes(data)

        with self.assertRaises(FCSError):
            try:
                get_data(data)
            except FCSError as err:
                self.assertEqual(err.args[0], 2)
                raise


from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import ProductSerializer,RateSerializer
from .models import Product, Rate
from rest_framework.permissions import IsAuthenticated
from django.db.models import Avg, Count

class ProductsView(APIView):

    permission_classes = [IsAuthenticated,]
    def get(self,request):

        products=Product.objects.all()

        ser_data=ProductSerializer(instance=products, many=True).data
        ser_list=[]
        for i in ser_data:
            ser_list.append(dict(i))

        for i in ser_list:
            id=i['id']
            rate=Rate.objects.filter(product=Product.objects.get(id=id) , user=request.user)
            if rate.exists():
                rate=rate.values('ratenum')[0]['ratenum']
                i.update({'you_rate':rate})

        for i in ser_list:
            agrrate = Product.objects.filter(id=i['id']).aggregate(average_rate=Avg('rate__ratenum'),count_rate=Count('rate__ratenum'))

            i.update(agrrate)

        return Response(ser_list)

class ProductDetailView(APIView):

    permission_classes = [IsAuthenticated,]
    def get(self,request,id):
        product=Product.objects.get(id=id)
        ser_data=ProductSerializer(instance=product).data
        agrrate=Product.objects.filter(id=id).aggregate(average_rate=Avg('rate__ratenum'),count_rate=Count('rate__ratenum'))
        rate = Rate.objects.filter(product_id=id, user=request.user)
        ser_data.update(agrrate)
        if rate.exists():
            rate = rate.values('ratenum')[0]['ratenum']
            ser_data.update({'you_rate': rate})
        return Response(ser_data)

class RateView(APIView):

    def post(self,request,id):
        rate = Rate.objects.filter(product_id=id, user=request.user)
        if rate.exists():
            ser_data=RateSerializer(instance=rate,data=request.data, partial=True)
            if ser_data.is_valid():
                rate.ratenum=ser_data.validated_data['ratenum']
                rate.save()
                return Response('your rate to this product updated!')
        else:
            print("this is a test:{ser_data}")

            ser_data=RateSerializer(data=request.data)
            if ser_data.is_valid():
                Rate.objects.create(product=Product.objects.get(id=id) , user=request.user, ratenum=ser_data.validated_data['ratenum'])
                return Response('your rate has been saved!')


def mostFrequentEven(nums) -> int:
    hm = {}
    for x in nums:
        if x % 2 == 0:
            hm[x] = {0}

    for c in nums:
        if c % 2 == 0:
            hm[c] = hm[c] + 1

    for key, value in hm.items():
        print(key, value)

    return 0

list = [3, 2, 4, 3]
mostFrequentEven(list)


# -*- coding: utf-8 -*-
"""
Created on Mon Jun 19 11:09:33 2017

@author: barteld
"""

import tensorflow as tf

from sklearn.datasets import load_boston
from sklearn.preprocessing import scale

total_X, total_Y = load_boston(True)
total_X = scale(total_X)
total_Y = total_Y.reshape(len(total_Y), 1)

X = tf.placeholder(tf.float32, [None, 13])
Y = tf.placeholder(tf.float32, [None, 1])

w = tf.Variable(tf.ones([13, 1]))
b = tf.Variable(tf.zeros([]))

yhat = tf.add(tf.matmul(X, w), b)
loss = tf.reduce_mean(tf.square(yhat - Y))

epochs = 100
learning_rate = 0.01
optimizer = tf.train.GradientDescentOptimizer(
    learning_rate).minimize(loss)

with tf.Session() as sess:
    ## initalize parameters
    sess.run(tf.global_variables_initializer())

    data_dict = {X: total_X, Y: total_Y}
    for i in range(epochs):
        ## run one epoch
        sess.run(optimizer, data_dict)
        ## print result and loss
        print("Epoch " + str(i + 1) + ", Loss: " + str(sess.run(loss, data_dict)))
    #print(str(sess.run(yhat, data_dict)))


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

import pymongo
from .base import wechatBase

class wechatMenu(wechatBase):
    typedict = {
        'supmenu': '父级菜单',
        'click': '点击',
        'view': '链接'
    }

    def create_menu4btn(self, menulist):
        return self.client.menu.create({
            "button": menulist
        })

    def get_menu(self):
        return self.client.menu.get()

    async def menu2db(self, request, menulist, parent=None):
        '''
        将微信服务器下载menu数据 解析至数据库
        :param request: handler 用于获取db操作对象
        :param menulist:
        :param parent:
        :return:
        '''
        for index, menu in enumerate(menulist):
            is_supmenu = (menu['sub_button'] and 'type' not in menu)
            menudb = {
                'name': menu['name'],
                'type': 'supmenu' if is_supmenu else menu['type'],
                'index': index,
                'parent': parent,
                'args': None if is_supmenu else {k: v for k, v in menu.items() if
                                                 k not in ('name', 'type', 'sub_button')}
            }
            menuid = await request.db.wechat_menu.insert(menudb)
            if is_supmenu:
                await self.menu2db(request, menu['sub_button'], parent=str(menuid))

    async def db2menu(self, request, parent=None):
        '''
        将数据库中的数据解析成易于辨析的menu list(本地)
        :param request: handler 用于获取db操作对象
        :param parent:
        :return:
        '''
        menulist = []
        cursor = request.db.wechat_menu.find({'parent': parent})
        cursor.sort([('index', pymongo.ASCENDING)])
        while (await cursor.fetch_next):
            menu = cursor.next_object()
            menu['_id'] = str(menu['_id'])
            if menu['type'] == 'supmenu':
                menu['sub_button'] = await self.db2menu(request, parent=menu['_id'])
            menulist.append(menu)
        return menulist

    async def db2menu4wechat(self, request, menulist=None):
        '''
        将数据库中的数据解析成微信格式的menu list(网络数据)
        :param request: handler 用于获取db操作对象
        :param parent:
        :return:
        '''
        if menulist is None:
            menulist = await self.db2menu(request)
        result = []
        for menu in menulist:
            if menu['type'] == 'supmenu':
                result.append({
                    'name': menu['name'],
                    'sub_button': (await self.db2menu4wechat(request, menulist=menu['sub_button']))
                })
            else:
                menu = {k:v for k, v in menu.items() if k in ('type', 'name', 'args')}
                if menu['args']: menu.update(menu['args'])
                del menu['args']
                result.append(menu)
        return result


#Loading libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import os
from scipy import ndimage
import math
import keras
import ast
import operator as op
import re
from tensorflow.keras.preprocessing.image import ImageDataGenerator

#Suppressing warning
def warn(*args, **kwargs):
    pass
import warnings
warnings.warn = warn

#Global Variable
dict_clean_img = {} #BINARY IMAGE DICTIONAY
dict_img = {} #ORIGINAL IMAGE DICTIONARY

#Keras support channel first (1,28,28) only
keras.backend.set_image_data_format("channels_first")

#loading models
try:
    model = keras.models.load_model('models/DCNN_10AD_sy.h5')
    model_robusta = keras.models.load_model('models/DCNN_10AD_2_sy.h5')
    #Model_Robusta is used when model predicts with lower probability
except:
    print('Model couldnot be loaded')
#%%
def image_resize(image, width = None, height = None, inter = cv2.INTER_LINEAR):
    '''
    image_resize : Function to resize images
    argument:
        image (Matrix)  : image to resize
        width (Integer) : width of the required image
        height (Integer): height of required image
        inter (Method)  : Interpolation/Extrapolation method
    output:
        image (Matrix)  : image resized
    '''
    dim = None
    (h, w) = image.shape[:2]

    # if both the width and height are None, then return the
    # original image
    if width is None and height is None:
        return image

    # check to see if the width is None
    if width is None:
        # calculate the ratio of the height and construct the
        # dimensions
        r = height / float(h)
        dim = (int(w * r), height)

    # otherwise, the height is None
    else:
        # calculate the ratio of the width and construct the
        # dimensions
        r = width / float(w)
        dim = (width, int(h * r))

    # resize the image
    resized = cv2.resize(image, dim, interpolation = inter)

    # return the resized image
    return resized

'''
Evaluate New
'''
# supported operators
operators = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
             ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
             ast.USub: op.neg}

def eval_expr(expr):
    """
    >>> eval_expr('2^6')
    4
    >>> eval_expr('2**6')
    64
    >>> eval_expr('1 + 2*3**(4^5) / (6 + -7)')
    -5.0
    """
    return eval_(ast.parse(expr, mode='eval').body)

def eval_(node):
    if isinstance(node, ast.Num): # <number>
        return node.n
    elif isinstance(node, ast.BinOp): # <left> <operator> <right>
        return operators[type(node.op)](eval_(node.left), eval_(node.right))
    elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1
        return operators[type(node.op)](eval_(node.operand))
    else:
        raise TypeError(node)

'''
Workspace Detection
'''

def sort_contours(cnts, method="left-to-right"):
    '''
    sort_contours : Function to sort contours
    argument:
        cnts (array): image contours
        method(string) : sorting direction
    output:
        cnts(list): sorted contours
        boundingBoxes(list): bounding boxes
    '''
    # initialize the reverse flag and sort index
    reverse = False
    i = 0

    # handle if we need to sort in reverse
    if method == "right-to-left" or method == "bottom-to-top":
        reverse = True

    # handle if we are sorting against the y-coordinate rather than
    # the x-coordinate of the bounding box
    if method == "top-to-bottom" or method == "bottom-to-top":
        i = 1

    # construct the list of bounding boxes and sort them from top to
    # bottom
    boundingBoxes = [cv2.boundingRect(c) for c in cnts]
    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
        key=lambda b:b[1][i], reverse=reverse))

    # return the list of sorted contours and bounding boxes
    return (cnts, boundingBoxes)

def getBestShift(img):
    '''
    getBestShift : Function to calculate centre of mass and get the best shifts
    argument:
        img (array) : gray scale image
    output:
        shiftx, shifty: x,y shift direction
    '''
    cy,cx = ndimage.measurements.center_of_mass(img)
    rows,cols = img.shape
    shiftx = np.round(cols/2.0-cx).astype(int)
    shifty = np.round(rows/2.0-cy).astype(int)

    return shiftx,shifty

def shift(img,sx,sy):
    '''
    Shift : Function to shift the image in given direction
    argument:
        img (array) : gray scale image
        sx, sy      : x, y direction
    output:
        shifted : shifted image
    '''
    rows,cols = img.shape
    M = np.float32([[1,0,sx],[0,1,sy]])
    shifted = cv2.warpAffine(img,M,(cols,rows))
    return shifted

#%%
#Data Generator using tensorflow method
train_datagen = ImageDataGenerator(
    data_format='channels_first',
    zca_whitening = True,
    rotation_range = 0.2)
#%%
def predict(img,x1,y1,x2,y2, proba = False, acc_thresh = 0.60):
    '''
    predict  : Function to predict the character
    argument:
        x1,y1(int,int)    : Top left corner point
        x2,y2(int,int)    : Bottom right corner point
        acc_thresh(0-1)   : Probability threshold for calling model_robusta
        proba(bool)       : If probability values is wanted in return
    output:
        c[index](int) : predicted character

    '''
    gray = img[y1:y2, x1:x2]

    # Steps to remove noises in image due to cropping
    temp = gray.copy()

    kernel_temp = np.ones((3,3), np.uint8)
    temp_tmp = cv2.dilate(temp, kernel_temp, iterations=3)

    # Find the contours -  To check whether its disjoint character or noise
    if(cv2.__version__ == '3.3.1'):
        xyz,contours_tmp,hierarchy = cv2.findContours(temp_tmp,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    else:
        contours_tmp,hierarchy = cv2.findContours(temp_tmp,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

    if(len(contours_tmp) > 1):
        # Find the contours
        if(cv2.__version__ == '3.3.1'):
            xyz,contours,hierarchy = cv2.findContours(gray,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        else:
            contours,hierarchy = cv2.findContours(gray,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        #Creating a mask of only zeros
        mask = np.ones(gray.shape[:2], dtype="uint8") * 0
        #print('Yes')
        # Find the index of the largest contour
        areas = [cv2.contourArea(c) for c in contours]
        max_index = np.argmax(areas)
        cnt=contours[max_index]

        cv2.drawContours(mask, [cnt], -1, 255, -1)
        #Drawing those contours which are noises and then taking bitwise and
        gray = cv2.bitwise_and(temp, temp, mask=mask)

    grayN = process_img (gray, resize_flag = 0)

    classes = model.predict(grayN, batch_size=2)
    ind = np.argmax(classes)
    c = ['0','1','2','3','4','5','6','7','8','9','+','-','*','(',')']

    if(c[ind] == '5' or c[ind] == '6'):
        #print('5/6 got called, Previous:',c[ind])
        grayN_1 = process_img (gray, resize_flag = 1)
        classes = model.predict(grayN_1, batch_size=2)
        ind = np.argmax(classes)
        #print('5/6 got called, Current:',c[ind])
        if (proba == True):
            return classes[0][ind]
        return c[ind]

    if (classes[0][ind] < acc_thresh):
        #print('Poor Handwriting, Augmenting and Testing Prediction, Previous:',c[ind])
        grayN_2 = process_img (gray, resize_flag = 1, preproc = 1)
        imgs = train_datagen.flow(grayN_2, batch_size=10)
        yhats = model_robusta.predict_generator(imgs, steps=10, verbose=0)
        yhats = np.mean(yhats,axis=0)
        classes = yhats[:,None].reshape(1,15)
        ind = np.argmax(classes)
        #print('Poor Handwriting, Augmenting and Testing Prediction, Current:',c[ind])
        if (proba == True):
            return classes[0][ind]
        return c[ind]

    if (proba == True):
        return classes[0][ind]

    return c[ind]
#%%
def process_img (gray, resize_flag = 1, preproc = 0):
    '''
    process_img  : Function to pre process image for prediction
    argument:
        gray (Matrix (np.uint8))  : image of character to be resized and processed
        resize_flag               : method used for resizing image
        preproc (method [bool])   : 0 : No erosion DIlation, 1 : Erosion, Dilation
    output:
        grayS (Matrix (0-1))      : Normalised image of character resized and processed

    '''
    gray = gray.copy()

    #Image Pre Processing
    if (preproc == 0):
        gray = cv2.GaussianBlur(gray,(7,7),0)
    else :
        kernel = np.ones((3,3), np.uint8)
        gray = cv2.dilate(gray, kernel, iterations=1)
        gray = cv2.GaussianBlur(gray,(5,5),1)
        gray = cv2.dilate(gray, kernel, iterations=2)
        gray = cv2.erode(gray, kernel,iterations=2)

    #Removing rows and columns where all the pixels are black
    while np.sum(gray[0]) == 0:
        gray = gray[1:]

    while np.sum(gray[:,0]) == 0:
        gray = np.delete(gray,0,1)

    while np.sum(gray[-1]) == 0:
        gray = gray[:-1]

    while np.sum(gray[:,-1]) == 0:
        gray = np.delete(gray,-1,1)

    rows,cols = gray.shape

    if(resize_flag) == 1:
        interpolation=cv2.INTER_AREA
    else:
        interpolation=cv2.INTER_CUBIC
    # Making the aspect ratio same before re-sizing
    if rows > cols:
        factor = 20.0/rows
        rows = 20
        cols = int(round(cols*factor))
        # first cols than rows
        gray = cv2.resize(gray, (cols,rows),interpolation=interpolation)
    else:
        factor = 20.0/cols
        cols = 20
        rows = int(round(rows*factor))
        # first cols than rows
        gray = cv2.resize(gray, (cols, rows),interpolation=interpolation)

    # Padding to a 28 * 28 image
    colsPadding = (int(math.ceil((28-cols)/2.0)),int(math.floor((28-cols)/2.0)))
    rowsPadding = (int(math.ceil((28-rows)/2.0)),int(math.floor((28-rows)/2.0)))
    gray = np.lib.pad(gray,(rowsPadding,colsPadding),'constant')

    # Get the best shifts
    shiftx,shifty = getBestShift(gray)
    shifted = shift(gray,shiftx,shifty)
    grayS = shifted
    grayS = grayS.reshape(1,1,28,28)

    #Normalize the image
    grayS = grayS/255

    return grayS

def extract_box(img, show=True):
    '''
    Function to extract the boxes in the ruled worksheet
    Input : Image with rectangle, show figures
    Output : Extract workspaces locations
    '''
    image_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    #Otsu thresholding
    thresh, binary_image = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

    # Defining a kernel length
    kernel_length = np.array(binary_image).shape[1]//80

    verticle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_length))
    hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length, 1))
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

    # Morphological operation to detect vertical lines from an image
    img_temp1 = cv2.erode(binary_image, verticle_kernel, iterations=3)
    verticle_lines_img = cv2.dilate(img_temp1, verticle_kernel, iterations=3)

    # Morphological operation to detect horizontal lines from an image
    img_temp2 = cv2.erode(binary_image, hori_kernel, iterations=3)
    horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=4)

    #Join horizontal and vertical images
    alpha = 0.5
    beta = 1.0 - alpha
    img_final_bin = cv2.addWeighted(verticle_lines_img, alpha, horizontal_lines_img, beta, 0.0)
    img_final_bin = cv2.erode(~img_final_bin, kernel, iterations=2)
    (thresh, img_final_bin) = cv2.threshold(img_final_bin, 0,255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

    #Find and sort the contours
    if(cv2.__version__ == '3.3.1'):
        xyz,contours, hierarchy = cv2.findContours(img_final_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    else:
        contours, hierarchy = cv2.findContours(img_final_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    (contours, boundingBoxes) = sort_contours(contours, method="top-to-bottom")

    area = []
    for contour in contours:
        area.append(cv2.contourArea(contour))

    s = np.argsort(area) #sorted area

    workspace_contours = []
    #Find the correct boxes where area is between 40% and 50% of the largest rectangle
    for i,contour in enumerate(contours):
        if cv2.contourArea(contour) >= area[s[-1]]*0.40  and cv2.contourArea(contour) < area[s[-1]]*0.50:
            workspace_contours.append(contour)

    #A list to containg rectangle locs
    rectangle_locs =[]

    #finding out locations of rectangle
    for cnt in workspace_contours:
        x,y,w,h = cv2.boundingRect(cnt)
        rectangle_locs.append([x,y,w,h])

    if (show):
        fig = plt.figure(figsize=(7,9))
        fig.suptitle('Extracted Workspaces')
        i=1
        l = len(rectangle_locs)
        for rect in rectangle_locs:
            ax = fig.add_subplot(l,1,i)
            ax.imshow(img[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]])
            i = i+1
        plt.show()

    return rectangle_locs

'''
Line Detection
'''

def find_good_contours_thres(conts, alpha = 0.002):
    '''
    Function to find threshold of good contours on basis of 10% of maximum area
    Input: Contours, threshold for removing noises
    Output: Contour area threshold

    For image dim 3307*4676
    alpha(text_segment) = 0.01
    alpha(extract_line) = 0.002
    '''
    #Calculating areas of contours and appending them to a list
    areas = []

    for c in conts:
        areas.append([cv2.contourArea(c)**2])
    #alpha is controlling paramter
    thres = alpha * max(areas)[0]

    return thres

def extract_line(image, beta=0.7, alpha=0.002, show = True):
    '''
    Function to extracts the line from the image
    Assumption : Sufficient gap b/w lines

    argument:
        img (array): image array
        beta (0-1) : Parameter to differentiate line
        alpha (0-1) : Parameter to select good contours
        show(bool) : to show figures or not
    output:
        uppers[diff_index]  : Upper points (x,y)
        lowers[diff_index]  : lower points(x,y)
    '''
    img = image.copy()
    H,W = img.shape[:2]
    h5 = int(.02 * H)
    w5 = int(.02 * W)
    img[:h5,:] = [255,255,255]
    img[-h5:,:] = [255,255,255]
    img[:,:w5] = [255,255,255]
    img[:,-w5:] = [255,255,255]

    #Converting image to gray
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    #Binary thresholding and inverting at 127
    th, threshed = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)

    #Selecting elliptical element for dilation
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
    dilation = cv2.dilate(threshed,kernel,iterations = 1)

    #Saving a copy of dilated image for taking bitwise_and operation
    temp = dilation.copy()

    # Find the contours
    if(cv2.__version__ == '3.3.1'):
        xyz,contours,hierarchy = cv2.findContours(dilation,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    else:
        contours,hierarchy = cv2.findContours(dilation,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

    cont_thresh = find_good_contours_thres(contours, alpha=alpha)

    #Creating a mask of only ones
    mask = np.ones(dilation.shape[:2], dtype="uint8") * 255

    #Drawing those contours which are noises and then taking bitwise and
    for c in contours:
        if( cv2.contourArea(c)**2 < cont_thresh):
            cv2.drawContours(mask, [c], -1, 0, -1)

    cleaned_img = cv2.bitwise_and(temp, temp, mask=mask)

    #Dilating the cleaned image for better detection of line in cases where
    #exponents are little up the line
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
    dil_cleaned_img = cv2.dilate(cleaned_img,kernel,iterations = 10)

    #Getting back the cleaned original image without noise
    cleaned_orig = cv2.erode(cleaned_img, kernel, iterations=1)

    ##find and draw the upper and lower boundary of each lines
    hist = cv2.reduce(dil_cleaned_img,1, cv2.REDUCE_AVG).reshape(-1)

    th = 1
    H,W = img.shape[:2]
    uppers = np.array([y for y in range(H-1) if hist[y]<=th and hist[y+1]>th])
    lowers = np.array([y for y in range(H-1) if hist[y]>th and hist[y+1]<=th])

    diff_1 = np.array([j-i for i,j in zip(uppers,lowers)])
    diff_index_1 = np.array([True if j > beta*(np.mean(diff_1)-np.std(diff_1)) else False for j in diff_1 ])

    uppers = uppers[diff_index_1]
    lowers = lowers[diff_index_1]

    #Extending uppers and lowers indexes to avoid cutting of chars of lines
    #Extended more uppers by 33% as exponential might lie above
    uppers[1:] = [i-int(j)/3 for i,j in zip(uppers[1:], diff_1[1:])]
    lowers[:-1] = [i+int(j)/4 for i,j in zip(lowers[:-1], diff_1[:-1])]

    diff_2 = np.array([j-i for i,j in zip(uppers,lowers)])
    diff_index_2 = np.array([True]*len(uppers))

    #Combining rogue exponentials into their deserving lines. This happens when
    #exponential and lines are separated by some distance
    for i,diff in enumerate(diff_2):
        if(i>0):
            if( (diff_2[i-1] < (diff/2)) and (( lowers[i-1]-uppers[i]) > ((lowers[i-1]-uppers[i-1])/5)) ):
                uppers[i] = uppers[i-1]
                diff_2[i] = diff_2[i]+diff_2[i-1]
                diff_index_2[i-1] = False
                print('Merging')

    diff_index = diff_index_2

    cleaned_orig_rec = cv2.cvtColor(cleaned_orig, cv2.COLOR_GRAY2BGR)

    #For changing color of intermediate lines, keeping count
    col_ct = 0

    for left,right in zip(uppers[diff_index], lowers[diff_index]):
        #print(left,right)
        col1 = (153,255,255)
        col2 = (255,255,153)
        if(col_ct % 2 == 0):
            col= col1
        else:
            col=col2
        cv2.rectangle(cleaned_orig_rec ,(0+10,left),(W-15,right),col,4)
        col_ct += 1

    if(show == True):
        fig0 = plt.figure(figsize=(15,5))
        ax1 = fig0.add_subplot(1,3,1)
        ax1.set_title('Original Image')
        ax1.imshow(img)
        ax1.axis('off')

        ax2 = fig0.add_subplot(1,3,2)
        ax2.set_title('Cleaned Image')
        ax2.imshow(cv2.cvtColor(cleaned_img, cv2.COLOR_GRAY2RGB))
        ax2.axis('off')

        ax3 = fig0.add_subplot(1,3,3)
        ax3.set_title('Noises')
        ax3.imshow(cv2.cvtColor(mask, cv2.COLOR_BGR2RGB))
        ax3.axis('off')

        fig0.suptitle('Denoising')
        plt.show()

        fig1 = plt.figure(figsize=(15,5))
        fig1.suptitle('Line Detection')
        ax1 = fig1.add_subplot(1,2,1)
        ax1.axis("off")
        ax1.imshow(cv2.cvtColor(cleaned_orig,cv2.COLOR_BGR2RGB))

        ax2 = fig1.add_subplot(1,2,2)
        ax2.axis("off")
        ax2.imshow(cv2.cvtColor(cleaned_orig_rec, cv2.COLOR_BGR2RGB))

        plt.show()

    return cleaned_orig, uppers[diff_index], lowers[diff_index]

def evaluate(df,A,B,X,Y):
    '''Function to evaluate mathematical equation and give bool output
    Input: Dataframe
           Values
    Output:
        Boolean T/F
    '''
    #Evaluating Expression
    actual = A*X*X+(B*Y)

    try:#If BODMAS is correct and Mathematically equation is correct
        pred = df["exp"].apply(lambda d: "**" if d==1 else "")
        pred = "".join(list(pred+df["pred"]))

        #looking for non digits in the start of the string for
        #ignoring equal to's
        matchesN = re.findall('^\-\-', pred)
        if(len(matchesN) > 0):
            for s in matchesN:
                pred = pred.replace(s,'')

        #looking for broken 5's
        matches5 = re.findall(r'5\*\*-\D*', pred)
        if(len(matches5) > 0):
            for s in matches5:
                sn = s.split('5**-')
                snew = sn[0]+'5'+sn[1]
                pred = pred.replace(s,snew)

        #This except block is fired when brackets are un necessarily used
        #while writing the answerscripts and in strings
        matchesB_left = re.findall(r'\d\(\d', pred)
        matchesB_right = re.findall(r'\d\)\d', pred)

        if(len(matchesB_left) > 0 or len(matchesB_right) > 0):
            for s in matchesB_left:
                sn = s.split('(')
                snew = sn[0]+'*('+sn[1]
                pred = pred.replace(s,snew)

            for s in matchesB_right:
                sn = s.split(')')
                snew = sn[0]+')*'+sn[1]
                pred = pred.replace(s,snew)

        ans = eval_expr(pred)
        print(pred )
#        if(ans == actual):
#            val='Correct'
#        else:
#            val='Wrong'
#        print(ans, actual, val)
        if(df['pred_proba'].mean() < 0.75):
            return 5

    except Exception as e:
        print(pred,'-',e)
        return 5

    return actual==ans

def text_segment(Y1,Y2,X1,X2,box_num,line_name, dict_clean = dict_clean_img,\
                 acc_thresh = 0.60, show = True):
    '''
    text_segment : Function to segment the characters
    Input:
        Box coordinates -X1,Y1,X2,Y2
        box_num - name of box
        line_name - name of line
        model - Deep Learning model to be used for prediction
        dict_clean - dictionary of clean box images
    Output :
        box_num - name of box
        line_name -name of line
        df_char - Dataframe of characters of that particular line
    '''
    img = dict_clean[box_num][Y1:Y2,X1:X2].copy()
    L_H = Y2-Y1
    ## apply some dilation and erosion to join the gaps
    #Selecting elliptical element for dilation
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
    dilation = cv2.dilate(img,kernel,iterations = 2)
    erosion = cv2.erode(dilation,kernel,iterations = 1)

    # Find the contours
    if(cv2.__version__ == '3.3.1'):
        xyz,contours,hierarchy = cv2.findContours(erosion,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    else:
        contours,hierarchy = cv2.findContours(erosion,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

    ct_th = find_good_contours_thres(contours, alpha=0.005)
    cnts = []
    for c in contours:
        if( cv2.contourArea(c)**2 > ct_th):
            cnts.append(c)
    contours_sorted,bounding_boxes = sort_contours(cnts,method="left-to-right")
    char_locs = []

    img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

    i = 0
    char_type =[]
    while i in range(0, len(contours_sorted)):
            x,y,w,h = bounding_boxes[i]
            exp = 0
            if i+1 != len(contours_sorted):
                x1,y1,w1,h1 = bounding_boxes[i+1]
                if abs(x-x1) < 10 and  (h1+h) < 70:
                    #print(h+h1)
                    minX = min(x,x1)
                    minY = min(y,y1)
                    maxX = max(x+w, x1+w1)
                    maxY = max(y+h, y1+h1)
                    x,y,x11,y11 = minX, minY, maxX, maxY

                    x,y,w,h = x,y,x11-x,y11-y
                    i = i+2
                    continue

            #char_locs.append([x,y,x+w,y+h])
            if(h<0.10*L_H and w<0.10*L_H):
                #print('Yes')
                i=i+1
                continue

            char_locs.append([x-2,y+Y1-2,x+w+1,y+h+Y1+1,w*h]) #Normalised location of char w.r.t box image

            cv2.rectangle(img,(x,y),(x+w,y+h),(153,180,255),2)
            if i!=0:
                if y+h < (L_H*(1/2)) and y < bounding_boxes[i-1][1] and h < bounding_boxes[i-1][3]:
                    exp = 1
                    cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
            i = i+1
            char_type.append(exp)

    if(show == True):
        plt.figure(figsize=(15,8))
        plt.axis("on")
        plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        plt.show()

    df_char = pd.DataFrame(char_locs)
    df_char.columns=['X1','Y1','X2','Y2','area']
    df_char['exp'] = char_type
    df_char['pred'] = df_char.apply(lambda c: predict(dict_clean[box_num],c['X1'],\
           c['Y1'],c['X2'], c['Y2'], acc_thresh=acc_thresh), axis=1 )
    df_char['pred_proba'] = df_char.apply(lambda c: predict(dict_clean[box_num],c['X1'],\
           c['Y1'],c['X2'], c['Y2'], proba=True, acc_thresh=acc_thresh), axis=1 )
    df_char['line_name'] = line_name
    df_char['box_num'] = box_num
    return [box_num,line_name,df_char]
#%%
def checker(image_path,A=-1,B=-1,X=-1,Y=-1, acc_thresh=0.60):
    '''
    Main driver function to manage calling and executing algorithm
    argument:
        image_path (string): image path
        A, B, X, Y (int)    : coefficients
    '''
    #reading image
    img_i = cv2.imread(image_path)

    if(type(img_i) != np.ndarray):
        return 'Invalid Image passed'
    #Aspect Ratio calculation
    asp_h = img_i.shape[0]
    asp_w = img_i.shape[1]
    asp_ratio = round(asp_h/asp_w , 1)

    if(asp_ratio != 1.4):
        print('Poor Image Aspect Ratio : Results Will be affected')

    if (asp_h > 4676):#Oversized image
        img = image_resize(img_i, height = 4676, width = 3307, inter = cv2.INTER_AREA)
    elif(asp_h < 4676):#Less sized image
        img = image_resize(img_i, height = 4676, width = 3307, inter = cv2.INTER_LINEAR)
        print('Image less than 300 dpi might have reduced accuracy')
    else:
        img = img_i

    #Workspaces Detection
    workspaces = extract_box(img)

    if(len(workspaces) != 3):
        print('Invalid worksheet image passed, please scan properly')
        return -1
    #Defining dataframe for storing infos about every line detected
    df_lines = pd.DataFrame()

    for r,rect in enumerate(workspaces):
        #Cropping boxes for sending to line detection module
        box = img[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]]
        H,W = box.shape[:2]
        #Extracting lines present in the boxes
        cleaned_orig,y1s,y2s = extract_line(box, show=False)
        x1s = [0]*len(y1s)
        x2s = [W]*len(y1s)

#        if(len(y1s)-len(y2s) == 0):
#            print('Lines in workspace-%d : %d' %(r, len(y1s)))

        df = pd.DataFrame([y1s,y2s,x1s,x2s]).transpose()
        df.columns = ['y1','y2','x1','x2']
        df['box_num'] = r

        df_lines= pd.concat([df_lines, df])

        dict_clean_img.update({r:cleaned_orig})
        dict_img.update({r:box})

        #print(df)

    df_lines['line_name'] = ['%d%d' %(df_lines.box_num.iloc[i],df_lines.index[i]) \
            for i in range(len(df_lines))]

    #df_chars contains locations of all characters along with box_num and line name
    list_chars = list(df_lines.apply(lambda row: text_segment(row['y1'],row['y2'],\
                 row['x1'],row['x2'], row['box_num'],row['line_name'], \
                 show=False, acc_thresh=acc_thresh), axis=1))

    df_chars = pd.DataFrame(list_chars)
    df_chars.columns = ['box_num', 'line_name', 'char_df']

    #Plotting detected Characters

    box_nums = df_chars.box_num.unique()
    #fig3 = plt.figure(figsize=(7,9))
    #fig3.suptitle('Characters Segmented')

    char_area_list = []
    df_chars['char_df'].apply(lambda d: char_area_list.append(list(d['area'])) )

    #Area based threshold for detecting and removing noises
    gamma = 0
    max_ar = max([max(i) for i in char_area_list])
    ar_thresh = max_ar*gamma

    #Keeping only those characters whose area of contours is above area threshold
    df_chars['char_df'] = df_chars['char_df'].apply(lambda d: d[d.area > ar_thresh] )

    for bn in box_nums:
        print('BOX %d' %(bn+1))
        box_img = dict_clean_img[bn] #For Processing B/W image
        box_img_1 = dict_img[bn] #For saving results
        box_img = cv2.cvtColor(box_img, cv2.COLOR_GRAY2BGR)

        df = df_chars[df_chars.box_num == bn].copy()
        df_l = df_lines[df_lines["box_num"]==bn].copy() #Defining dF with line info

        df['char_df'].apply(lambda d: d.apply(lambda c: cv2.rectangle(box_img, \
          (c['X1'],c['Y1']),(c['X2'], c['Y2']),(255*(c['exp']==1),180,0),2+(2*c['exp'])), axis=1 ) )

        df['line_status'] = df['char_df'].apply(lambda d: evaluate(d[["pred","exp","pred_proba"]],A,B,X,Y))

        scale_percent = 200 # percent of original size
        width = int(box_img.shape[1] * scale_percent / 100)
        height = int(box_img.shape[0] * scale_percent / 100)
        dim = (width, height)
        box_img = cv2.resize(box_img, dim, interpolation = cv2.INTER_AREA)

        #Drawing rectangle on original Image
        df_l['line_status'] = list(df['line_status'])
        df_l.apply(lambda c: cv2.rectangle(box_img_1, (c['x1'],c['y1']),(c['x2'],\
          c['y2']),(255*(c['line_status']==5),255*(c['line_status']==True),\
                                   255*(c['line_status']==False)),2), axis=1)

        plt.figure(figsize=(13,7))
        plt.title('Box - %d' %(bn+1) )
        plt.imshow(cv2.cvtColor(box_img_1, cv2.COLOR_BGR2RGB))
        plt.figure()
        plt.imshow(cv2.cvtColor(box_img, cv2.COLOR_BGR2RGB))
        fname = os.path.join('output','image%d.jpg' %(bn+1))
        plt.imsave(fname,cv2.cvtColor(box_img_1, cv2.COLOR_BGR2RGB))
        fname_2 = os.path.join('logs',image_path.split('/')[2].split('.jpg')[0]\
                               +'b%d_%s.jpg' %(bn+1,ts))
        plt.imsave(fname_2,cv2.cvtColor(box_img_1, cv2.COLOR_BGR2RGB))
        del df
        del df_l

    return 1