import socket

import rospy
from geometry_msgs.msg import Wrench, WrenchStamped
from std_msgs.msg import Header

REMOTE_IP = "192.168.53.3"
REMOTE_PORT  = 63351
REMOTE_ADDR = (REMOTE_IP, REMOTE_PORT)

def main():
    # Create socket and connect to remote address
    local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    local_socket.connect(REMOTE_ADDR)

    # Create a publisher and a new node in ROS
    publisher = rospy.Publisher('sensor_topic', WrenchStamped, queue_size=1)
    rospy.init_node("robotiq_ft_sensor_publisher")
    # Set rate to run (100hz for robotiq)
    rate = rospy.Rate(100)

    # Create message parts
    wrench_message = WrenchStamped()
    header = Header()
    wrench = Wrench()
    header.frame_id = "robotiq_ft_frame_id"

    # Create a varaible to hold incomplete packets
    last_message = ""
    while not rospy.is_shutdown():

        # Read bytes from tcp stream and convert to ascii string
        buffer, addr = local_socket.recvfrom(100)
        message = buffer.decode("ascii")

        # We want to split the message in packets, but we need to track the peackets incomplete '(...' or '...)'
        message = message.replace(")", ")|")    # So we add another delimiter between packets
        reading_list = message.split("|")       # Now we split using our delimiter, which will be removed

        # We can now inspect the first packet
        if (reading_list[0].count("(") == 0):
            # if the first packet doesn't have the opening braket, we compose it with the last packet of the previus reading from socket
            reading_list[0] = last_message + reading_list[0]
            last_message = "" #last message has been used, we clean it
        # Now we inspect the last packet
        if (reading_list[-1].count(")") == 0):
            # if the last packet doesn't have the closing bracket, we save it for later use
            last_message = reading_list[-1]
            reading_list.remove(reading_list[-1]) # and we remove the incomplete packet from the reading list. It will be used in the next reading.

        # Now we scan each packet
        for reading in reading_list:

            # Make sure each reading is now fully composed
            if reading.count("(") == 0 or reading.count(")") == 0:
                rospy.loginfo(f"MALFORMED packet is missing brackets, printing buffer, list and readings:\n" +
                              f"BUFFER:{message}\n\n" +
                              f"Reading list:{reading_list}\n\n" +
                              f"Reading:{reading}")
                # We don't send this reading
                continue

            # We can finally remove brakets
            reading = reading.replace("(", "").replace(")", "")
            # Now we can split safely, and convert each value to float value
            values = list(map(float, reading.split(" , ")))

            # We make sure each packet has 6 values
            if len(values) != 6 :
                rospy.loginfo(f"MALFORMED packet is missing values, printing buffer, list and readings:\n" +
                              f"BUFFER:{message}\n\n" +
                              f"Reading list:{reading_list}\n\n" +
                              f"Reading:{reading}\n" +
                              f"has been mapped to\n" +
                              f"{values}")
                # We don't send this reading
                continue

            # Now we need to construct the message
            # Construct force vector
            wrench.force.x = values[0]
            wrench.force.y = values[1]
            wrench.force.z = values[2]
            #Construct torque vector
            wrench.torque.x = values[3]
            wrench.torque.y = values[4]
            wrench.torque.z = values[5]
            # Construct header's stamp
            header.stamp = rospy.Time.now()

            # Set message header and wrench
            wrench_message.header = header
            wrench_message.wrench = wrench

            # Publish WrenchStamped message to topic and sleep
            publisher.publish(wrench_message)

        # We sent packets received, we can read again at given ros frequency
        rate.sleep()

if __name__ == '__main__':
    try:
        main()
    except rospy.ROSInterruptException:
        pass


import unittest

# These are normal inclusions
from golix import Ghid

# These are abnormal (don't use in production) inclusions
from golix._spec import _gidc, _geoc, _gobs, _gobd, _gdxx, _garq
from golix._spec import _asym_hand, _asym_ak, _asym_nk, _asym_else
from golix.crypto_utils import _dummy_signature
from golix.crypto_utils import _dummy_mac
from golix.crypto_utils import _dummy_asym
from golix.crypto_utils import _dummy_address
from golix.crypto_utils import _dummy_pubkey
from golix.crypto_utils import _dummy_pubkey_exchange

# ###############################################
# Testing
# ###############################################

_dummy_ghid = Ghid(0, _dummy_address)

class SpecTest(unittest.TestCase):
    ''' Test all of the parsing systems in _spec.
    '''

    def test_gidc(self):
        # GIDC test parsers
        gidc_1 = {
            'magic': b'GIDC',
            'version': 2,
            'cipher': 0,
            'body': {
                'signature_key': _dummy_pubkey,
                'encryption_key': _dummy_pubkey,
                'exchange_key': _dummy_pubkey_exchange,
            },
            'ghid': _dummy_ghid,
            'signature': None
        }

        gidc_1p = _gidc.pack(gidc_1)
        gidc_1r = _gidc.unpack(gidc_1p)

        self.assertEqual(gidc_1, gidc_1r)

    def test_geoc(self):
        # GEOC test parsers
        geoc_1 = {
            'magic': b'GEOC',
            'version': 14,
            'cipher': 0,
            'body': {
                'author': _dummy_ghid,
                'payload': b'Hello world',
            },
            'ghid': _dummy_ghid,
            'signature': _dummy_signature
        }

        geoc_1p = _geoc.pack(geoc_1)
        geoc_1r = _geoc.unpack(geoc_1p)

        self.assertEqual(geoc_1, geoc_1r)

    def test_gobs(self):
        # GOBS test parsers
        gobs_1 = {
            'magic': b'GOBS',
            'version': 6,
            'cipher': 0,
            'body': {
                'binder': _dummy_ghid,
                'target': _dummy_ghid,
            },
            'ghid': _dummy_ghid,
            'signature': _dummy_signature
        }

        gobs_1p = _gobs.pack(gobs_1)
        gobs_1r = _gobs.unpack(gobs_1p)

        self.assertEqual(gobs_1, gobs_1r)

    def test_gobd_new(self):
        # GOBD test parsers with no history
        gobd_1 = {
            'magic': b'GOBD',
            'version': 16,
            'cipher': 0,
            'body': {
                'binder': _dummy_ghid,
                'counter': 0,
                'target_vector': (_dummy_ghid,)
            },
            'ghid_dynamic': _dummy_ghid,
            'ghid': _dummy_ghid,
            'signature': _dummy_signature
        }

        gobd_1p = _gobd.pack(gobd_1)
        gobd_1r = _gobd.unpack(gobd_1p)

        self.maxDiff = None
        for key in gobd_1:
            with self.subTest(key):
                self.assertEqual(gobd_1[key], gobd_1r[key])

    def test_gobd_historied(self):
        # GOBD test parsers
        gobd_1 = {
            'magic': b'GOBD',
            'version': 16,
            'cipher': 0,
            'body': {
                'binder': _dummy_ghid,
                'counter': 1,
                'target_vector': (_dummy_ghid, _dummy_ghid)
            },
            'ghid_dynamic': _dummy_ghid,
            'ghid': _dummy_ghid,
            'signature': _dummy_signature
        }

        gobd_1p = _gobd.pack(gobd_1)
        gobd_1r = _gobd.unpack(gobd_1p)

        self.maxDiff = None
        for key in gobd_1:
            with self.subTest(key):
                self.assertEqual(gobd_1[key], gobd_1r[key])

    def test_gdxx(self):
        # GDXX test parsers
        gdxx_1 = {
            'magic': b'GDXX',
            'version': 9,
            'cipher': 0,
            'body': {
                'debinder': _dummy_ghid,
                'target': _dummy_ghid,
            },
            'ghid': _dummy_ghid,
            'signature': _dummy_signature
        }

        gdxx_1p = _gdxx.pack(gdxx_1)
        gdxx_1r = _gdxx.unpack(gdxx_1p)

        self.assertEqual(gdxx_1, gdxx_1r)

    def test_garq(self):
        # GARQ test parsers
        garq_1 = {
            'magic': b'GARQ',
            'version': 12,
            'cipher': 0,
            'body': {
                'recipient': _dummy_ghid,
                'payload': _dummy_asym,
            },
            'ghid': _dummy_ghid,
            'signature': _dummy_mac
        }

        garq_1p = _garq.pack(garq_1)
        garq_1r = _garq.unpack(garq_1p)

        self.assertEqual(garq_1, garq_1r)

    def test_handshake(self):
        # Asymmetric payload blob tests.
        asym_hand_1 = {
            'author': _dummy_ghid,
            'magic': b'HS',
            'payload': {
                'target': _dummy_ghid,
                'secret': bytes(32)
            }
        }
        asym_hand_1p = _asym_hand.pack(asym_hand_1)
        asym_hand_1r = _asym_hand.unpack(asym_hand_1p)

        self.assertEqual(asym_hand_1, asym_hand_1r)

    def test_ack(self):
        asym_ak_2 = {
            'author': _dummy_ghid,
            'magic': b'AK',
            'payload': {
                'target': _dummy_ghid,
                'status': 0
            }
        }
        asym_ak_2p = _asym_ak.pack(asym_ak_2)
        asym_ak_2r = _asym_ak.unpack(asym_ak_2p)

        self.assertEqual(asym_ak_2, asym_ak_2r)

    def test_nak(self):
        asym_nk_3 = {
            'author': _dummy_ghid,
            'magic': b'NK',
            'payload': {
                'target': _dummy_ghid,
                'status': 0
            }
        }
        asym_nk_3p = _asym_nk.pack(asym_nk_3)
        asym_nk_3r = _asym_nk.unpack(asym_nk_3p)

        self.assertEqual(asym_nk_3, asym_nk_3r)

    def test_asym_other(self):
        asym_else_4 = {
            'author': _dummy_ghid,
            'magic': b'\x00\x00',
            'payload': b'Hello world'
        }
        asym_else_4p = _asym_else.pack(asym_else_4)
        asym_else_4r = _asym_else.unpack(asym_else_4p)

        self.assertEqual(asym_else_4, asym_else_4r)

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


class Group():
    gid = 1
    def __init__(self, persons) :
        self.gid = Group.gid
        Group.gid += 1
        self.persons = persons
        self.len_persons = len(persons)
        self.sum_answers = "".join([x.data for x in self.persons])
        self.unique_answers = {x for x in self.sum_answers}
        self.len_unique_answers = len(self.unique_answers)

    def __repr__(self) :
        return f"\nGroup {self.gid}: {self.len_unique_answers} \t {self.persons}"

class Person() :
    def __init__(self, form_data) :
        self.data = form_data

    def __repr__(self) :
        return f"Data: {self.data}"

with open("advent2020/p06a_data.txt") as file :
    data = file.read().split("\n\n")

groups = []
for d in data :
    persons = []
    for person_data in d.split("\n") :
        persons.append(Person(person_data))
    groups.append(Group(persons))

print(sum([x.len_unique_answers for x in groups]))
print(sum([x.len_answer_intersection for x in groups]))


from typing import List
from uuid import UUID

from fastapi import APIRouter, Depends, Response, status
from fastapi.exceptions import HTTPException
from structlog import get_logger

from fastapi_server.lib.logs import exception_to_string
from fastapi_server.resources.database.postgres import get_db_session
from fastapi_server.resources.database.database import get_databases

from fastapi_server.apps.users.schemas import ActiveUser
from fastapi_server.apps.users.auth import with_active_user
from ..schemas import (
    ProjectMemberCreate,
    ProjectMemberRead,
    ProjectMemberUpdate,
    ProjectRead,
    ProjectCreate,
    ProjectUpdate,
)
from ..database.postgres import ProjectsDB, get_projects_db
from ..entitlements import project_with_permissions
from .. import core

from .schemas import CreateProjectMemberPayload, CreateProjectResponse

logger = get_logger("projects")

router = APIRouter(
    prefix="/projects", tags=["projects"], responses={404: {"description": "Not found"}}
)

@router.get(
    "/projects",
    name="projects:projects:get-projects",
    response_description="Get all Projects",
    response_model=List[ProjectRead],
)
async def get_projects(
    db: ProjectsDB = Depends(get_projects_db),
    user: ActiveUser = Depends(with_active_user),
):
    projects = await db.get_projects()
    logger.info(
        "Get Projects",
        code="projects-get_projects",
        user_id=user.user_id,
        projects=len(projects),
    )
    return projects

@router.get(
    "/projects/user",
    name="projects:projects:get-user-projects",
    response_description="Get user Projects",
    response_model=List[ProjectRead],
)
async def get_user_projects(
    db: ProjectsDB = Depends(get_projects_db),
    user: ActiveUser = Depends(with_active_user),
):
    projects = await db.get_projects_by_user(user.user_id)
    logger.info(
        "Get User Projects",
        code="projects-get_user_projects",
        user_id=user.user_id,
        projects=len(projects),
    )
    return projects

@router.post(
    "/projects",
    name="projects:projects:add-project",
    status_code=status.HTTP_201_CREATED,
)
async def create_project(
    project_create: ProjectCreate,
    db: ProjectsDB = Depends(get_projects_db),
    user: ActiveUser = Depends(with_active_user),
) -> CreateProjectResponse:
    created_project, created_project_member = await core.create_project(
        db, user.user_id, project_create
    )
    logger.info(
        "Create project",
        code="projects-create_project",
        user_id=user.user_id,
        project_id=str(created_project.id),
    )
    return {"project": created_project, "project_member": created_project_member}

@router.patch(
    "/projects/{project_id}",
    name="projects:projects:update-project",
    response_model=ProjectRead,
)
async def update_project(
    project_id: UUID,
    project_update: ProjectUpdate,
    db: ProjectsDB = Depends(get_projects_db),
    user: ActiveUser = Depends(with_active_user),
):
    log_kwargs = {
        "code": "projects-update_project",
        "user_id": user.user_id,
        "project_id": str(project_id),
    }
    await project_with_permissions(db, project_id, user.user_id, True)
    try:
        updated_project = await core.update_project(
            db, user.user_id, project_id, project_update
        )
    except Exception as e:
        logger.error("Update project", exception=exception_to_string(e), **log_kwargs)
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
        )
    logger.info("Update project", **log_kwargs)
    return updated_project

@router.delete(
    "/projects/{project_id}",
    name="projects:projects:delete-project",
    status_code=status.HTTP_204_NO_CONTENT,
    response_class=Response,
)
async def delete_project(
    project_id: UUID,
    db: ProjectsDB = Depends(get_projects_db),
    user: ActiveUser = Depends(with_active_user),
):
    log_kwargs = {
        "code": "projects-delete_project",
        "user_id": user.user_id,
        "project_id": str(project_id),
    }
    await project_with_permissions(db, project_id, user.user_id, True)
    try:
        await core.delete_project(db, project_id)
    except Exception as e:
        logger.error("Delete project", exception=str(e), **log_kwargs)
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
    logger.info("Delete project", **log_kwargs)

    return None

"""
PROJECT MEMBERS
"""

@router.get(
    "/projects/{project_id}/members",
    name="projects:project-members:get-project-members",
    response_description="Get Project Members",
    response_model=List[ProjectMemberRead],
)
async def get_project_members(
    project_id: UUID,
    db: ProjectsDB = Depends(get_projects_db),
    user: ActiveUser = Depends(with_active_user),
):
    await project_with_permissions(db, project_id, user.user_id)
    project_members = await db.get_project_members_by_project_id(project_id)
    if not project_members:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
    return project_members

@router.post(
    "/projects/{project_id}/members",
    name="projects:project-members:create-project-member",
    response_description="Create Project Member",
    response_model=ProjectMemberRead,
    status_code=status.HTTP_201_CREATED,
)
async def create_project_member(
    project_id: UUID,
    project_member_create_payload: CreateProjectMemberPayload,
    session=Depends(get_db_session),
    user: ActiveUser = Depends(with_active_user),
):
    dbs = get_databases(session)
    await project_with_permissions(dbs["projects"], project_id, user.user_id, True)
    try:
        user_to_add = await dbs["users"].get_user_by_email(
            project_member_create_payload.user_email
        )
        if not user_to_add:
            raise Exception()

        project_member_create = ProjectMemberCreate(
            project_id=project_id,
            user_id=user_to_add.id,
            is_admin=project_member_create_payload.is_admin,
        )
        project_member = await core.create_project_member(
            dbs["projects"], user.user_id, project_member_create
        )
    except Exception as e:
        logger.error(
            f"Create project member for project {project_id}",
            project_id=str(project_id),
            user_id=user.user_id,
            project_member_create_payload=project_member_create_payload.model_dump(),
            exception=exception_to_string(e),
        )
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
        )
    return project_member

@router.patch(
    "/projects/{project_id}/members/{member_id}",
    name="projects:project-members:update-project-member",
    response_model=ProjectMemberRead,
)
async def update_project_member(
    project_id: UUID,
    member_id: str,
    project_member_update: ProjectMemberUpdate,
    db: ProjectsDB = Depends(get_projects_db),
    user: ActiveUser = Depends(with_active_user),
):
    await project_with_permissions(db, project_id, user.user_id, True)

    try:
        updated_project_member = await core.update_project_member(
            db, user.user_id, project_id, member_id, project_member_update
        )
    except Exception as e:
        logger.error(
            f"Update project member {project_id}",
            project_id=project_id,
            user_id=user.user_id,
            member_id=member_id,
            project_member=project_member_update.model_dump(),
            exception=exception_to_string(e),
        )
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
        )

    return updated_project_member

@router.delete(
    "/projects/{project_id}/members/{member_id}",
    name="projects:project-members:remove-project-member",
    response_description="Remove Project Member",
    status_code=status.HTTP_204_NO_CONTENT,
)
async def remove_project_member(
    project_id: UUID,
    member_id: str,
    db: ProjectsDB = Depends(get_projects_db),
    user: ActiveUser = Depends(with_active_user),
):
    await project_with_permissions(db, project_id, user.user_id, True)
    try:
        await db.delete_project_member_by_user_id(member_id)
    except Exception as e:
        logger.error(
            f"Delete project member for {project_id}",
            project_id=str(project_id),
            member_id=member_id,
            user_id=user.user_id,
            exception=exception_to_string(e),
        )
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
        )
    return None


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:

        if not l1 and not l2: return ListNode(0)
        if not l1: return l2
        if not l2: return l1

        cur = ans = ListNode(0)
        cur1 = l1
        cur2 = l2
        carry = 0

        # 1. move both ptrs
        while cur1 and cur2:
            ans_val = carry + cur1.val + cur2.val
            if ans_val >= 10:
                carry = 1
                cur.next = ListNode(ans_val % 10)
            else:
                carry = 0
                cur.next = ListNode(ans_val)
            cur = cur.next
            cur1 = cur1.next
            cur2 = cur2.next

        # 2. move cur1 ptr if cur1
        while cur1:
            ans_val = carry + cur1.val
            if ans_val >= 10:
                carry = 1
                cur.next = ListNode(ans_val % 10)
            else:
                carry = 0
                cur.next = ListNode(ans_val)
            cur = cur.next
            cur1 = cur1.next

        # 3. move cur2 ptr if cur2
        while cur2:
            ans_val = carry + cur2.val
            if ans_val >= 10:
                carry = 1
                cur.next = ListNode(ans_val % 10)
            else:
                carry = 0
                cur.next = ListNode(ans_val)
            cur = cur.next
            cur2 = cur2.next

        # 4. add carry if carry = 1
        if carry == 1:
            cur.next = ListNode(1)

        return ans.next


import re
import os
import json
from datetime import date, datetime
from collections.abc import Iterable
import pandas as pd
from pandas.api.types import is_numeric_dtype, is_categorical_dtype, is_string_dtype, is_object_dtype, infer_dtype
import plotly

from .currencies import get_valid_currencies

def __generic_error_message(text:str):
    """
    This function can be used if a custom error message function is not provided.
    It simply returns the text it was passed.
    """
    return text

def check_int(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is an integer. If not, this will raise
    an error.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if not isinstance(value_to_check, int):
        message = get_error_message_function(f"{name} must be an integer.")
        raise TypeError(message)

def check_positive_numeric(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is a positive number (int or float). If not, this will raise
    an error.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if (isinstance(value_to_check, int) or isinstance(value_to_check, float)) and value_to_check > 0:
        pass
    else:
        message = get_error_message_function(f"{name} must be a positive number.")
        raise ValueError(message)

def check_int(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is an integer. If not, this will raise
    an error.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if not isinstance(value_to_check, int):
        message = get_error_message_function(f"{name} must be an integer.")
        raise TypeError(message)

def check_bool(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is a boolean. If not, this will raise
    an error.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if not isinstance(value_to_check, bool):
        message = get_error_message_function(f"{name} must be a boolean value (must be logical).")
        raise TypeError(message)

def check_scalar(value_to_check, name:str, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is a scalar value, meaning, that it is NOT
    a iterable. Note that for these purposes strings are considered scalars,
    even though they are technically iterable.
    Params:
        value_to_check: The value in question.
        name: The variable name for the error message.
        get_error_message_function: The function to call to get the error message template.
    Raises:
        TypeError - If the check fails.
    """
    if not isinstance(value_to_check, str) and isinstance(value_to_check, Iterable):
        message = get_error_message_function(f"{name} must be a scalar (not a list or other iterable type).")
        raise TypeError(message)

def check_enum(value_to_check, possible_values, get_error_message_function=__generic_error_message):
    """
    Verify that the provided value is in a list of possible values.
    Params:
        value_to_check: The value in question
        possible_values: An iterable list of values
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not value_to_check in possible_values:
        message = get_error_message_function(f"{value_to_check} must be one of {possible_values}")
        raise ValueError(message)

def check_is_list(value_to_check, get_error_message_function):
    """
    Verify that the provided value is a list.
    Params:
        value_to_check: The value in question
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not isinstance(value_to_check, list):
        message = get_error_message_function(f"Expected value '{value_to_check}' to be a list")
        raise ValueError(message)

def check_has_variable(df: pd.DataFrame, varname: str, get_error_message_function):
    """
    Verify that the dataframe contains the column.
    Params:
        df: Pandas DataFrame
        varname: The variable name to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if varname not in df.columns:
        raise ValueError(get_error_message_function(f"Could not find variable {varname} is in the list of columns"))

def check_numeric(df: pd.DataFrame, varname: str, get_error_message_function):
    """
    Verify that in the dataframe, the column 'varname' is numeric.
    Params:
        df: Pandas DataFrame
        varname: The variable name to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not is_numeric_dtype(df[varname]):
        raise ValueError(get_error_message_function(f"The variable '{varname}' must be numeric."))

def check_string_datatype(df: pd.DataFrame, varname: str, get_error_message_function=__generic_error_message):
    """
    Verify that in the dataframe, the column 'varname' is a string datatype.
    Params:
        df: Pandas DataFrame
        varname: The variable name to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not is_string_column(df[varname]):
        raise ValueError(get_error_message_function(f"The variable '{varname}' is not a string."))

def check_atomic_vector(df: pd.DataFrame, varname: str, get_error_message_function=__generic_error_message):
    """
    Verify that in the dataframe, the column 'varname' is an atomic vector, or
    in other words, not a nested type.
    Params:
        df: Pandas DataFrame
        varname: The variable name to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if infer_dtype(df[varname]) == "mixed":
        raise ValueError(get_error_message_function(f"The variable '{varname}' is must be an atomic vector (not a nested type)."))

def check_valid_currency(value_to_check: str, get_error_message_function):
    """
    Verify that the provided currency is a valid one (e.g., USD, EUR).
    Params:
        value_to_check: the value in question.
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    check_enum(value_to_check, get_valid_currencies(), get_error_message_function)

def check_range(df: pd.DataFrame, varname: str, min: float, max: float, get_error_message_function):
    """
    Verify that all values in 'varname' column in the dataframe are within this range.
    Params:
        df: Pandas DataFrame
        varname: The column
        min: float - The minimum value of the range (inclusive)
        max: float - The maximum value of the range (inclusive)
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    if not df[varname].between(min, max, "both").all():
        raise ValueError(get_error_message_function(f"The variable '{varname}' must be in the range {min} to {max}."))

def check_latitude_variable(df: pd.DataFrame, varname: str, get_error_message_function):
    """
    Verify that the latitude variable is numeric and in the proper range.
    Params:
        df: Pandas DataFrame
        varname: The latitude column
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    check_numeric(df, varname, get_error_message_function)
    check_range(df, varname, -90, 90, get_error_message_function)

def check_longitude_variable(df: pd.DataFrame, varname: str, get_error_message_function):
    """
    Verify that the longitude variable is numeric and in the proper range.
    Params:
        df: Pandas DataFrame
        varname: The longitude column
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    check_numeric(df, varname, get_error_message_function)
    check_range(df, varname, 0, 180, get_error_message_function)

# From: https://stackoverflow.com/a/22238613
def custom_json_serializer(obj):
    """JSON serializer for objects not serializable by default json code"""

    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    raise TypeError("Type {type(obj)} is not serializable")

def check_exhaustive_levels(df: pd.DataFrame, levels: list, varname: str, get_error_message_function):
    """
    Verifies that the values in the `varname` column contains only those values specified
    in `levels`. If any extras are found, an error is raised.
    Params:
        df: Pandas DataFrame
        levels: list - The possible values
        varname: The column to check
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    actual_values = set(df[varname].unique())
    expected_values = set(levels)

    diff = actual_values - expected_values

    if len(diff) > 0:
        raise ValueError(get_error_message_function(f"{varname} contains values not specified in levels:{levels}"))

def check_graph_var(df: pd.DataFrame, varname: str, id_varname: str, get_error_message_function):
    """
    """
    # TODO: After we have determined how to handle the graph data in Pandas,
    # implement this method to verify it.

    raise NotImplementedError()

valid_image_extensions = {"apng", "avif", "gif", "jpg", "jpeg", "jfif", "pjpeg",
  "pjp", "png", "svg", "webp"}

def _extension_matches(text:str, ext_to_match:str, match_case:bool = False):
    """
    Returns true if the extension of `text` matches the provided
    `ext_to_match`.

    Params:
        text: str - The filepath
        ext_to_match: str - The extension not including the . (pass "jpg" not ".jpg")

    Designed to be used as a "lambda" function in an apply method.
    """
    (_, ext) = os.path.splitext(text)

    # Get rid of the leading . in .jpg
    ext = ext.removeprefix(".")

    is_match = False

    if match_case:
        is_match = (ext == ext_to_match)
    else:
        is_match = (ext.lower() == ext_to_match.lower())

    return is_match

def find_figure_columns(df:pd.DataFrame):
    """
    Finds a list of columns in the dataframe that are completely filled with
    `Figure` objects.
    """

    # SB: This function (and its unit tests)  place a dependency on plotly,
    # because they check for plotly figure object. If this is not desired,
    # another approach could be used such as checking for a "facel_panel"
    # column name or something similar.

    figure_cols = []
    obj_cols = [col for col in df.columns if is_object_dtype(df[col])]

    for col in obj_cols:
        if isinstance(df[col][0], plotly.graph_objs.Figure):
            # The first row is a Figure, check all now
            if df[col].apply(lambda x: isinstance(x, plotly.graph_objs.Figure)).all():
                figure_cols.append(col)

    return figure_cols

def find_image_columns(df:pd.DataFrame):
    """
    Finds a list of columns in the dataframe that are completely filled with
    image references.
    """
    image_cols = []
    str_cols = [col for col in df.columns if is_string_column(df[col])]

    for col in str_cols:
        if is_image_column(df, col):
            image_cols.append(col)

    return image_cols

def is_image_column(df:pd.DataFrame, col:str) -> bool:
    """
    Returns True if the provided column is an image column, meaning
    that every value has the same, valid image extension.
    """
    is_image = False

    # Get the extension of the first item
    (_, ext) = os.path.splitext(df[col][0])

    # Get rid of the leading . in .jpg
    ext = ext.removeprefix(".")

    if ext in valid_image_extensions:
        # The first row had a valid image extension, now check if
        # they all have this same extension
        if df[col].apply(lambda x: _extension_matches(x, ext)).all():
            # All rows in this column have this extension
            is_image = True

    return is_image

def check_image_extension(list_to_check:list, get_error_message_function=__generic_error_message):
    """
    Verify that each element in the list has a valid image extension.
    Params:
        list_to_check: The list of strings.
        get_error_message_function: The function to call to get the error message template
    Raises:
        ValueError - If the check fails.
    """
    for item in list_to_check:
        filename, ext = os.path.splitext(item)

        # Get rid of the leading . in .jpg
        ext = ext.removeprefix(".")

        if ext not in valid_image_extensions:
            # Found invalid file extension
            message = get_error_message_function(f"Extension {ext} is not valid. All file extensions must be one of: {valid_image_extensions}")
            raise ValueError(message)

def is_all_remote(col:pd.Series):
    """
    Determines if every value in the provided `col` column is
    remote, meaning that they all begin with `http:`.
    """
    return col.apply(lambda x: x.startswith("http")).all()

def sanitize(text:str, to_lower=True) -> str:
    if to_lower:
        text = text.lower()

    text = text.replace(" ", "_")
    text = re.sub(r"[^\w]", "", text)

    return text

def get_jsonp_wrap_text_dict(jsonp: bool, function_name: str) -> dict():
    """
    Gets the starting and ending text to use for the config file.
    If it is jsonp, it will have a function name and ()'s. If it is
    not (ie, regular json), it will have empty strings.
    """
    text_dict = {}
    if jsonp:
        text_dict["start"] = f"{function_name}("
        text_dict["end"] = ")"
    else:
        text_dict["start"] = ""
        text_dict["end"] = ""

    return text_dict

def write_json_file(file_path: str, jsonp: bool, function_name: str, content: str):
    wrap_text_dict = get_jsonp_wrap_text_dict(jsonp, function_name)
    wrapped_content = wrap_text_dict["start"] + content + wrap_text_dict["end"]

    with open(file_path, "w") as output_file:
        output_file.write(wrapped_content)

def write_window_js_file(file_path: str, window_var_name: str, content: str):
    wrapped_content = f"window.{window_var_name} = {content}"

    with open(file_path, "w") as output_file:
        output_file.write(wrapped_content)

def get_file_path(directory: str, filename_no_ext: str, jsonp: bool):
    file_ext = "jsonp" if jsonp else "json"
    filename = f"{filename_no_ext}.{file_ext}"

    file_path = os.path.join(directory, filename)

    return file_path

def read_jsonp(file: str) -> dict():
    """
    Reads the json content of the .json or .jsonp file. If the file is
    a .jsonp file, the function name and ()'s will be ignored.
    Params:
        file: str - The full path to the file.
    Returns:
        dict - The content of the .json or .jsonp file.
    """
    content = ""
    with open(file) as file_handle:
        content = file_handle.read()

    json_content = ""

    if file.endswith(".json"):
        json_content = content
    elif file.endswith(".jsonp"):
        open_paren_index = content.index("(")
        close_paren_index = content.rindex(")")
        json_content = content[open_paren_index + 1 : close_paren_index]
    else:
        raise ValueError(f"Unrecognized file extension for file {file}. Expected .json or .jsonp")

    result = json.loads(json_content)
    return result

def is_dataframe_grouped(df: pd.DataFrame) -> bool:
    index_names = df.index.names

    is_empty_index = len(index_names) == 1 and index_names[0] is None
    return not is_empty_index

def get_dataframe_grouped_columns(df: pd.DataFrame) -> list:
    return df.index.names

def get_string_columns(df: pd.DataFrame) -> list:
    char_cols = [c for c in df.columns if is_string_column(df[c])]
    return char_cols

def get_string_or_factor_columns(df: pd.DataFrame) -> list:
    char_cols = [c for c in df.columns if is_string_column(df[c]) or df[c].dtype == "category"]
    return char_cols

def get_numeric_columns(df: pd.DataFrame) -> list:
    return list(df.select_dtypes('number'))

def get_uniquely_identifying_cols(df: pd.DataFrame) -> list:
    unique_key_cols = []

    # Try all columns, beginning with characters
    char_cols = get_string_columns(df)
    numeric_cols = get_numeric_columns(df)
    all_cols = char_cols + numeric_cols

    key_cols = []

    for col in all_cols:
        key_cols.append(col)

        if df.set_index(key_cols).index.is_unique:
            # This set of key_cols uniquely identifies the rows
            unique_key_cols = key_cols
            break

    return unique_key_cols

def is_string_column(column: pd.Series):
    """
    Checks to see if the provided column (Pandas Series) is a string datatype,
    including checking that it is not a Figure object.
    """
    is_string = False

    if is_string_dtype(column) and not is_categorical_dtype(column):
        # This is a "string dtype" but that could include other types of
        # objects such as a plotly `Figure`, so verify that the first value
        # is actually a string.
        if type(column[0]) == str:
            is_string = True

    return is_string


from glob import glob

IMAGES = glob('planets_fotos/*.jp*g')

#функция подсчета слов в фразе
def wordcount_func(frase):
    if len(frase) ==0:
        return 'no text'
    elif '"' == frase[0] == frase[-1]:
        return len(frase.strip('"').split())
    else:
        return 'Что то не так... Может ковычки забыли ?'

# не используется
'''
def easy_calc(expression):
    if len(expression) == 0:
        return 'Пустое выражение'
    elif expression[-1] != '=':
        return 'забыли "=" на конце :('
    try:
        return eval(expression.strip('='))
    except NameError:
        return 'Упс, ошибочка вышла. Вводить нужно только числа'
    except ZeroDivisionError:
        return 'Разве в школе не учили, что на ноль делить нельзя?!'
'''

# не используется
'''
def word_calc(expression):
    operators = {'plus': '+', 'minus': '-', 'devide': '/', 'multiple': '*'}
    # тут тоже нужны проверки, но для экономии времени на них забъю... и так все понятно
    expression = expression.strip('!.,# ').split()
    new_expression = ''
    for i in expression:
        if i in operators:
            new_expression += operators[i]
        else: new_expression += i
        new_expression += ' '
    try:
        return eval(new_expression)
    except NameError:
        return 'Упс, ошибочка вышла. Вводить нужно только числа'
    except ZeroDivisionError:
        return 'Разве в школе не учили, что на ноль делить нельзя?!'

'''

if __name__ == '__main__':
    #print(wordcount_func(input('пиши что нибудь: ')))
    print(IMAGES)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('project', '0053_auto_20150722_0413'),
    ]

    operations = [
        migrations.AlterField(
            model_name='project',
            name='project_status',
            field=models.CharField(default=b'DR', max_length=2, choices=[(b'AC', b'Active'), (b'ST', b'Staged'), (b'PR', b'Proposed'), (b'CO', b'Completed'), (b'DR', b'Drafted')]),
            preserve_default=True,
        ),
    ]


from django.db import models
from django.utils import timezone
from datetime import timedelta
from django.contrib.auth.models import AbstractUser, Group

class Insurance(models.Model):
    policy_number = models.CharField(max_length=200, null=True)
    company = models.CharField(max_length=200, null=True)

    def __repr__(self):
        return "{0} with {1}".format(self.policy_number, self.company)

class EmergencyContact(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    phone_number = models.CharField(max_length=30)
    relationship = models.CharField(max_length=30)

class MedicalInformation(models.Model):
    SEX_CHOICES = (
        'Female',
        'Male',
        'Intersex',
    )
    sex = models.CharField(max_length=50)
    insurance = models.ForeignKey(Insurance,on_delete=models.CASCADE, null=True)
    medications = models.CharField(max_length=200, null=True)
    allergies = models.CharField(max_length=200, null=True)
    medical_conditions = models.CharField(max_length=200, null=True)
    family_history = models.CharField(max_length=200, null=True)
    additional_info = models.CharField(max_length=400, null=True)

    def __repr__(self):
        return (("Sex: {0}, Insurance: {1}, Medications: {2}, Allergies: {3}, " +
                "Medical Conditions: {4}, Family History: {5}," +
                " Additional Info: {6}").format(
                    self.sex, repr(self.insurance), self.medications,
                    self.allergies, self.medical_conditions,
                    self.family_history, self.additional_info
                ))

class Hospital(models.Model):
    name = models.CharField(max_length=200)
    address = models.CharField(max_length=200)
    city = models.CharField(max_length=200)
    state = models.CharField(max_length=2)
    zipcode = models.CharField(max_length=20)

    def __repr__(self):
        # "St. Jude Hospital at 1 Hospital Road, Waterbury, CT 06470"
        return ("%s at %s, %s, %s %s" % self.name, self.address, self.city,
                self.state, self.zipcode)

class DoctorInformation(models.Model):
    specialisation = models.CharField(max_length=100,null=True)
    years_of_experience = models.CharField(max_length=2,null=True)
    fee = models.CharField(max_length=5,null=True)
    degree = models.CharField(max_length=200,null=True)
    visit_days = models.CharField(max_length=200,null=True)
    two_shift = models.CharField(max_length=10,null=True)
    first_shift_start = models.CharField(max_length=10,null=True)
    first_shift_end = models.CharField(max_length=10,null=True)
    second_shift_start = models.CharField(max_length=10,null=True)
    second_shift_end = models.CharField(max_length=10,null=True)

    VISIT_DAYS = (
        'Monday',
        'Tuesday',
        'Wednesday',
        'Thursday',
        'Friday',
        'Saturday',
        'Sunday',
    )

    SPECIALISATION = (
        'Dentist',
        'Gynecologist/Obstetrician',
        'General Physician',
        'Dermatologist',
        'Ear-Nose-Throat(ENT)',
        'Homoeopath',
        'Ayurveda',
    )

    TWO_DAYS_SHIFT = (
        'Yes',
        'No',
    )

    def __repr__(self):
        return (("specialisation: {0}, years_of_experience: {1}, fee: {2}, degree: {3}, " +
                "visit_days : {4}, two_shift: {5}," +
                "first_shift_start: {6}, first_shift_end: {7}" +
                "second_shift_start: {8}, second_shift_end: {9}").format(
                    self.specialisation, self.years_of_experience,
                    self.fee, self.degree, self.visit_days, self.two_shift,
                    self.first_shift_start, self.first_shift_end,
                    self.second_shift_start,self.second_shift_end
                ))

class User(AbstractUser):
    date_of_birth = models.DateField(null=True)
    phone_number = models.CharField(max_length=30)
    medical_information = models.ForeignKey(MedicalInformation, null=True,on_delete=models.CASCADE)
    emergency_contact = models.ForeignKey(EmergencyContact, null=True,on_delete=models.CASCADE)
    hospital = models.ForeignKey(Hospital,null=True,on_delete=models.CASCADE)
    doctor_information = models.ForeignKey(DoctorInformation,null=True,on_delete=models.CASCADE)

    REQUIRED_FIELDS = ['phone_number', 'email', 'first_name',
                       'last_name']

    def all_patients(self):
        """
        Returns all patients relevant for a given user.
        If the user is a doctor:
            Returns all patients with active appointments with the doctor.
        If the user is a patient:
            Returns themself.
        If the user is an admin:
            Returns all patients in the database.
        :return:
        """
        if self.is_superuser or self.is_doctor():
            # Admins and doctors can see all users as patients.
            return Group.objects.get(name='Patient').user_set.all()
        else:
            # Users can only see themselves.
            return User.objects.filter(pk=self.pk)

    def can_edit_user(self, user):
        return user == self      \
            or self.is_superuser \
            or user.is_patient() \
            and self.is_doctor()

    def active_patients(self):
        """
        Same as all_patients, but only patients that are active.
        :return: All active patients relevant to the current user.
        """
        return self.all_patients().filter(is_active=True)

    def schedule(self):
        """
        :return: All appointments for which this person is needed.
        """
        if self.is_superuser:
            return Appointment.objects
        elif self.is_doctor():
            # Doctors see all appointments for which they are needed.
            return Appointment.objects.filter(doctor=self)
        # Patients see all appointments
        return Appointment.objects.filter(patient=self)

    def upcoming_appointments(self):
        date = timezone.now()
        start_week = date - timedelta(date.weekday())
        end_week = start_week + timedelta(7)
        return self.schedule().filter(date__range=[start_week, end_week])

    def is_patient(self):
        """
        :return: True if the user belongs to the Patient group.
        """
        return self.is_in_group("Patient")

    def is_doctor(self):
        """
        :return: True if the user belongs to the Doctor group.
        """
        return self.is_in_group("Doctor")

    def is_in_group(self, group_name):
        """
        :param group_name: The group within which to check membership.
        :return: True if the user is a member of the group provided.
        """
        try:
            return (Group.objects.get(name=group_name)
                         .user_set.filter(pk=self.pk).exists())
        except ValueError:
            return False

    def group(self):
        return self.groups.first()

    def is_free(self, date, duration):
        """
        Checks the user's schedule for a given date and duration to see if
        the user does not have an appointment at that time.
        :param date:
        :param duration:
        :return:
        """
        schedule = self.schedule().all()
        end = date + timedelta(minutes=duration)
        for appointment in schedule:
            # If the dates intersect (meaning one starts while the other is
            # in progress) then the person is not free at the provided date
            # and time.
            if (date <= appointment.date <= end or
                    appointment.date <= date <= appointment.end()):
                return False
        return True

class Appointment(models.Model):
    patient = models.ForeignKey(User, related_name='patient_appointments',on_delete=models.CASCADE)
    doctor = models.ForeignKey(User, related_name='doctor_appointments',on_delete=models.CASCADE)
    date = models.DateTimeField()
    duration = models.IntegerField()

    def end(self):
        """
        :return: A datetime representing the end of the appointment.
        """
        return self.date + timedelta(minutes=self.duration)

    def __repr__(self):
        return '{0} minutes on {1}, {2} with {3}'.format(self.duration, self.date,
                                                         self.patient, self.doctor)


#!/usr/bin/env python3

import re

def CleanLyrics(lyrics : str) -> str:
    # remove string seemingly random inserted into some lyric pulls
    lyrics = lyrics.replace("You might also like", "")

    # remove the top 'Lyrics'
    lyrics = (re.search(r"(?<=Lyrics)[^*]*", lyrics)).group(0)

    # remove the footer embed
    lyrics = re.sub(r"[\d]*(?=Embed)\w*", "", lyrics)

    # remove '[]'s
    lyrics = re.sub(r"\[.*?\]", "", lyrics)

    # clean empty newlines
    lyrics = re.sub(r"(?<=\n)\s+", "", lyrics)

    return lyrics[:75]


import streamlit as st
state = st.session_state
import pandas as pd
import base64
import requests
from scripts import tools

tools.page_config()
tools.get_data()

head_cols = st.columns((7,2,1))
with head_cols[0]:
    st.write('# Good for your heart foods')
    st.write('A guide to heart healthy vegetarian foods that can help to lower blood pressure.')
with head_cols[1]:
    st.image(tools.round_corners('res/head_img.jpg'), width=400)

st.write('## Raw foods')
rf_cols = st.columns((5,1))
with rf_cols[0]:
    st.write('*See the nutritional value of some common foods. The progress bar displays the value in relation to the other foods in the list. Click any column header to change the sort order.*')
with rf_cols[1]:
    hide_pb_rf = st.checkbox('Hide progress bars', key="hide_pb_rf")

if hide_pb_rf:
    st.dataframe(state.ing_df, use_container_width=True)
else:
    st.data_editor(state.ing_df,column_config={
                c: st.column_config.ProgressColumn(
                format="%f", min_value=float(state.ing_df[c].min()),
                max_value=float(state.ing_df[c].max())) for c in state.ing_df},
                use_container_width=True)

st.write('## Prepared foods')
meal_tabs1, meal_tabs2 = st.tabs(['Nutritional value', 'Recipe ideas'])

with meal_tabs1:

    pf_cols = st.columns((5,1))
    with pf_cols[0]:
        st.write('*See the nutritional value of some prepared foods. The progress bar displays the value in relation to the other foods in the list. Click any column header to change the sort order.*')
    with pf_cols[1]:
        hide_pb_pf = st.checkbox('Hide progress bars', key="hide_pb_pf")

    if hide_pb_pf:
        st.dataframe(state.prep_df, use_container_width=True)
    else:
        st.data_editor(state.prep_df,column_config={
                    c: st.column_config.ProgressColumn(
                    format="%d", min_value=float(state.prep_df[c].min()),
                    max_value=float(state.prep_df[c].max())) for c in state.prep_df},
                    use_container_width=True)

with meal_tabs2:

    st.write('## Meal ideas')
    ing_search_cols = st.columns((3,1,4))
    with ing_search_cols[0]:
        ing_filter = st.text_input('*Filter by ingredient (separate multiple ingredients with a comma)*',
                                    key="ing_filter")
    if ing_filter.strip() != '':
        ings = ing_filter.split(',')

        try:
            ings = [tools.get_lemma(i) for i in ings]
        except:
            pass

        conditions = [state.meals_df['ingredients'].str.contains(i.strip(), case=False) for i in ings]
        state.meals_df_filtered = state.meals_df[pd.DataFrame(conditions).all(axis=0)]

        # state.meals_df = state.meals_df[
        #                 state.meals_df.ingredients.str.contains('|'.join([i.strip() \
        #                 for i in ing_filter.split(',')]), case=False)]
    else:
        state.meals_df_filtered = state.meals_df
    with ing_search_cols[1]:
        st.button("clear text input", on_click=tools.clear_text)

    meal_cols = st.columns(4)
    ct = 0
    for i,r in state.meals_df_filtered.iterrows():

        with meal_cols[ct]:
            try:
                img = requests.get(r.image)
                img.raise_for_status()  # Check if the request was successful
                thumb = img.content
            except requests.RequestException as e:
                print(f"Error fetching the image: {e}")
            st.markdown(
                    f"""

{r.meal}
""",unsafe_allow_html=True,)

            # st.write(html, unsafe_allow_html=True)
            if ct < 3:
                 ct += 1
            else:
                ct = 0

with st.expander('Sources'):
    st.write('Dataset: Food suitable for diabetes and blood pressure. [https://www.kaggle.com/datasets/nandagopll/food-suitable-for-diabetes-and-blood-pressure](https://www.kaggle.com/datasets/nandagopll/food-suitable-for-diabetes-and-blood-pressure)')


from geolocation import LocationError
from models import Location
import pytest

def test_location_latlong_gettering():
    location = Location(city_name="campinas", uf="sp")
    location.load_lat_lon()
    assert pytest.approx(location.lat, 0.01) == -22.89
    assert pytest.approx(location.lon, 0.01) == -47.10

def test_location_invalid_raises_error():
    location = Location(city_name="a test not a city", uf="sp")
    with pytest.raises(LocationError) as execinfo:
        location.load_lat_lon()
    assert "Geolocation not found" in str(execinfo.value)


import os
import csv
import re
from django.core.management import BaseCommand
from ifbcat_api.models import Credit
from ifbcat_api.models import Service
from ifbcat_api.models import ElixirCommunities
from ifbcat_api.models import Publication
from ifbcat.settings import BASE_DIR

class Command(BaseCommand):
    def import_service_from_csv_file(self):
        data_folder = os.path.join(BASE_DIR, './import_data')
        Service.objects.all().delete()
        Credit.objects.all().delete()
        ElixirCommunities.objects.all().delete()
        Publication.objects.all().delete()
        print(data_folder, 'data_folder')
        for data_file in os.listdir(data_folder):
            # name of the correct csv file
            if data_file == "services.csv":
                with open(os.path.join(data_folder, data_file), encoding='utf-8') as data_file:
                    data = csv.reader(data_file)
                    # skip first line as there is always a header
                    next(data)
                    # do the work
                    for data_object in data:
                        if data_object == []:
                            continue  # Check for empty lines
                        credit_list = []
                        service_name = data_object[0]
                        credit_name = data_object[1]

                        credit_laboratory = data_object[2]
                        credit_institute = data_object[3]
                        credit_adress = data_object[4]
                        credit_email = data_object[5]
                        try:

                            credit1, created = Credit.objects.get_or_create(
                                name=credit_name,
                                laboratory=credit_laboratory,
                                institute=credit_institute,
                                adress=credit_adress,
                                email=credit_email,
                            )

                            credit1.save()
                            credit_list.append(credit1)
                            display_format = "\nCredit, {}, has been saved."
                            print(display_format.format(credit1))
                        except Exception as ex:
                            print(str(ex))
                            msg = "\n\nSomething went wrong saving this credit: {}\n{}".format(credit1, str(ex))
                            print(msg)

                        credit_name2 = data_object[6]
                        credit_laboratory2 = data_object[7]
                        credit_institute2 = data_object[8]
                        credit_adress2 = data_object[9]
                        credit_email2 = data_object[10]
                        if data_object[6] != " ":

                            try:
                                credit2, created = Credit.objects.get_or_create(
                                    name=credit_name2,
                                    laboratory=credit_laboratory2,
                                    institute=credit_institute2,
                                    adress=credit_adress2,
                                    email=credit_email2,
                                )

                                credit2.save()
                                credit_list.append(credit2)
                                display_format = "\nCredit, {}, has been saved."
                                print(display_format.format(credit2))
                            except Exception as ex:
                                print(str(ex))
                                msg = "\n\nSomething went wrong saving this credit: {}\n{}".format(credit2, str(ex))
                                print(msg)

                        service_scope = data_object[11]

                        category = data_object[12]
                        category2 = category.split("\n")
                        service_is_tool = False
                        service_is_data = False
                        service_is_training = False
                        service_is_compute = False
                        service_is_interoperability = False
                        for category3 in category2:
                            if category3 == "Tool":
                                service_is_tool = True
                            elif category3 == "Data":
                                service_is_data = True
                            elif category3 == "Training":
                                service_is_training = True
                            elif category3 == "Compute":
                                service_is_compute = True
                            elif category3 == "Interoperability":
                                service_is_interoperability = True
                        service_description = data_object[13]
                        service_communities = data_object[14]
                        elixir_communities_name_bis = data_object[15]
                        elixir_communities_name = elixir_communities_name_bis.split("\n")
                        elixir_communities_list = []
                        elixir_community = ""
                        for community in elixir_communities_name:
                            if len(community) > 4:

                                try:

                                    elixir_community, created = ElixirCommunities.objects.get_or_create(
                                        name=community,
                                    )
                                    elixir_community.save()
                                    elixir_communities_list.append(elixir_community)
                                    display_format = "\nElixirCommunities, {}, has been saved."
                                    print(display_format.format(elixir_community))
                                except Exception as ex:
                                    print(str(ex))
                                    msg = "\n\nSomething went wrong saving this Elixir_communities: {}\n{}".format(
                                        elixir_community, str(ex)
                                    )
                                    print(msg)

                        service_year_created = data_object[16]
                        service_maturity = data_object[17].upper()
                        service_access = data_object[18]
                        service_quality = data_object[19]
                        service_usage = data_object[20]
                        service_publication_citations_nb = data_object[21]
                        service_publication_coauthor_nb = data_object[22]
                        publications_doi = []
                        doi = data_object[23]
                        doi_split = doi.split("\n")
                        for line in doi_split:
                            match = re.findall(r'(10.[0-9]{4,9}[A-Za-z0-9:;\)\(_/.-]+)', line)
                            if str(match) != '[]':
                                try:

                                    publication, created = Publication.objects.get_or_create(
                                        doi=str(match).strip('[]').strip('\'\''),
                                    )

                                    publication.save()
                                    publications_doi.append(publication)
                                except Exception as ex:
                                    print(str(ex))
                                    msg = "\n\nSomething went wrong saving this publication: {}\n{}".format(
                                        publication, str(ex)
                                    )
                                    print(msg)
                            else:
                                continue

                        service_sab_user_comittee = data_object[25]
                        service_term_of_use = data_object[26]
                        service_ethics_policy = data_object[27]
                        service_funding = data_object[28]
                        motivation = data_object[29]
                        motivation_split = motivation.split("\n")
                        for motivations in motivation_split:
                            if motivations == "be registered in the IFB catalogue of tools":
                                service_motivation_catalog = True
                            if motivations == "be registered as an ELIXIR service (in its SDP)":
                                service_motivation_sdp = True
                        service_motivation_support_ifb_it = False
                        service_motivation_support_ifb_curation = False
                        service_motivation_support_ifb_core_resource = False
                        support = data_object[30]
                        support_split = support.split("\n")
                        for supports in support_split:
                            if supports == "IT support (computation/storage)":
                                service_motivation_support_ifb_it = True
                            elif supports == "curation (tools and network of experts)":
                                service_motivation_support_ifb_curation = True
                            elif supports == "support for the application to become an ELIXIR core resource":
                                service_motivation_support_ifb_core_resource = True

                        service = ""
                        try:

                            service, created = Service.objects.get_or_create(
                                name=service_name,
                                scope=service_scope,
                                is_tool=service_is_tool,
                                is_data=service_is_data,
                                is_training=service_is_training,
                                is_compute=service_is_compute,
                                is_interoperability=service_is_interoperability,
                                description=service_description,
                                communities=service_communities,
                                year_created=service_year_created,
                                maturity=service_maturity,
                                access=service_access,
                                quality=service_quality,
                                usage=service_usage,
                                publication_citations_nb=service_publication_citations_nb.replace(",", ""),
                                publication_coauthor_nb=service_publication_coauthor_nb.replace(",", ""),
                                sab_user_comittee=service_sab_user_comittee,
                                term_of_use=service_term_of_use,
                                ethics_policy=service_ethics_policy,
                                funding=service_funding,
                                motivation_catalog=service_motivation_catalog,
                                motivation_sdp=service_motivation_sdp,
                                motivation_support_ifb_it=service_motivation_support_ifb_it,
                                motivation_support_ifb_curation=service_motivation_support_ifb_curation,
                                motivation_support_ifb_core_resource=service_motivation_support_ifb_core_resource,
                            )

                            if created:
                                service.save()

                                display_format = "\nService, {}, has been saved."
                                print(display_format.format(service))
                                for credit_service in credit_list:
                                    service.credit.add(credit_service)
                                    print(credit_service)
                                for service_elixir_community in elixir_communities_list:
                                    service.elixir_communities.add(service_elixir_community)
                                for service_pub in publications_doi:
                                    service.key_pub.add(service_pub)

                                service.save()

                        except Exception as ex:
                            print(str(ex))
                            msg = "\n\nSomething went wrong saving this service: {}\n{}".format(service, str(ex))
                            print(msg)

    def handle(self, *args, **options):
        """
        Call the function to import data
        """
        self.import_service_from_csv_file()


import unittest, h5py, submitted
from gradescope_utils.autograder_utils.decorators import weight
import numpy as np

# TestSequence
class TestStep(unittest.TestCase):
    def setUp(self):
        self.h5 = h5py.File('solutions.hdf5','r')
        with h5py.File('data.hdf5','r') as f:
            self.sfreq = f['sfreq'][0]
            self.onesecond = f['onesecond'][:]
        self.filterlength = 1
        self.evenlength = 200
        self.oddlength = 201
        self.omegaL = 0.785398163397448

    @weight(7.15)
    def test_lpf_even(self):
        h_even = submitted.todo_lpf_even(self.evenlength, self.omegaL)
        e = np.sum(np.abs(h_even-self.h5['h_even']))/np.sum(np.abs(self.h5['h_even']))
        self.assertTrue(e < 0.04, 'todo_lpf_even wrong by more than 4% (visible case)')

    @weight(7.15)
    def test_lpf_odd(self):
        h_odd = submitted.todo_lpf_odd(self.oddlength, self.omegaL)
        e = np.sum(np.abs(h_odd-self.h5['h_odd']))/np.sum(np.abs(self.h5['h_odd']))
        self.assertTrue(e < 0.04, 'todo_lpf_odd wrong by more than 4% (visible case)')

    @weight(7.14)
    def test_h_theta(self):
        h_theta = submitted.todo_h_theta(self.sfreq, self.filterlength)
        e = np.sum(np.abs(h_theta-self.h5['h_theta']))/np.sum(np.abs(self.h5['h_theta']))
        self.assertTrue(e < 0.04, 'todo_h_theta wrong by more than 4% (visible case)')

    @weight(7.14)
    def test_convolve(self):
        h_theta = self.h5['h_theta']
        thetawaves = submitted.todo_convolve(self.onesecond, h_theta)
        e = np.sum(np.abs(thetawaves-self.h5['thetawaves']))/np.sum(np.abs(self.h5['thetawaves']))
        self.assertTrue(e < 0.04, 'todo_convolve wrong by more than 4% (visible case)')

    @weight(7.14)
    def test_h_alpha(self):
        h_alpha = submitted.todo_h_alpha(self.sfreq, self.filterlength)
        alphawaves = submitted.todo_convolve(self.onesecond, h_alpha)
        e = np.sum(np.abs(h_alpha-self.h5['h_alpha']))/np.sum(np.abs(self.h5['h_alpha']))
        self.assertTrue(e < 0.04, 'todo_h_alpha wrong by more than 4% (visible case)')
        e = np.sum(np.abs(alphawaves-self.h5['alphawaves']))/np.sum(np.abs(self.h5['alphawaves']))
        self.assertTrue(e < 0.04, 'todo_h_alpha alphawaves by more than 4% (visible case)')

    @weight(7.14)
    def test_h_beta(self):
        h_beta = submitted.todo_h_beta(self.sfreq, self.filterlength)
        betawaves = submitted.todo_convolve(self.onesecond, h_beta)
        e = np.sum(np.abs(h_beta-self.h5['h_beta']))/np.sum(np.abs(self.h5['h_beta']))
        self.assertTrue(e < 0.04, 'todo_h_beta wrong by more than 4% (visible case)')
        e = np.sum(np.abs(betawaves-self.h5['betawaves']))/np.sum(np.abs(self.h5['betawaves']))
        self.assertTrue(e < 0.04, 'todo_h_beta betawaves by more than 4% (visible case)')

    @weight(7.14)
    def test_h_gamma(self):
        h_gamma = submitted.todo_h_gamma(self.sfreq, self.filterlength)
        gammawaves = submitted.todo_convolve(self.onesecond, h_gamma)
        e = np.sum(np.abs(h_gamma-self.h5['h_gamma']))/np.sum(np.abs(self.h5['h_gamma']))
        self.assertTrue(e < 0.04, 'todo_h_gamma wrong by more than 4% (visible case)')
        e = np.sum(np.abs(gammawaves-self.h5['gammawaves']))/np.sum(np.abs(self.h5['gammawaves']))
        self.assertTrue(e < 0.04, 'todo_h_gamma gammawaves by more than 4% (visible case)')


import os

from flask import Flask
from flask import render_template
from flask_bootstrap import Bootstrap5

from . import db

def create_app(test_config=None):
    app = Flask(__name__, instance_relative_config=True)
    Bootstrap5(app)

    app.config.from_mapping(
        SECRET_KEY='dev',
        DATABASE=os.path.join(app.instance_path, 'next.sqlite'),
    )

    if test_config is None:
        app.config.from_pyfile('config.py', silent=True)
    else:
        app.config.from_mapping(test_config)

    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    db.init_app(app)

    @app.route('/')
    def index():
        name = 'Library "3 Books"'
        return render_template('enter.html', name=name)

    return app


from PyQt5.QtCore import pyqtSignal, pyqtSlot
import fileFunctions
import tableFunctions
import forms

class Inventory:
    def __init__(self, home_window):
        self.part_list_file = "../Inventory/part_list.csv"
        self.product_list_file = "../Inventory/products.json"
        self.home_window = home_window
        self.balance_sheet = self.home_window.balance_sheet
        self.income_statement = self.home_window.income_statement
        self.inventory_table = self.home_window.inventory_table
        self.products_table = self.home_window.products_table
        self.add_part_btn = self.home_window.add_part_btn
        self.vendor_list = self.home_window.vendor_list
        self.build_robots_btn = self.home_window.build_robots_btn
        self.sell_robots_btn = self.home_window.sell_robots_btn
        self.purchase_inventory_btn = self.home_window.purchase_inventory_btn
        self.add_part_btn.clicked.connect(self.launchAddPartForm)
        self.build_robots_btn.clicked.connect(self.launchBuildRobotsForm)
        self.sell_robots_btn.clicked.connect(self.launchSellRobotsForm)
        self.purchase_inventory_btn.clicked.connect(self.launchPurchasePartsForm)
        self.readInParts()
        self.updateTable()

        self.products = fileFunctions.loadJSON(self.product_list_file)
        self.updateProductsTable()

        self.updateBalanceSheetInventory()

    def readInParts(self):
        self.inventory_df = fileFunctions.readCSV(self.part_list_file)
        self.headers = list(self.inventory_df.columns)

    def launchAddPartForm(self):
        #self.add_part_btn.setEnabled(False)
        vendor_name_list = self.vendor_list.getListOfNames()
        self.add_form = forms.AddPart(self, vendor_name_list)
        self.add_form.submit_signal.connect(self.updateTable)
        self.add_form.show()

    def launchBuildRobotsForm(self):
        product_list = self.products.keys()
        self.build_robots_form = forms.BuildRobots(self, product_list)
        self.build_robots_form.submit_signal.connect(self.updateAllTables)
        self.build_robots_form.show()

    def launchSellRobotsForm(self):
        product_list = self.products.keys()
        self.sell_robots_form = forms.SellRobots(self, product_list)
        self.sell_robots_form.submit_signal.connect(self.updateAllTables)
        self.sell_robots_form.show()

    def launchPurchasePartsForm(self):
        parts_list = self.inventory_df.part_name.to_list()
        self.purchase_parts_form = forms.PurchaseParts(self, parts_list)
        self.purchase_parts_form.submit_signal.connect(self.updateAllTables)
        self.purchase_parts_form.show()

    def addPart(self, part_name="", part_number="", unit_price="", vendor=""):
        new_part_dict = \
            {
                "part_name" : part_name,
                "count": 0,
                "part_number" : part_number,
                "unit_price" : unit_price,
                "vendor" : vendor
            }
        self.inventory_df = self.inventory_df.append(new_part_dict, ignore_index=True)
        return True

    def calculateCOGS(self, product):
        parts = self.products[product]["parts"]
        cogs = 0
        for part in parts:
            part_num = int(part) - 1
            quantity = float(parts[part])
            unit_price = self.inventory_df.unit_price[part_num]
            cogs += unit_price * quantity
        return cogs

    def checkCash(self, price):
        balance = self.balance_sheet["current assets"]["cash"]
        if price > balance:
            return False
        return True

    def purchaseParts(self, part_num=0, quantity=0):
        unit_price = self.inventory_df.unit_price[part_num]
        total_price = unit_price * quantity
        if self.checkCash(total_price) == False:
            return False

        self.inventory_df.at[part_num, "count"] += quantity
        self.balance_sheet["short term liabilities"]["payables"] += total_price
        self.updateBalanceSheetInventory()
        return True

    def checkInventory(self, product, quantity):
        parts = self.products[product]["parts"]
        for part in parts:
            part_num = int(part) - 1
            quantity_for_one = float(parts[part])
            available = self.inventory_df["count"][part_num]
            ask = quantity_for_one * quantity
            if ask > available:
                return False
        return True

    def subtractInventory(self, product, quantity):
        parts = self.products[product]["parts"]
        for part in parts:
            part_num = int(part) - 1
            available = self.inventory_df.at[part_num, "count"]
            ask = parts[part] * quantity
            new_quantity = available - ask
            self.inventory_df.at[part_num, "count"] = new_quantity

    def calculatePartsValue(self):
        value = 0
        for idx, part in self.inventory_df.iterrows():
            price = part.unit_price
            quantity = part["count"]
            value += price * quantity
        return value

    def calculateProductValue(self):
        value = 0
        for product in self.products:
            sale_price = self.products[product]["sale price"]
            quantity = self.products[product]["count"]
            value += sale_price * quantity
        return value

    def checkProductInventory(self, product, quantity):
        in_stock = self.products[product]["count"]
        if quantity > in_stock:
            return False
        return True

    def buildRobots(self, product="", quantity=0):
        if self.checkInventory(product, quantity) == False:
            return False

        self.products[product]["count"] += quantity
        self.subtractInventory(product, quantity)

        self.updateBalanceSheetInventory()
        return True

    def sellRobots(self, product="", quantity=0):
        if self.checkProductInventory(product, quantity) == False:
            return False

        self.products[product]["count"] -= quantity
        self.updateBalanceSheetInventory()

        total_sale = quantity * self.products[product]["sale price"]
        self.income_statement["revenue"][product] += total_sale
        self.balance_sheet["current assets"]["receivables"] = total_sale

        total_cogs = quantity * self.calculateCOGS(product)
        self.income_statement["cogs"][product] += total_cogs

        return True

    def updateBalanceSheetInventory(self):
        self.balance_sheet["current assets"]["inventory parts"] = self.calculatePartsValue()
        self.balance_sheet["current assets"]["inventory products"] = self.calculateProductValue()
        self.balance_sheet.updateAllInformation()

    def updateAllTables(self):
        self.updateTable()
        self.updateProductsTable()
        self.balance_sheet.updateAllInformation()
        self.income_statement.updateAllInformation()

    def updateTable(self):
        tableFunctions.setRowCount(self.inventory_table, self.inventory_df.shape[0])
        tableFunctions.setColumnCount(self.inventory_table, self.inventory_df.shape[1])
        tableFunctions.setHeaders(self.inventory_table, self.headers)
        for r, row in self.inventory_df.iterrows():
            for c, item in enumerate(row):
                tableFunctions.setItem(self.inventory_table, r, c, str(item))
        fileFunctions.writeCSV(self.inventory_df, self.part_list_file)

    def updateProductsTable(self):
        headers = ["name","count","sale price","cog"]
        tableFunctions.setRowCount(self.products_table, len(self.products))
        tableFunctions.setColumnCount(self.products_table, len(headers))
        tableFunctions.setHeaders(self.products_table, headers)
        for row, product in enumerate(self.products.keys()):
            count = self.products[product]["count"]
            sale_price = fileFunctions.formatCurrency(self.products[product]["sale price"])
            cog = fileFunctions.formatCurrency(self.calculateCOGS(product))
            tableFunctions.setItem(self.products_table, row, 0, product)
            tableFunctions.setItem(self.products_table, row, 1, str(count))
            tableFunctions.setItem(self.products_table, row, 2, sale_price)
            tableFunctions.setItem(self.products_table, row, 3, cog)
        fileFunctions.writeJSON(self.product_list_file, self.products)


import urllib.request
import json
import pprint  # module that makes it easier to print and look at dictionaries

# Challenge: write a program that prints all of the status updates

search_term = input('Please enter a search term (defaults to "northwestern"): ')
if search_term == '':
    search_term = 'Northwestern'
url = 'https://eecs110-twitter-proxy.herokuapp.com/1.1/search/tweets.json?q='
url += search_term
request = urllib.request.urlopen(url)
data = json.loads(request.read().decode())

pprint.pprint(data, depth=1)


import itertools
import numpy as np
import scipy.special as sp
from scipy import integrate

cutoff = 0
Q = 3
ThetaCut = np.pi

l_max = Q - 0.5 + cutoff
mm = [-l_max + i for i in range(int(2*l_max+1))]

def SLL_normalization(Q, l, m):
    # Normalization constant for the Spherical Landau Level
    # Only depends on the charge Q, Landau level l and angular momentum m
    return np.sqrt(((2*l+1)/(4*np.pi)) * sp.binom(2*l, l-Q)/sp.binom(2*l, l-m))

def SLL(theta, Q, l, m):
    # Spherical Landau Level
    # Q is the charge, l is the Landau level, m is the angular momentum
    # this function outputs the value (complex number) of the SLL wavefunction at a specified angular coordinate
    u = np.cos(theta/2)  # * np.exp(1j*phi/2)
    v = np.sin(theta/2)  # * np.exp(-1j*phi/2)
    pre = SLL_normalization(Q, l, m) * (-1)**(l-m) * \
        v**(Q-m) * u**(Q+m)  # part before the summation
    # part inside the summation
    sum_part = 0
    for s in range(0, int(l-m+1)):
        if (l-Q >= s) and (l+Q >= l-m-s):
            sum_part += (-1)**s * sp.binom(l-Q, s) * sp.binom(l+Q, l-m-s) * \
                (v*v)**(l-Q-s) * (u*u)**s
    wf = pre * sum_part  # total wavefunction
    return wf

def ThreeParticleSixTermsOI(theta,Q,l,m1,m2,m3,m4,m5,m6):
    wf1 = SLL(theta,Q,l,m1)
    wf2 = SLL(theta,Q,l,m2)
    wf3 = SLL(theta,Q,l,m3)
    wf4 = SLL(theta,Q,l,m4)
    wf5 = SLL(theta,Q,l,m5)
    wf6 = SLL(theta,Q,l,m6)

    x = 2 * np.pi * np.sin(theta) * (wf1 * wf2 * wf3 * wf4 * wf5 * wf6)

    return x

def ThreeParticleInteractionStrength(Q,l,m1,m2,m3,m4,m5,m6,ThetaCut):
    x = integrate.quad(ThreeParticleSixTermsOI,0,ThetaCut,args=(Q,l,m1,m2,m3,m4,m5,m6,))

    return x[0]

# All the indices for three-particle interactions at cutoff = 0
ThreIn = []
for m1, m2 in itertools.product(mm,mm):
    for m3,m4 in itertools.product(mm,mm):
        for m5 in mm:
            m6 = m1 + m2 + m3 - m4 - m5
            if abs(m6) <= l_max:
                ThreIn.append((m1,m2,m3,m4,m5,m6))
ThreIn = list(set(ThreIn))

OIlist = []
for am in ThreIn:

    m1 = am[0]
    m2 = am[1]
    m3 = am[2]
    m4 = am[3]
    m5 = am[4]
    m6 = am[5]
    OIlist.append(ThreeParticleInteractionStrength(l_max,l_max,m1,m2,m3,m4,m5,m6,ThetaCut))

np.savetxt("ThreeParticleIntegralsQ"+str(Q)+"cutoff"+str(0)+".dat",np.c_[ThreIn,OIlist],fmt="%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.8f")


import configparser
import logging
import re
from cgitb import text
from tkinter import NO, E

class Translator:
    def __init__(self) -> None:
        self.map = {}

    def _read_config(self) -> configparser.ConfigParser:
        config = configparser.ConfigParser()
        with open("./config/settings.cfg") as f:
            config_text = f.read()
            config.read_string(config_text)
        return config

    def _is_contain_chinese(self, word):
        pattern = re.compile(r"[\u4e00-\u9fa5]")
        match = pattern.search(word)
        return True if match else False

    def _get_cache(self, text):
        if self.map.__contains__(text):
            return self.map[text]
        else:
            return None

    def _cache(self, cn_text, en_text):
        if not self.map.__contains__(text):
            self.map[cn_text] = en_text

    def _cn2en(self, text):
        raise NotImplemented

    def cn2en(self, text):
        if not self._is_contain_chinese(text):
            return text
        if self._get_cache(text) is not None:
            return self._get_cache(text)
        try:
            en_text = self._cn2en(text)
            self._cache(text, en_text)
            text = en_text
        except Exception as e:
            logging.error(f"{text} translate error: {e}")
        return text


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

import time

class PokerHand:
    def __init__(self, hand):
        self.hand = hand

    def compare_with(self, opponent):
        #this function gives a ranking to each hand and compares the player's and oppentnt's the rankings
        # to determine the winner
        # input: oppenent
        # output: 0, 1 or 2, 0, 1, 2 stands for a tie, player wins and player loses respectively
        #
        #
        #print(self.cards);
        #print(opponent.cards);
        player_cardset = self.hand.split(' ');
        opponent_cardset = opponent.hand.split(' ')
        #print(player_cardset);
        #print(opponent_cardset);
        player_ranking, player_score, player_weight = PokerHand.ranking(player_cardset)
        opponent_ranking, opponent_score, opponent_weight = PokerHand.ranking(opponent_cardset)
        print(f"Player's hand -- {self.hand}, {player_ranking.upper()}, {player_weight}\n")
        print('.......\n')
        time.sleep(1)
        print(f"Opponent's hand -- {opponent.hand}, {opponent_ranking.upper()}, {opponent_weight}\n")

        if player_score > opponent_score:
            return 1 #player wins
        elif player_score < opponent_score:
            return 2 #player loses
        else:
            result = 0
            if player_score ==10:
                return 0 #royal flush
            else:
                for w1, w2 in zip(player_weight, opponent_weight):
                    if w1>w2:
                        result = 1;
                        break
                    elif w1<w2:
                        result =2 ;
                        break
            return result

    @staticmethod
    def ranking(player_cardset):
        #this function classifies the hand into a ranking and returns the classification result
        #to determine who is the winner
        #input: players' card set in a list
        #output: ranking, scores and weight list
        #   ranking: could be one of the following 10 rankings depending on the combination of the cards in one hand.
        #   score: the score of the ranking. Each ranking will be given a ranking score, varying from 1 (lowest) to 10 (highest).
        #           Ranking score is primarily used to determine the winner.
        #   weight list: list of numbers. When two hands are the same ranking, the weight list is used to determine the winner.
        #           *** Please be noted that the rule used in tie to determine the winner only apply to one deck.
        #               Some of them might not be able to apply to more than one deck game.
        #           For example, if two players get 3 of a kind. The player who has the highest value of triplets is the winner.
        #           In one-deck game, two hands of 3(or 4) of A kind with the same value of triplet (quadruplet) won't appear
        #           at the same time. Therefore, for 4 of A Kind, FULL HOUSE and 3 of A KIND tie situation,
        #           the value of quadruplet and triplet is enough to determine the winner.
        #           However, for two pairs, compare the values of two pairs and the the 5th card might be necessary .
        #           If these three values are the same, it is a tie.
        #The following is the list of 10 rankings(from the highest to lowest), ranking scores and weight lists
        #'ROYAL FLUSH', 10, []
        #'STRAIGHT FLUSH', 9, [highest value in 5 cards]
        #'4 of A KIND', 8, [value of quadruplet]
        #'FULL HOUSE', 7, [value of triplet]
        #'FLUSH', 6, [5 card values in descending order]
        #'STRAIGHT', 5, [highest value in 5 cards]
        #'3 of A Kind', 4, [value of triplet]
        #'2 PAIR', 3, [value of highest pair, value of the second pair, value of the 5th card ]
        #'1 PAIR', 2 [value of the pair, the values of the rest three cards in descending order]
        #'HIGH CARD', 1, [5 card values in descending order]

        player_card_val=[]
        is_flush = True
        first_suit = player_cardset[0][1]
        valDict ={'A':1, 'T':10, 'J':11, 'Q':12, 'K':13}
        for card in player_cardset:
            val = card[0]
            if  val.isdigit():
                val = int(val)
            else:
                val = valDict[val]
            player_card_val.append(val)
            if is_flush:
                is_flush = first_suit== card[1]

        is_straight = True
        max_step = len(player_card_val)
        min_val = min(player_card_val)
        if (1 in player_card_val) and (10 in player_card_val):
            min_val = 10
            max_step -=1

        for incre in range(1, max_step):
            if not (min_val+incre in player_card_val):
                is_straight = False
                break

        player_card_val.sort(reverse=True)

        if (is_straight or is_flush):
            if min(player_card_val)==1:
                if ((is_straight and (10 in player_card_val)) or \
                    (not is_straight and is_flush)):
                    player_card_val[player_card_val.index(1)]=14
            if is_straight and is_flush:
                if 14 in player_card_val:
                    return ('ROYAL FLUSH', 10, [])
                else:
                    return ('STRAIGHT FLUSH', 9, [max(player_card_val)])
            elif is_flush:
                player_card_val.sort(reverse=True)
                return('FLUSH', 6, player_card_val)
            elif is_straight:
                return('STRAIGHT', 5, [max(player_card_val)])
        else: #check pair
            unique_vals = list(set(player_card_val))
            repeated_number =[]
            for unique_val in unique_vals:
                repeated_number.append(player_card_val.count(unique_val))
            if min(unique_vals)==1:
                unique_vals[unique_vals.index(1)] = 14

            if len(repeated_number) ==2:
                if max(repeated_number)==4:
                    weight = [unique_vals[repeated_number.index(4)]]
                    return ('4 of A KIND', 8, weight)
                else:
                    weight = [unique_vals[repeated_number.index(3)]]
                    return ('FULL HOUSE', 7, weight)
            elif len(repeated_number) ==3:
                if max(repeated_number)==3:
                    return ('3 of A KIND', 4, [unique_vals[repeated_number.index(3)]])
                else:
                    last_val = unique_vals[repeated_number.index(1)];
                    unique_vals.remove(last_val)
                    weight =[max(unique_vals), min(unique_vals), last_val]
                    return ('2 PAIR', 3, weight)
            elif len(repeated_number) ==4:
                pair_val = unique_vals[repeated_number.index(2)];
                unique_vals.remove(pair_val)
                unique_vals.sort(reverse=True)
                unique_vals.insert(0,pair_val)
                return ('1 PAIR', 2, unique_vals)
            else:
                unique_vals.sort(reverse=True)
                return ('HIGH CARD', 1, unique_vals )


t = int(input())

def SQRT(N):
    end = 1
    while end * end < N:
        end *= 2
    beg = end // 2
    res = 1
    while beg <= end:
        mid = (beg + end) // 2
        if mid * mid <= N:
            res = mid
            beg = mid + 1
        else:
            end = mid - 1
    return res

for _ in range(t):
    n = int(input())
    if n == 1:
        print(0)
    else:
        print(SQRT(n))


class Solution1:
    def isAnagram(self, s: str, t: str) -> bool:
        if len(s) != len(t):
            return False

        # countS -> occurance of each character in string S
        # countT -> occurance of each character in string T
        # We want to know if S is an anagram for T
        #
        # We setting the Hashmaps for both these strings S and T
        countS, countT = {}, {} # HASHMAP S and T

        for i in range(len(s)):
            countS[s[i]] = 1 + countS.get(s[i], 0)
            countT[t[i]] = 1 + countT.get(t[i], 0)
        # key is s/t[i], we are setting the values using the get() method.
        # 0 is used for cases --->
        # ---------->  when a key exist in 'S' doesn't exist but not in T

        # now since we already have Hashmaps countS and countT
        # we can iterate through each keys in countS and check
        # whether that key has the same value as with the countT
        #
        # since if they are anagrams, they have to have / must have
        # the same number of values for each keys in both of their
        # Hashmaps
        for c in countS:
            if countS[c] != countT.get(c, 0):
                return False

        return True

#################################################################
##### Everything after this section is for testing purposes #####
#################################################################

def test_case_1():
    sol = Solution1()
    s = "listen"
    t = "silent"
    assert sol.isAnagram(s, t) == True

def test_case_2():
    sol = Solution1()
    s = "hello"
    t = "world"
    assert sol.isAnagram(s, t) == False

def test_case_3():
    sol = Solution1()
    s = "anmnagramgr"
    t = "nagmargrnam"
    assert sol.isAnagram(s, t) == True

def test_case_4():
    sol = Solution1()
    s = "hello"
    t = "ohhello"
    assert sol.isAnagram(s, t) == False

def test_case_5():
    sol = Solution1()
    s = ""
    t = ""
    assert sol.isAnagram(s, t) == True

def test_case_6():
    sol = Solution1()
    s = "iceman!"
    t = "!cinema"
    assert sol.isAnagram(s, t) == True

def test_case_7():
    sol = Solution1()
    s = "hello"
    t = "world!"
    assert sol.isAnagram(s, t) == False

if __name__ == "__main__":
    test_case_1()
    test_case_2()
    test_case_3()
    test_case_4()
    test_case_5()
    test_case_6()
    test_case_7()

    print("All test cases passed!")

################################################################
######################## END OF TESTING ########################
################################################################

0 BLIND/0 Arrays & Hashing/2 0242 Valid Anagram/Solution.py


# 숫자가 같은 배수

# 자연수 N이 있다. N의 10진법 표기(단, 0으로 시작하지 않도록 표기해야 함)에서 나타나는 숫자들을 재배열하여 N보다 큰 N의 배수(즉 2N, 3N, …, k•N, …) 를 만들 수 있는지 판단하는 프로그램을 작성하라.

# [입력]
# 첫 번째 줄에 테스트 케이스의 수 T가 주어진다.
# 각 테스트 케이스는 하나의 줄로 이루어진다. 각 줄에는 자연수 N (1 ≤N ≤ 106) 이 공백 하나를 사이로 두고 주어진다.

# [출력]
# 각 테스트 케이스마다, 주어진 자연수에 나타난 숫자들을 재배열하여 더 큰 배수를 만들 수 있다면 ‘possible’, 불가능하다면 ‘impossible’을 출력한다.

# 입력
# 3
# 142857
# 1
# 1035

# 출력
# #1 possible
# #2 impossible
# #3 possible

T = int(input())

for tc in range(1, T+1):

    N = input().strip()

    # 만약 N의 첫자리가 0인경우 재배열해도 배수를 만들 수 없기 때문에 바로 impossible 출력 후 다음 테스트 케이스 진행
    if N[0] == '0':
        print(f"#{tc} impossible")

    # '0'부터 '9'에 해당하는 딕셔너리 생성
    counts = {str(d):0 for d in range(10)}

    # N의 각 자리숫자 확인하며 counts 딕셔너리 해당 자리 값을 1씩 증가
    for digit in N:
        counts[digit] += 1

    # 가능 불가능 flag 변수 선언
    is_possible = False

    # 재배열하면서 N보다 큰 N의 배수를 만들기 위해 2 ~ 9에 해당하는 k를 N에 곱해주고 이를 candidate 변수에 문자열로 저장
    for k in range(2, 10):
        candidate = str(k * int(N))
        candidate_count = {str(d):0 for d in range(10)}

        # N과 k*N의 자리수가 다르다면 이는 재배열하여 N보다 큰 N의 배수를 만들 수 없는 경우
        # 다음 테스트 케이스 진행
        if len(candidate) != len(N):
            continue

        # k*N의 케이스의 자리수에 해당하는 값 증가
        for digit in candidate:
            candidate_count[digit] += 1

        # 원래 수와 k배수를 곱한 값의 모든 자리에서 같은 숫자들로 이루어져 있다면, 재배열 하여 N보다 큰 N의 배수로 만들 수 있는 경우
        # 이 경우에는 flag 변수를 True로 변경하고 종료
        if candidate_count == counts:
            is_possible = True
            break

    if is_possible:
        print(f"#{tc} possible")
    else:
        print(f"#{tc} impossible")


from PIL import Image
import requests
from io import BytesIO
import json

pages = json.load(open('bots/botpages.json', 'r'))

new_json = []

pageid = 1
for page in pages:
	dpurl = page["dp_link"]
	new_page_data = {}
	new_page_data["title"] = page["title"]
	new_page_data["fb_link"] = page["fb_link"]
	new_page_data["tags"] = page["tags"]
	new_page_data["dp_link"] = page["dp_link"]
	new_page_data["dp_id"] = "../pagedps/{}.png".format(pageid)
	if "github" in page:
		new_page_data["github"] = page["github"]
	new_json.append(new_page_data)

	response = requests.get(dpurl)
	try:
		img = Image.open(BytesIO(response.content))
	except:
		print("Link is dead; check the following page:")
		print(page["title"])
	img.thumbnail((80, 80))
	img.save("pagedps/{}.png".format(pageid), "PNG")

	print(str(pageid) + " done")
	pageid += 1

with open('bots/botpages.json', 'w') as outfile:
    json.dump(new_json, outfile)