import yaml
import argparse
from edgeutils import ApiSession

parser = argparse.ArgumentParser()
parser.add_argument('-s', '--segment_name', required=True,
                    help='Name of the host segment to modify.')
parser.add_argument('-H', '--hosts_list', required=True,
                    help='Name of the hosts to add to the segment. Comma separated list.',
                    type=str)
group = parser.add_mutually_exclusive_group()
group.add_argument('-u', '--update', action='store_true',
                    help='If host segment exists, merge hosts_list with list of existing hosts.')
group.add_argument('-f', '--force', action='store_true',
                    help='If host segment exists, replace existing hosts with hosts_list.')
args = parser.parse_args()

with open('config.yaml') as f:
    config = yaml.safe_load(f)

api = ApiSession(config)

# Get new hosts
hosts = api.get('agents')
arg_hosts_list = [x.strip().lower() for x in args.hosts_list.split(',')]
new_hosts = [{'id': x['id']} for x in hosts if x['name'].lower() in arg_hosts_list]

if not new_hosts:
    raise Exception('No hosts found for segment')

# Get segments
collections = api.get('collections')['content']
user_collections = [x for x in collections if x['owner'] == 'USER']
segments = [x for x in user_collections if x['query']['type'] == 'HOST']

# Get existing segment, if specified, else None
segment = next((x for x in segments if x['name'] == args.segment_name), None)

# Update/overwrite if exists else create segment
response = None
if segment:
    print("Existing segment '{}' found".format(args.segment_name))
    payload = {}

    # Update the segment if exists and update flag is True
    if args.update:
        print('Updating segment hosts list')
        r = api.get('scopes/{}/scope-data?scopeType=COLLECTION'.format(segment['id']))
        existing_hosts = [{'id': x['id']} for x in r['childScopes'] if x['type'] == 'HOST']
        all_hosts = [*existing_hosts, *new_hosts]
        payload = {'type': 'COLLECTION', 'id': segment['id'], 'name': args.segment_name, 'query': {'type': 'HOST', 'hosts': all_hosts}}

    # Overwrite the segment if exists and force flag is True
    elif args.force:
        print('Overwriting segment hosts list')
        payload = {'type': 'COLLECTION', 'id': segment['id'], 'name': args.segment_name, 'query': {'type': 'HOST', 'hosts': new_hosts}}

    # Error out if segment exists but no update or force flag set
    else:
        raise Exception('Existing segment found, modifying it requires either update or force flag but none set')

    # Execute the update/overwrite
    response = api.put('collections/{}'.format(segment['id']), payload)

else:
    # Create the new segment
    print("Segment '{}' does not exist\nCreating a new segment".format(args.segment_name))
    payload = {'type': 'COLLECTION', 'name': args.segment_name, 'dynamic': True, 'query': {'type': 'HOST', 'hosts': new_hosts}}
    response = api.post('collections', payload)

# Verify and print result
result_hosts = [x['name'].lower() for x in hosts if x['id'] in [y['id'] for y in response['query']['hosts']]]
print("Segment '{}' now contains hosts: {}".format(response['name'], sorted(result_hosts)))


import dask
import dask.dataframe

import pyarrow as pa

from .dataset import ReadConfig, Dataset

class ReadArgs(object):
    def __init__(
        self,
        uri,
        cfg,
        attrs,
        region_partitions,
        sample_partitions,
        samples,
        regions,
        samples_file,
        bed_file,
        fnc,
    ):
        self.uri = uri
        self.cfg = cfg
        self.attrs = attrs
        self.region_partitions = region_partitions
        self.sample_partitions = sample_partitions
        self.samples = samples
        self.regions = regions
        self.samples_file = samples_file
        self.bed_file = bed_file
        self.fnc = fnc

def _read_partition(read_args):
    table_fragments = []

    ds = Dataset(read_args.uri, "r", read_args.cfg)
    pyar = ds.read_arrow(
        attrs=read_args.attrs,
        samples=read_args.samples,
        regions=read_args.regions,
        samples_file=read_args.samples_file,
        bed_file=read_args.bed_file,
    )
    table_fragments.append(pyar)

    while not ds.read_completed():
        table_fragments.append(ds.continue_read_arrow(release_buffers=True))

    table = pa.concat_tables(table_fragments, promote=False)

    df = table.to_pandas()

    if read_args.fnc is not None:
        df = read_args.fnc(df)

    return df

def map_dask(
    self,
    fnc,
    attrs,
    region_partitions=1,
    sample_partitions=1,
    limit_partitions=None,
    samples=None,
    regions=None,
    samples_file=None,
    bed_file=None,
):
    """Maps a function on a Dask dataframe obtained by reading from the dataset.

    May be more efficient in some cases than read_dask() followed by a regular
    Dask map operation.

    The remaining parameters are the same as the read_dask() function.

    :return: Dask DataFrame with results
    """
    cfg = self.cfg if self.cfg is not None else ReadConfig()
    partitions = []
    for r in range(0, region_partitions):
        for s in range(0, sample_partitions):
            r_part = (r, region_partitions)
            s_part = (s, sample_partitions)
            cfg = cfg._replace(region_partition=r_part, sample_partition=s_part)
            read_args = ReadArgs(
                self.uri,
                cfg,
                attrs,
                region_partitions,
                sample_partitions,
                samples,
                regions,
                samples_file,
                bed_file,
                fnc,
            )
            partitions.append(dask.delayed(_read_partition)(read_args))

            if limit_partitions is not None and len(partitions) >= limit_partitions:
                break
        else:
            continue
        break

    return dask.dataframe.from_delayed(partitions)

def read_dask(
    self,
    attrs,
    region_partitions=1,
    sample_partitions=1,
    limit_partitions=None,
    samples=None,
    regions=None,
    samples_file=None,
    bed_file=None,
):
    """Reads data from a TileDB-VCF into a Dask DataFrame.

    Partitioning proceeds by a straightforward block distribution, parameterized
    by the total number of partitions and the particular partition index that
    a particular read operation is responsible for.

    Both region and sample partitioning can be used together.

    The remaining parameters are the same as the normal read() function.

    :param int region_partition: Number of partitions over regions
    :param int sample_partition: Number of partitions over samples
    :param int limit_partitions: Maximum number of partitions to read (for testing/debugging)

    :return: Dask DataFrame with results
    """

    return map_dask(
        self,
        None,
        attrs,
        region_partitions,
        sample_partitions,
        limit_partitions,
        samples,
        regions,
        samples_file,
        bed_file,
    )

# Patch functions and members into dataset class
Dataset.read_dask = read_dask
Dataset.map_dask = map_dask


import numpy as np
import cv2
import skimage.measure

def snr(image, ddof=0):
    """snr calculates the signal-to-noise ratio of an image.
    Input:  image
            ddof (default is 0)
    Output: snr of the image
    """
    array = np.asanyarray(image)
    array = (array - array.min()) / (array.max() - array.min())
    m = array.mean()
    std = array.std(ddof=ddof)

    return m, std

def my_cpp(image):
    """cpp is evaluating the contrast per pixel.
    Input:  image
    Output: cpp of the image
    """
    kernel = np.asarray([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])/8
    filtered_image = cv2.filter2D(image, -1, kernel)
    return np.mean(filtered_image)

def entropy(image, _min, _max, is_CT):
    """entropy calculates the entropy of a given image.
    Input:  Image
    Output: Entropy of the image
    """
    if is_CT:
        _min = -400
        _max = 600
    array = np.round(255*(np.asarray(image) - _min) / (_max - _min)).astype(int)
    return skimage.measure.shannon_entropy(image)

def statis_info(image, _min, _max, is_CT):
    """statis_info calculates the mean and the std of the given image.
    """
    if is_CT:
        _min = -400
        _max = 600
    array = (np.asarray(image) - _min) / (_max - _min)
    mean = np.mean(array)
    std = np.std(array)
    return mean, std


import random
import textwrap
import itertools
from pathlib import Path

import htmap

def mashup(first_book, second_book):
    first_text = first_book.read_text()
    second_text = second_book.read_text()

    first_words = first_text.split()
    second_words = second_text.split()

    words = []
    for first_word, second_word in zip(first_words, second_words):
        words.append(random.choice((first_word, second_word)))

    text = ' '.join(words)
    wrapped = textwrap.wrap(text)[100:-500]
    final = '\n'.join(wrapped)

    return final

if __name__ == "__main__":
    books_dir = htmap.TransferPath.cwd() / 'books'
    book_paths = list(books_dir.iterdir())

    with htmap.build_map(mashup, tag = 'mashups') as builder:
        for first_book, second_book in itertools.combinations(book_paths, r = 2):
            builder(first_book, second_book)

    m = builder.map
    print(m.tag)


from django.shortcuts import render
from django.views import View
from verifications.libs.captcha.captcha import captcha
from django_redis import get_redis_connection
from django import http
import random,logging

from . import constants
from meiduo.utils.response_code import RETCODE
from verifications.libs.yuntongxun.ccp_sms import CPP
# Create your views here.

# 创建日志输出器，来记录短信日志
logger = logging.getLogger('django')

class SMSCodeView(View):
    """短信验证码"""
    def get(self,request,mobile):
        """
        :param request:
        :param mobile:手机号
        :return: json
        """
        # 接收参数
        img_code_client = request.GET.get('image_code')
        # print(img_code_client)
        uuid = request.GET.get('uuid')
        # 校验参数
        if not all([img_code_client,uuid]):
            return http.HttpResponseForbidden('缺少必要参数')
        # 创建链接redis的对象
        redis_conn = get_redis_connection('verify_code')

        # 判断用户是否频繁发送短信验证码
        send_flg = redis_conn.get('send_flg_%s' % mobile)
        if send_flg:    # 已经发送过了
            return http.JsonResponse({'code':RETCODE.THROTTLINGERR,'errmsg':'发送短信过于频繁'})

        # 提取图形验证码

        img_code_server = redis_conn.get("img_%s" % uuid)   # 这是一个bytes类型
        if img_code_server is None:
            return http.JsonResponse({'code':RETCODE.IMAGECODEERR,'errmsg':'图形验证码已经失效'})
        # 删除图形验证码
        redis_conn.delete("img_%s" % uuid)
        # 对比图形验证码，将bytes类型转为字符串再比较
        img_code_server = img_code_server.decode()
        if img_code_server.lower() != img_code_client.lower():
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码有误'})

        # 生产短信验证码 %06d代表，如果不够6位，前面补0
        sms_code = '%06d' % random.randint(0,999999)
        # 手动输出日志，记录短信验证码
        logger.info(sms_code)
        # # 保存短信验证码
        # redis_conn.setex("sms_%s" % mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
        # # 保存发送短信验证码的标记
        # redis_conn.setex('send_flg_%s' % mobile,constants.SEND_SMS_CODE_INTERVAL,1)

        # 创建redis管道
        pl = redis_conn.pipeline()
        # 将命令添加到队列中
        # 保存短信验证码
        pl.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        # 保存发送短信验证码的标记
        pl.setex('send_flg_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
        # 执行
        pl.execute()

        # 发送短信验证码
        CPP().send_message_sms(mobile,[sms_code,constants.SMS_CODE_REDIS_EXPIRES // 60],constants.SEND_SMS_TEMPLATE_ID)
        return http.JsonResponse({'code':RETCODE.OK,'errmsg':'发送短信成功'})

class ImageCodeView(View):
    """图形验证码"""
    def get(self,request,uuid):
        """
        :param request:
        :param uuid: 通用唯一识别码，用于唯一表示该图形验证码属于哪个用户的
        :return:
        """
        # 接受和校验参数
        # 实现主体业务逻辑：生成图形验证码，保存，响应图形验证码
        # 生成图形验证码
        text,image = captcha.generate_captcha()
        # 保存图片验证码
        redis_conn = get_redis_connection('verify_code')    # 找到dev中配置的redis库
        # 设置键为uuid，值为text，超时时间为300秒
        redis_conn.setex("img_%s" % uuid,constants.IMAGE_CODE_REDIS_EXPIRES,text)  # setex可以设置生存时间
        # 响应图片验证码
        return http.HttpResponse(image,content_type='image/jpg')


import os
import sys
import glob
import shutil
from colorama import Fore, Back, Style

def main():

    # List existing RADLab Modules
    module = list_modules()

    sc_path = os.getcwd() + '/radlab-service-catalog'

    # Creating RadLab Service Catalog Package folder
    os.system('mkdir -p ' + sc_path)

    # Pull specific folder from RADLab GitHub Repo
    shutil.copytree(os.path.dirname(os.getcwd()) + '/modules/'+ module, sc_path + '/' + module)

    for filename in os.listdir(sc_path + '/' + module):

        f = os.path.join(sc_path + '/' + module, filename)

        # Remove all non.tf files from the root of the module
        if os.path.isfile(f) and os.path.splitext(f)[1] != ".tf":
            os.remove(f)

    # Zip the module in such a way that .tf files are at the root of the zipped file
    os.system('cd ' + sc_path + '/' + module + '; zip -r ' + module + '.zip *')

    # Move thezip package to the RADLab Service Catalog Folder
    os.system('mv ' + sc_path + '/' + module + '/' + module + '.zip ' + sc_path )

    # Remove the downloaded module
    os.system('rm -r ' + sc_path + '/' + module)

    # Printing path to RADLab's Service Catalog Solution.
    print("Please find the zipped solution here: " + sc_path + '/' + module +'.zip')

def list_modules():
    modules = [s.replace(os.path.dirname(os.getcwd()) + '/modules/', "") for s in glob.glob(os.path.dirname(os.getcwd()) + '/modules/*')]
    modules = sorted(modules)
    c = 1
    print_list = ''

    # Printing List of Modules
    for module in modules:
        first_line = ''
        # Fetch Module name
        try:
            with open(os.path.dirname(os.getcwd()) + '/modules/'+ module + '/README.md', "r") as file:
                first_line = file.readline()
        except:
            print(Fore.RED +'Missing README.md file for module: ' + module + Style.RESET_ALL)
        print_list = print_list + "["+ str(c) +"] " + first_line.strip() + Fore.GREEN + " (" +module + ")\n" + Style.RESET_ALL
        c = c+1

    # Selecting Module
    try:
        selected_module = input("\nList of available RAD Lab modules:\n"+print_list+"["+ str(c) +"] Exit\n"+ Fore.YELLOW + Style.BRIGHT + "Choose a number for the RAD Lab Module"+ Style.RESET_ALL + ': ').strip()
        selected_module = int(selected_module)
    except:
        sys.exit(Fore.RED + "\nInvalid module")

    # Validating User Module selection
    if selected_module > 0 and selected_module < c:
        # print(modules)
        module_name = modules[selected_module-1]
        print("\nRAD Lab Module (selected) : "+ Fore.GREEN + Style.BRIGHT +module_name+ Style.RESET_ALL)
        return module_name
    elif selected_module == c:
        sys.exit(Fore.GREEN + "\nExiting Installer")
    else:
        sys.exit(Fore.RED + "\nInvalid module")

if __name__ == '__main__':
    main()


from datetime import datetime
import datetime as datetime_date
from django.urls import reverse

from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.http import JsonResponse, HttpResponseBadRequest, HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.views.generic import TemplateView, DetailView, CreateView, UpdateView
# Create your views here.
from django.views.generic.base import View
from django.shortcuts import redirect, get_object_or_404
from social_core.utils import slugify
from PIL import Image

import places
from analytics.utils import get_visitor_data, get_country_by_ip
from operators.models import TourOperator
from places.models import Animal, Activity, Park, CountryIndex, Country
from photos.models import Tag
from reviews.forms import ParkReviewForm, TourOperatorReviewForm, ParkKilimanjaroReviewForm
from reviews.models import ParkReview, TourOperatorReview, SafariType, KilimanjaroParkReview
import json
from django.db.models.functions import Lower
import yas.settings as settings
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from photos.models import Photo

from photos.forms import PhotoTagsForm

# Authentication:
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin

class MemberRequiredLoginView(UserPassesTestMixin, LoginRequiredMixin):

    def test_func(self):
        return self.request.user.is_authenticated

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return context

class PhotoGuidelinesView(TemplateView):
    template_name = 'reviews/photo_guidelines.html'

class ReviewIndexView(TemplateView):
    template_name = 'reviews/index.html'

class ReviewCreateView(MemberRequiredLoginView, TemplateView):
    template_name = 'reviews/create.html'

    def get(self, request, **kwargs):
        return self.post(request)

    def post(self, request, **kwargs):
        data = request.POST
        errors = {}

        if data:
            if data.get('review_type') == 'park':
                if data.get('selected_park') and data.get('selected_country'):
                    return redirect('reviews:park', pk=data.get('selected_park'))
                elif data.get('selected_park') or data.get('selected_country'):
                    errors['selected_country'] = 'Please select a country' if not data.get('selected_country') else None
                    errors['selected_park'] = 'Please select a park' if not data.get('selected_park') else None
                else:
                    errors['selected_country'] = 'Please select a country'
                    errors['selected_park'] = 'Please select a park'

            else:
                if data.get('review_type') == 'tour_operator':
                    if data.get('selected_tour_operator'):
                        return redirect('reviews:tour_operator', pk=data.get('selected_tour_operator'))
                    else:
                        errors['selected_tour_operator'] = 'Please select a tour operator'
                else:
                    errors['review_type'] = 'Select a review type'

        context = {}

        countries = CountryIndex.objects.all()
        countries_json = []
        for country in countries:
            country_json = {}
            country_json['id'] = country.id
            country_json['name'] = country.name
            country_json['parks'] = list(country.parks.all().values('id', 'name'))
            countries_json.append(country_json)

        tour_operators = TourOperator.objects.all().order_by(Lower('name'))
        tour_operators_json = []
        for tour_operator in tour_operators:
            tour_operator_json = {}
            tour_operator_json['id'] = tour_operator.id
            tour_operator_json['name'] = tour_operator.name
            tour_operators_json.append(tour_operator_json)

        context['vue_variables'] = {}
        context['vue_variables']['errors'] = json.dumps(errors)
        context['vue_variables']['countries_json'] = json.dumps(countries_json)
        context['vue_variables']['tour_operators_json'] = json.dumps(tour_operators_json)
        context['vue_variables']['data'] = json.dumps(data)

        context['vue_strings'] = {}
        context['vue_strings']['review_type'] = data.get('review_type') if data else None
        context['vue_strings']['selected_country'] = data.get('selected_country') if data else None
        context['vue_strings']['selected_park'] = data.get('selected_park') if data else None
        context['vue_strings']['selected_tour_operator'] = data.get('selected_tour_operator') if data else None

        return render(request, self.template_name, context=context)

class ReviewCreateParkReviewAckView(MemberRequiredLoginView,TemplateView):
    template_name = "reviews/create_park_review_ack.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        review = get_object_or_404(ParkReview, pk=self.kwargs.get('pk'))

        reviewed_parks = []

        for parkreview in self.request.user.parkreview_set.all():
            reviewed_parks.append(parkreview.id)

        similar_parks = Park.objects.filter(country_indexes__in=review.park.country_indexes.all()).exclude(
            pk=review.park.id)
        context['review'] = review
        context['park'] = review.park
        context['similar_parks'] = similar_parks

        context['review_count'] = review.park.park_reviews.filter(status="AC").count()
        context['review_rating'] = review.park.rating_decimal()
        context['base_url'] = settings.BASE_URL
        return context

class ReviewCreateTourOperatorReviewAckView(MemberRequiredLoginView,TemplateView):
    template_name = "reviews/create_tour_operator_review_ack.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        review = get_object_or_404(TourOperatorReview, pk=self.kwargs.get('pk'))

        reviewed_parks = []

        for parkreview in self.request.user.parkreview_set.all():
            reviewed_parks.append(parkreview.park.id)

        similar_parks = review.parks.exclude(pk__in=reviewed_parks)
        context['review'] = review
        context['tour_operator'] = review.tour_operator
        context['similar_parks'] = similar_parks
        context['base_url'] = settings.BASE_URL
        return context

class ReviewCreateParkReviewView(MemberRequiredLoginView,TemplateView):
    model = ParkReview
    template_name = "reviews/create_park_review.html"
    form_class = ParkReviewForm

    def get(self, request, **kwargs):
        return super(ReviewCreateParkReviewView, self).get(request)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        park = get_object_or_404(Park, pk=self.kwargs.get('pk'))
        animals = Animal.objects.all().order_by('name')
        animals_json = []
        for animal in animals:
            animal_json = {}
            animal_json['id'] = animal.id
            animal_json['name'] = animal.name
            animals_json.append(animal_json)

        activities = Activity.objects.filter(activity_type="SAFARI").order_by('name')
        activities_json = []
        for activity in activities:
            activity_json = {}
            activity_json['id'] = activity.id
            activity_json['name'] = activity.name
            activities_json.append(activity_json)

        routes_to_climb_json = []
        for key, value in KilimanjaroParkReview.ROUTES_CHOICES:
            route_to_climb_json = {}
            route_to_climb_json['key'] = key
            route_to_climb_json['value'] = value
            routes_to_climb_json.append(route_to_climb_json)

        context['vue_variables'] = {}
        context['vue_variables']['animals_json'] = json.dumps(animals_json)
        context['vue_variables']['activities_json'] = json.dumps(activities_json)
        context['vue_variables']['routes_to_climb_json'] = json.dumps(routes_to_climb_json)
        context["park"] = park
        return context

class ReviewCreateParkKilimanjaroView(ReviewCreateParkReviewView):
    model = KilimanjaroParkReview

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return context

class ReviewCreateTourOperatorView(MemberRequiredLoginView,TemplateView):
    model = TourOperatorReview
    template_name = "reviews/create_tour_operator_review.html"
    form_class = ParkReviewForm

    def get(self, request, **kwargs):
        return super(ReviewCreateTourOperatorView, self).get(request)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        tour_operator = get_object_or_404(TourOperator, pk=self.kwargs.get('pk'))
        countries = tour_operator.country_indexes.all().order_by('name')
        # countries = CountryIndex.objects.all().order_by('name')
        countries_json = []
        for country in countries:
            country_json = {}
            country_json['id'] = country.id
            country_json['name'] = country.name
            country_json['parks'] = list(country.parks.all().values('id', 'name'))
            countries_json.append(country_json)

        animals = Animal.objects.all().order_by('name')
        animals_json = []
        for animal in animals:
            animal_json = {}
            animal_json['id'] = animal.id
            animal_json['name'] = animal.name
            animals_json.append(animal_json)

        activities = Activity.objects.filter(activity_type="SAFARI").order_by('name')
        activities_json = []
        for activity in activities:
            activity_json = {}
            activity_json['id'] = activity.id
            activity_json['name'] = activity.name
            activities_json.append(activity_json)

        safari_types = SafariType.objects.all()
        safari_types_json = []
        for safari_type in safari_types:
            safari_type_json = {}
            safari_type_json['id'] = safari_type.id
            safari_type_json['name'] = safari_type.name
            safari_types_json.append(safari_type_json)

        routes_to_climb_json = []
        for key, value in KilimanjaroParkReview.ROUTES_CHOICES:
            route_to_climb_json = {}
            route_to_climb_json['key'] = key
            route_to_climb_json['value'] = value
            routes_to_climb_json.append(route_to_climb_json)

        context['vue_variables'] = {}
        context['vue_variables']['booking_with_this_company'] = False
        context['vue_variables']['countries_json'] = json.dumps(countries_json)
        context['vue_variables']['animals_json'] = json.dumps(animals_json)
        context['vue_variables']['activities_json'] = json.dumps(activities_json)
        context['vue_variables']['safari_types_json'] = json.dumps(safari_types_json)
        context['vue_variables']['routes_to_climb_json'] = json.dumps(routes_to_climb_json)
        context["tour_operator"] = tour_operator
        context["countries"] = countries
        return context

@login_required
def save_review_park(request, pk):
    if request.method == 'POST':
        data = json.loads(request.body)

        data['date_created'] = datetime.now()
        data['date_modified'] = datetime.now()
        data['email_sent'] = False
        data['visit_date'] = datetime(data['visit_date_year'], data['visit_date_month'], 1)

        form = ParkReviewForm(data)
        form.instance.user = request.user
        park = get_object_or_404(Park, pk=pk)
        form.instance.park = park
        ip = get_visitor_data(request)['ip_address']
        form.instance.ip_address = ip
        try:
            iso = get_country_by_ip(ip)
            country = Country.objects.get(iso=iso)
            if country:
                form.instance.country_written = country
        except places.models.Country.DoesNotExist:
            pass

        if form.is_valid():
            form = form.save()
            form.slug = slugify(data['title'])

            obj = json.loads(request.body)
            for key in obj.get('selected_activities'):
                form.activities.add(Activity.objects.get(pk=key))

            for key in obj.get('selected_animals'):
                form.animals.add(Animal.objects.get(pk=key))
            form.save()
            send_review_thank_you_email(request, park.name)
            data = {'status': 'success', 'review_park': form.id}
            return JsonResponse(data)
        else:
            return JsonResponse({'status': 'error', 'errors': form.errors})

@login_required
def save_review_park_kilimanjaro(request, pk):
    if request.method == 'POST':
        data = json.loads(request.body)
        data['slug'] = slugify(data['title'])
        data['date_created'] = datetime.now()
        data['date_modified'] = datetime.now()
        data['email_sent'] = False
        data['visit_date'] = datetime(data['visit_date_year'], data['visit_date_month'], 1)

        form = ParkKilimanjaroReviewForm(data)
        form.instance.user = request.user
        park = Park.objects.get(pk=pk)
        form.instance.park = park
        ip = get_visitor_data(request)['ip_address']
        form.instance.ip_address = ip
        try:
            iso = get_country_by_ip(ip)
            country = Country.objects.get(iso=iso)
            if country:
                form.instance.country_written = country
        except places.models.Country.DoesNotExist:
            pass

        if form.is_valid():

            form = form.save()
            form.slug = slugify(data['title'])
            obj = json.loads(request.body)

            for key in obj.get('selected_activities'):
                form.activities.add(Activity.objects.get(pk=key))

            for key in obj.get('selected_animals'):
                form.animals.add(Animal.objects.get(pk=key))

            form.save()
            send_review_thank_you_email(request, park.name)
            data = {'status': 'success', 'review_park': form.id}
            return JsonResponse(data)
        else:
            return JsonResponse({'status': 'error', 'errors': form.errors})

def send_review_thank_you_email(request, item):
    email_to = request.user.email
    if not settings.REAL_EMAILS:
        email_to = settings.TESTING_EMAILS
    from post_office import mail
    context = {}
    context['member'] = request.user.profile.display_name_for_email()
    context['item'] = item
    mail.send(
        email_to,
        'Your African Safari <support@yourafricansafari.com>',
        template='review_thank_you',
        context=context,
    )

@login_required
def save_review_tour_operator(request, pk):
    if request.method == 'POST':
        data = json.loads(request.body)
        data['title'] = data['review_title']
        data['content'] = data['review_copy']
        data['pearls_of_wisdom'] = data['pearls_of_wisdom']
        data['friend_recommend'] = data['friend_recommend']
        data['reached_summit'] = data['reached_summit']
        data['take_medications'] = data['take_medications']
        data['route_to_climb'] = data['route_to_climb']
        if data['route_to_climb'] == "unselected" or data['route_to_climb'] == None:
            data['route_to_climb'] = None
        data['other_route_to_climb'] = data['other_route_to_climb']
        data['date_created'] = datetime.now()
        data['date_modified'] = datetime.now()
        if data['start_date_year'] > 0:
            data['start_date'] = datetime(data['start_date_year'], data['start_date_month'], 1)

        if data['is_kilimanjaro'] == True:
            data_kilimanjaro = data
            data_kilimanjaro['crowdedness_rating'] = data_kilimanjaro['crowdedness_rating_kilimanjaro']
            data_kilimanjaro['quality_wildlife_rating'] = 0
            data_kilimanjaro['quality_lodging_rating'] = 0
            data_kilimanjaro['content'] = data_kilimanjaro['content_kilimanjaro']
            data_kilimanjaro['visit_date'] = data['start_date']
            data_kilimanjaro['pearls_of_wisdom'] = data['pearls_of_wisdom_kilimanjaro']

        data['vehicle_rating'] = data['vehicle_rating']
        data['meet_and_greet_rating'] = data['meet_and_greet_rating']
        data['responsiveness_rating'] = data['responsiveness_rating']
        data['safari_quality_rating'] = data['safari_quality_rating']
        data['itinerary_quality_rating'] = data['itinerary_quality_rating']
        data['overall_rating'] = data['overall_rating']
        data['days_booked'] = data['days_booked'] or 0
        data['did_not_go'] = data['did_not_go']
        data['find_out'] = data['find_out']
        data['find_out_website'] = data['find_out_website']

        data['email_sent'] = False
        if data['is_kilimanjaro'] == True:
            data_kilimanjaro['email_sent'] = False

            form_kilimanjaro = ParkKilimanjaroReviewForm(data_kilimanjaro)
            form_kilimanjaro.instance.user = request.user

            form_kilimanjaro.instance.park = Park.objects.get(slug='kilimanjaro')
            ip = get_visitor_data(request)['ip_address']
            form_kilimanjaro.instance.ip_address = ip
            try:
                iso = get_country_by_ip(ip)
                country = Country.objects.get(iso=iso)
                if country:
                    form_kilimanjaro.instance.country_written = country
            except places.models.Country.DoesNotExist:
                pass

            if form_kilimanjaro.is_valid():
                form_kilimanjaro = form_kilimanjaro.save()
                form_kilimanjaro.slug = slugify(data['title'])
                obj = json.loads(request.body)

                for key in obj.get('selected_activities'):
                    form_kilimanjaro.activities.add(Activity.objects.get(pk=key))

                for key in obj.get('selected_animals'):
                    form_kilimanjaro.animals.add(Animal.objects.get(pk=key))

                form_kilimanjaro.save()
                data_kilimanjaro = {'status': 'success', 'review_park': form_kilimanjaro.id}
                # return JsonResponse(data_kilimanjaro)
            else:
                return JsonResponse({'status': 'error', 'errors': form_kilimanjaro.errors})

        form = TourOperatorReviewForm(data)
        form.instance.user = request.user
        tour_operator = TourOperator.objects.get(pk=pk)
        form.instance.tour_operator = tour_operator
        form.instance.tour_operator.last_review_date = datetime.now()
        form.instance.tour_operator.save()
        if data['safari_type_id'] != "" and data['safari_type_id'] != None:
            form.instance.safari_type = SafariType.objects.get(id=data['safari_type_id'])

        ip = get_visitor_data(request)['ip_address']
        form.instance.ip_address = ip
        try:
            iso = get_country_by_ip(ip)
            country = Country.objects.get(iso=iso)
            if country:
                form.instance.country_written = country
        except places.models.Country.DoesNotExist:
            pass

        if form.is_valid():
            review = form.save()
            review.slug = slugify(data['review_title'])

            obj = json.loads(request.body)
            for key in obj.get('selected_activities'):
                review.activities.add(Activity.objects.get(pk=key))

            for key in obj.get('selected_animals'):
                review.animals.add(Animal.objects.get(pk=key))

            for key in obj.get('selected_countries'):
                review.country_indexes.add(CountryIndex.objects.get(pk=key))

            for key in obj.get('selected_parks'):
                review.parks.add(Park.objects.get(pk=key))

            review.save()
            send_review_thank_you_email(request, tour_operator.name)
            data = {'status': 'success', 'review_tour_operator': review.id}
            return JsonResponse(data)
        else:
            return JsonResponse({'status': 'error', 'errors': form.errors})

class ParkReviewDetailView(DetailView):
    model = ParkReview
    template_name = "reviews/park_review.html"

class TourOperatorReviewDetailView(DetailView):
    model = TourOperatorReview
    template_name = "places/tour_operator_review.html"

def test_settings(user, review):
    if user.id == review.user.id:
        return True
    else:
        return False

@method_decorator(login_required, name='dispatch')
class TourOperatorReviewManagePhotosView(UserPassesTestMixin, DetailView):
    model = TourOperatorReview
    template_name = "reviews/tour_operators_review_photos.html"

    def test_func(self):
        tour_review_id = self.request.get_full_path().rsplit('/', 1)[1]
        tour_review = TourOperatorReview.objects.get(id=tour_review_id)
        return test_settings(self.request.user, tour_review)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        review = get_object_or_404(TourOperatorReview, pk=self.kwargs.get('pk'), user=self.request.user)

        context['country_indexes'] = CountryIndex.objects.all()
        context['activities'] = Activity.objects.filter(activity_type="SAFARI")
        context['animals'] = Animal.objects.all().order_by('name')

        context['review'] = review
        context['max_photo_count'] = 10
        return context

    def post(self, request, pk):
        photos = Photo.objects.filter(park_review__pk=pk)

        data = request.POST

        for photo in photos:

            photo.caption = data.__getitem__('caption_' + str(photo.id))

            photo.country_index = CountryIndex.objects.get(
                id=int(data.__getitem__('country_index_' + str(photo.id)))) if data.__getitem__(
                'country_index_' + str(photo.id)) else None

            photo.park = Park.objects.get(id=int(data.__getitem__('park_' + str(photo.id)))) if data.__getitem__(
                'park_' + str(photo.id)) else None

            photo.activity = Activity.objects.get(
                id=int(data.__getitem__('activity_' + str(photo.id)))) if data.__getitem__(
                'activity_' + str(photo.id)) else None

            photo.animals.clear()
            if data.getlist('animals_' + str(photo.id)):
                for animal in data.getlist('animals_' + str(photo.id)):
                    photo.animals.add(Animal.objects.get(id=int(animal)))

            photo.tags.clear()
            if data.getlist('tags_' + str(photo.id)):
                tags = data.getlist('tags_' + str(photo.id))[0].split(',')
                for tag in tags:
                    photo.tags.add(Tag.objects.get(name=tag))

            photo.save()

        return HttpResponse('uploaded park review')

@method_decorator(login_required, name='dispatch')
class ParkReviewManagePhotosView(UserPassesTestMixin, TemplateView):
    model = ParkReview
    template_name = "reviews/parks_review_photos.html"

    def test_func(self):
        park_review_id = self.request.get_full_path().rsplit('/', 1)[1]
        park_review = get_object_or_404(ParkReview, id=park_review_id)
        return self.request.user.pk == park_review.user.pk

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        review = get_object_or_404(ParkReview, pk=self.kwargs.get('pk'), user=self.request.user)

        context['country_indexes'] = CountryIndex.objects.all()
        context['activities'] = Activity.objects.filter(activity_type="SAFARI")
        context['animals'] = Animal.objects.all().order_by('name')

        context['review'] = review
        context['max_photo_count'] = 10
        return context

    def post(self, request, pk):
        data = request.POST
        photos = []
        for key in data.keys():
            if key.startswith('photo_id'):
                photos.append(data[key])

        for photoId in photos:

            photo = Photo.objects.get(id=photoId)

            photo.draft = False

            photo.caption = data.__getitem__('caption_' + photoId)

            photo.country_index = CountryIndex.objects.get(
                id=int(data.__getitem__('country_index_' + photoId))) if data.__getitem__(
                'country_index_' + photoId) else None

            photo.park = Park.objects.get(id=int(data.__getitem__('park_' + photoId))) if data.__getitem__(
                'park_' + photoId) else None

            photo.activity = Activity.objects.get(
                id=int(data.__getitem__('activity_' + photoId))) if data.__getitem__(
                'activity_' + photoId) else None

            photo.animals.clear()
            if data.getlist('animals_' + photoId):
                for animal in data.getlist('animals_' + photoId):
                    photo.animals.add(Animal.objects.get(id=int(animal)))

            photo.tags.clear()
            if data.getlist('tags_' + photoId):
                tags = data.getlist('tags_' + photoId)[0].split(',')
                for tag in tags:
                    tag_model, _ = Tag.objects.get_or_create(name=tag)
                    photo.tags.add(tag_model)

            photo.save()

        return HttpResponse('uploaded park review')

@method_decorator(csrf_exempt, name='dispatch')
@method_decorator(login_required, name='dispatch')
class ParkReviewCreatePhotoView(TemplateView):
    model = ParkReview

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        review = get_object_or_404(ParkReview, pk=self.kwargs.get('pk'), user=self.request.user)

        context['review'] = review
        return context

    def post(self, request, pk, **kwargs):
        review = get_object_or_404(ParkReview, pk=pk, user=request.user)
        if review.photos.count == 10:
            return HttpResponseBadRequest('Max photos have been reached')
        im = Image.open(request.FILES.get('file'))
        width, height = im.size
        if width < 720 or height < 540:
            return HttpResponseBadRequest('Image is too small')
        else:
            photo = Photo()
            photo.park_review = review
            photo.image = request.FILES.get('file')
            photo.user = request.user
            photo.draft = True
            photo.save()
            return HttpResponse(photo.id)

@method_decorator(csrf_exempt, name='dispatch')
@method_decorator(login_required, name='dispatch')
class TourOperatorReviewCreatePhotoView(TemplateView):
    model = TourOperatorReview

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        review = get_object_or_404(TourOperatorReview, pk=self.kwargs.get('pk'), user=self.request.user)

        context['review'] = review
        return context

    def post(self, request, pk, **kwargs):
        review = get_object_or_404(TourOperatorReview, pk=pk, user=request.user)
        if review.photos.count == 10:
            return HttpResponseBadRequest('Max photos have been reached')
        im = Image.open(request.FILES.get('file'))
        width, height = im.size
        if width < 720 or height < 540:
            return HttpResponseBadRequest('Image is too small')
        else:
            photo = Photo()
            photo.tour_operator_review = review
            photo.image = request.FILES.get('file')
            photo.user = request.user
            photo.draft = True
            photo.save()
            return HttpResponse(photo.id)


import pandas as pd
import numpy as np
from pathlib import Path
import asrtoolkit
from fuzzywuzzy import fuzz
from nltk.metrics import distance
import string
from scipy import stats
from difflib import Differ
import warnings
warnings.filterwarnings('ignore')

def load_results(filenames: list) -> (list, pd.DataFrame):
    results = pd.DataFrame()
    models = list()

    for idx, filename in enumerate(filenames):
        new_results = pd.read_csv(filename)
        model_label = Path(filename).stem  # .split('-')[0]
        ground_truth_label = f'{model_label}-ground_truth'
        new_results = new_results.rename(columns={'label': ground_truth_label,
                                                  'prediction': model_label})
        del new_results['Unnamed: 0']
        models.append((ground_truth_label, model_label))
        new_results[ground_truth_label] = new_results.apply(lambda r: str(r[ground_truth_label]), axis=1)
        new_results[model_label] = new_results.apply(lambda r: str(r[model_label]), axis=1)
        results = pd.concat([results, new_results], axis=1)

    models = sorted(models, key=lambda b: b[1])
    return models, results

def generate_summary_stats(models: list, results: pd.DataFrame) -> pd.DataFrame:
    NUM_STATS = 6
    NUM_SUB_STATS = 5
    a = ['matchratio'] * NUM_SUB_STATS + ['CER'] * NUM_SUB_STATS + ['matchratio_insensitive'] * NUM_SUB_STATS + \
        ['CER_insensitive'] * NUM_SUB_STATS + ['matchratio_nopunc'] * NUM_SUB_STATS + ['CER_nopunc'] * NUM_SUB_STATS
    b = ['mean', 'min', 'max', 'stdev', 'median'] * NUM_STATS
    headers = pd.MultiIndex.from_arrays([a, b], names=('stat', 'substats'))
    summary_results = pd.DataFrame(columns=headers)

    def _apply_stat(model_label: str, query_label: str, summary_stat_label: str, stat_function):
        results[query_label] = subset.apply(stat_function, axis=1)
        summary_results.loc[model_label, (summary_stat_label, 'mean')] = results[query_label].mean()
        summary_results.loc[model_label, (summary_stat_label, 'stdev')] = results[query_label].std()
        summary_results.loc[model_label, (summary_stat_label, 'min')] = results[query_label].min()
        summary_results.loc[model_label, (summary_stat_label, 'median')] = results[query_label].median()
        summary_results.loc[model_label, (summary_stat_label, 'max')] = results[query_label].max()
        subset[query_label] = results[query_label]

    for ground_truth_label, model_label in models:
        subset = results[[ground_truth_label, model_label]].dropna()

        _apply_stat(model_label, f'{model_label} CER', 'CER',
                    lambda r: asrtoolkit.cer(str(r[ground_truth_label]), str(r[model_label])))
        _apply_stat(model_label, f'{model_label} match ratio', 'matchratio',
                    lambda r: fuzz.ratio(str(r[ground_truth_label]), str(r[model_label])))
        results[f'{model_label}-edit_distance'] = subset.apply(
            lambda r: distance.edit_distance(str(r[ground_truth_label]), str(r[model_label])), axis=1)

        subset[f'{ground_truth_label}-lower'] = subset[ground_truth_label].map(str.lower)
        subset[f'{model_label}-lower'] = subset[model_label].map(str.lower)
        _apply_stat(model_label, f'{model_label} CER insensitive', 'CER_insensitive',
                    lambda r: asrtoolkit.cer(str(r[f'{ground_truth_label}-lower']), str(r[f'{model_label}-lower'])))
        _apply_stat(model_label, f'{model_label} match ratio insensitive', 'matchratio_insensitive',
                    lambda r: fuzz.ratio(str(r[f'{ground_truth_label}-lower']), str(r[f'{model_label}-lower'])))

        subset[f'{ground_truth_label}-nopunc'] = subset[ground_truth_label].map(
            lambda s: s.translate(str.maketrans('', '', string.punctuation)))
        subset = subset.loc[subset[f'{ground_truth_label}-nopunc'].str.len() > 0]
        subset[f'{model_label}-nopunc'] = subset[model_label].map(
            lambda s: s.translate(str.maketrans('', '', string.punctuation)))
        subset = subset.loc[subset[f'{model_label}-nopunc'].str.len() > 0]
        _apply_stat(model_label, f'{model_label} CER no punc', 'CER_nopunc',
                    lambda r: asrtoolkit.cer(str(r[f'{ground_truth_label}-nopunc']), str(r[f'{model_label}-nopunc'])))
        _apply_stat(model_label, f'{model_label} match ratio no punc', 'matchratio_nopunc',
                    lambda r: fuzz.ratio(str(r[f'{ground_truth_label}-lower']), str(r[f'{model_label}-lower'])))

        exact = results.dropna().apply(lambda r: 1 if int(r[f'{model_label}-edit_distance']) == 0 else 0, axis=1).sum()
        oboe = results.dropna().apply(lambda r: 1 if int(r[f'{model_label}-edit_distance']) == 1 else 0, axis=1).sum()
        summary_results.loc[model_label, 'exact_matches'] = pd.to_numeric(exact, downcast='integer')
        summary_results.loc[model_label, 'oboe_matches'] = pd.to_numeric(oboe, downcast='integer')

        err_range = stats.norm.interval(alpha=0.95,
                                        loc=np.mean(results[f'{model_label} CER'].dropna()),
                                        scale=stats.sem(results[f'{model_label} CER'].dropna()))
        summary_results.loc[model_label, 'cer_95_error_min'] = err_range[0]
        summary_results.loc[model_label, 'cer_95_error_max'] = err_range[1]

    return summary_results

def plot_cer(models: list, results: pd.DataFrame, graph) -> None:
    graph.set_title('Character Error Rate (CER)')
    graph.set_xticklabels([label[1] for label in models], rotation=15, horizontalalignment='right')
    graph.set_ylim([-1, 200])
    subset = results[[f'{label[1]} CER' for label in models]].T
    subset = np.asarray([model[1].dropna() for model in subset.iterrows()], dtype=object).T
    graph.boxplot(subset)

def plot_cer_confidence_interval(models: list, summary_results: pd.DataFrame, graph) -> None:
    min = summary_results['cer_95_error_min']
    min = min.apply(lambda v: v if v >= 0 else 0)
    max = summary_results['cer_95_error_max']
    max = max.apply(lambda v: v if v <= 100 else 100)
    error_min = [summary_results.loc[label[1], ('CER', 'mean')] - min[label[1]] for label in models]
    error_max = [max[label[1]] - summary_results.loc[label[1], ('CER', 'mean')] for label in models]
    graph.set_title('CER 95% confidence interval')
    graph.set_xticklabels([label[1] for label in models], rotation=15, horizontalalignment='right')
    graph.set_ylim(top=100)
    graph.errorbar([label[1] for label in models], summary_results[('CER', 'mean')], yerr=[error_min, error_max], fmt='o')
    for i in range(len(models)):
        graph.text(i + 0.05, max[i] - 2, f'{max[i]:.3f}')
        graph.text(i + 0.05, min[i] + 1, f'{min[i]:.3f}')

def plot_fuzzy_match(models: list, results: pd.DataFrame, graph) -> None:
    graph.set_title('Fuzzy Match Ratio')
    graph.set_xticklabels([label[1] for label in models], rotation=15, horizontalalignment='right')
    subset = results[[f'{label[1]} match ratio' for label in models]].T
    subset = np.asarray([model[1].dropna() for model in subset.iterrows()], dtype=object).T
    graph.boxplot(subset)

def plot_close_matches(models: list, results: pd.DataFrame, summary_results: pd.DataFrame, graph):
    graph.set_title('% of Exact/Almost Exact String Matches')
    exact_matches = [match/results.shape[0] for match in summary_results['exact_matches']]
    obo_matches = [match/results.shape[0] for match in summary_results['oboe_matches']]
    ex = graph.bar([label[1] for label in models], exact_matches,
                   width=0.3, label='Exact match')
    obo = graph.bar([label[1] for label in models], obo_matches,
                    width=0.3, bottom=exact_matches, label='Off by one')
    graph.set_xticklabels([label[1] for label in models], rotation=15, horizontalalignment='right')
    graph.set_ybound(0, 0.2)
    graph.legend()

def process_oboes(models: list, results: pd.DataFrame) -> (list, dict, dict, dict):
    d = Differ()
    substitution_errors = {}
    deletion_errors = {}
    insertion_errors = {}
    CHAR_LIST = '\' !"#&()[]*+,-./0123456789:;?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
    empty_char_dict = {c: 0 for c in list(CHAR_LIST)}
    plain_model_labels = ['-'.join(a[1].split('-')[:-1]) for a in models]

    for ground_truth_label, model_label in models:
        model_label_plain = '-'.join(model_label.split('-')[:-1])
        oboe = results[results[f'{model_label}-edit_distance'] == 1][[ground_truth_label, model_label]]
        subs = {}
        dels = empty_char_dict.copy()
        ins = empty_char_dict.copy()

        for idx, row in oboe.iterrows():
            differ_result = list(d.compare(row[ground_truth_label], row[model_label]))
            differ_result = [a for a in differ_result if a[0] != ' ']
            assert len(differ_result) <= 2, f'Lens are wrong: {differ_result}'
            removed = [c[2] for c in differ_result if c[0] == '-']
            added = [c[2] for c in differ_result if c[0] == '+']
            if len(removed) == 0:
                ins[added[0]] += 1
            elif len(added) == 0:
                dels[removed[0]] += 1
            else:
                sub_chars = (removed[0], added[0])
                if sub_chars in subs.keys():
                    subs[sub_chars] += 1
                else:
                    subs[sub_chars] = 1

        subs = dict(sorted(subs.items(), key=lambda item: item[1], reverse=True))
        dels = dict(sorted(dels.items(), key=lambda item: item[1], reverse=True))
        ins = dict(sorted(ins.items(), key=lambda item: item[1], reverse=True))
        substitution_errors[model_label_plain] = subs
        deletion_errors[model_label_plain] = dels
        insertion_errors[model_label_plain] = ins

    return plain_model_labels, substitution_errors, deletion_errors, insertion_errors


import  cv2
import  os
import mediapipe as mp
import numpy as np
import math

class collect:

    cam = None
    directory = None
    alphacount = []

    def createSquare(self,img, x, y):
        factor = math.sqrt(2) * 4
        uppercorner = (int(x - factor), int(y - factor))
        lowercorner = (int(x + factor), int(y + factor))
        # cv2.rectangle(image, start_point, end_point, color, thickness)
        cv2.rectangle(img, uppercorner, lowercorner, (255, 0, 0), -1)

    def createTriangle(self,img, x, y):
        vertices = np.array([[x - 4, y], [x + 4, y - 4], [x + 4, y + 4]], np.int32)
        pts = vertices.reshape((-1, 1, 2))
        cv2.polylines(img, [pts], isClosed=True, color=(0, 175, 255), thickness=3)
        # fill it
        cv2.fillPoly(img, [pts], color=(0, 175, 255))

    def checkCam(self, cam):
        if not cam.isOpened():
            print("Could not open cam")
            exit()
        # Setting capture window size
        # 3->width
        cam.set(3, 1080)
        # 4->height
        cam.set(4, 720)
        print("Camera successfully initialized...")

    def initializeOS(self):
        os.chdir(directory)
        if not os.path.exists("data"):
            os.makedirs("data")
        if not os.path.exists("data/train"):
            os.makedirs("data/train")
        if not os.path.exists("data/test"):
            os.makedirs("data/test")
        for i in range(65, 91):
            if not os.path.exists("data/train"+chr(i)):
                os.makedirs("data/train/" + chr(i))
            if not os.path.exists("data/test"+chr(i)):
                os.makedirs("data/test/" + chr(i))
        print("Directories Created Successfully...")

    def __init__(self):
        print("Object created")
        global cam, directory, alphacount
        alphacount = [0]*26
        print(alphacount)
        cam = cv2.VideoCapture(0)
        directory = r'D:\playground\Major Project (Hand sign)\SubGroup'
        self.checkCam(cam)
        self.initializeOS()

    def generateDataSet(self):
        global cam, directory, alphacount
        # , mp_drawing, mp_hands, hands
        mp_drawing = mp.solutions.drawing_utils
        # mp_drawing_styles = mp.solutions.drawing_styles
        mp_hands = mp.solutions.hands
        hands = mp_hands.Hands()
        while True:
            success, frame = cam.read()
            if success:
                frame = cv2.flip(frame, 1)
                # cv2.rectangle(image, start_point, end_point, color, thickness)
                display = cv2.rectangle(frame.copy(), (800, 100), (1150, 450), (0, 255, 0), 2)
                # [(y1:y2),(x1:x2)]
                ROI = frame[100:450, 800:1150].copy()
                imgRGB = cv2.cvtColor(ROI, cv2.COLOR_BGR2RGB)
                result = hands.process(imgRGB)
                blank_image = np.zeros(shape=[350, 350, 3], dtype=np.uint8)
                keypressed = cv2.waitKey(5)
                if(result.multi_hand_landmarks!=None):
                    for handLms in result.multi_hand_landmarks:
                        mp_drawing.draw_landmarks(blank_image, handLms, mp_hands.HAND_CONNECTIONS)
                        for id, lm in enumerate(handLms.landmark):
                            # print(id, lm)
                            h, w, c = imgRGB.shape  # height, width, channels
                            cx, cy = int(lm.x * w), int(lm.y * h)  # center coordinates
                            if (id == 5 or id == 9 or id == 13 or id == 17):
                                cv2.circle(blank_image, (cx, cy), 5, (131, 245, 44), -1)  # florant green for MCP
                            elif (id == 8 or id == 12 or id == 16 or id == 20):  # fingerpits triangle yellow
                                self.createTriangle(blank_image, cx, cy)
                            elif (id == 1 or id == 2 or id == 3):  # giving preference to thumb
                                cv2.circle(blank_image, (cx, cy), 5, (30, 144, 255), -1)
                            elif (id == 4):  # thumb tip
                                self.createSquare(blank_image, cx, cy)
                                # cv2.circle(image, center_coordinates, radius, color, thickness)
                        for i in range(97, 123):
                            if keypressed & 0xFF == ord(chr(i)):
                                print(chr(i), "pressed")
                                tempcount = alphacount[i-97]
                                alphacount[i-97]+=1
                                print(i,"  ",tempcount)
                                if(tempcount < 1000):
                                    tempdirectory='data/train/'+chr(i)
                                    os.chdir(tempdirectory)
                                    cv2.imwrite(str(tempcount)+'.jpg',blank_image)
                                else:
                                    tempdirectory = 'data/test/' + chr(i)
                                    os.chdir(tempdirectory)
                                    cv2.imwrite(str(tempcount-1000)+'.jpg', blank_image)
                                os.chdir(directory)
                if keypressed & 0xFF == 27:  # cv2.waitkey(delay (milliseconds))
                    break
                cv2.imshow('Filter Roi', blank_image)
                cv2.imshow("Capture Video", display)
    def releaseResource(self):
        global cam
        cam.release()
        cv2.destroyAllWindows()

c = collect()
c.generateDataSet()
c.releaseResource()


import requests
from telegram import InlineKeyboardButton

def get_token(client_id, client_secret):
    data = {
        'client_id': client_id,
        'client_secret': client_secret,
        'grant_type': 'client_credentials',
    }
    response = requests.post('https://api.moltin.com/oauth/access_token',
                             data=data)
    response.raise_for_status()
    token_params = response.json()
    access_token = token_params['access_token']
    token_expires = token_params['expires']
    return access_token, token_expires

def get_products_params(access_token):
    headers = {
            'Authorization': f'Bearer {access_token}',
        }
    response = requests.get('https://api.moltin.com/pcm/products',
                            headers=headers)
    response.raise_for_status()
    return response.json()

def get_product_params(access_token, product_id):
    headers = {
            'Authorization': f'Bearer {access_token}',
        }
    params = {
        'include': 'prices',
    }
    response = requests.get(f'https://api.moltin.com/pcm/products/{product_id}',
                            headers=headers,
                            params=params)
    response.raise_for_status()
    return response.json()

def get_products_prices(access_token, price_list_id):
    headers = {
            'Authorization': f'Bearer {access_token}',
        }
    response = requests.get(f'https://api.moltin.com/pcm/pricebooks/{price_list_id}/prices',
                            headers=headers)
    response.raise_for_status()
    return response.json()

def get_product_files(access_token, file_id):
    headers = {
            'Authorization': f'Bearer {access_token}',
        }
    response = requests.get(f'https://api.moltin.com/v2/files/{file_id}',
                            headers=headers)
    response.raise_for_status()
    return response.json()

def create_client(access_token, client_name, email):
    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json',
    }

    json_data = {
        'data': {
            'type': 'customer',
            'name': client_name,
            'email': email,
        },
    }
    response = requests.post('https://api.moltin.com/v2/customers',
                             headers=headers,
                             json=json_data)
    return response

def get_products_names(products_params):
    keyboard_products = [InlineKeyboardButton("Главное меню",
                                              callback_data='main_menu')]
    for product in products_params['data']:
        button_name = product['attributes']['name']
        button_id = product['id']
        button = InlineKeyboardButton(button_name, callback_data=button_id)
        keyboard_products.insert(0, button)
    return keyboard_products

def add_item_to_cart(access_token, product_id, quantity, cart_name):
    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json'
    }
    json_data = {
        'data': {
            'type': 'cart_item',
            'id': product_id,
            "quantity": quantity,
        }
    }
    response = requests.post(f'https://api.moltin.com/v2/carts/{cart_name}/items',
                             headers=headers,
                             json=json_data)
    response.raise_for_status()
    return response

def get_products_from_cart(access_token, cart_name):
    headers = {
            'Authorization': f'Bearer {access_token}',
        }
    response = requests.get(f'https://api.moltin.com/v2/carts/{cart_name}/items',
                            headers=headers)
    response.raise_for_status()
    return response.json()

def get_cart_params(access_token, cart_name):
    headers = {
        'Authorization': f'Bearer {access_token}',
    }
    response = requests.get(f'https://api.moltin.com/v2/carts/{cart_name}',
                            headers=headers)
    response.raise_for_status()
    return response.json()

def delete_item_from_cart(access_token, cart_name, product_id):
    headers = {
        'Authorization': f'Bearer {access_token}',
    }
    response = requests.delete(f'https://api.moltin.com/v2/carts/{cart_name}/items/{product_id}',
                    headers=headers)
    response.raise_for_status()
    return response


import random
from datetime import datetime
from unittest import mock

import requests_mock
from django.conf import settings
from django.forms.models import model_to_dict
from django.test import TestCase
from faker import Faker
from freezegun import freeze_time

from app.enquiries.common.as_utils import fetch_and_process_enquiries
from app.enquiries.models import Enquiry, Enquirer

faker = Faker()

# relevant table from the complete html body
table_template = """

See below for your submitted form:

            Given name
            {first_name}

            Family name
            {last_name}

            Job title
            CEO

            Email address
            {email}

            Phone number
            {phone}

            Company name
            {company_name}

            Company website
            https://example.com

            Company HQ address
            Far, far away

            Country
            US

            Industry
            AEROSPACE

                Which of these best describes how you feel about expanding to the UK?

            I’m still exploring where to expand my business and would like to know more about\
 the UK’s offer.

            Tell us about your investment
            This is a test message sent via automated tests

            Would you like to arrange a call?
            {arrange_call}

            When should we call you?

            How did you hear about us?
            LinkedIn

            I would like to receive additional information by email
            {email_consent}

                I would like to receive additional information by telephone

            {phone_consent}

"""

def get_enquiries_data():
    response = {"hits": {"hits": []}}
    details = []
    for i in range(3):
        item = {
            "_source": {
                "object": {
                    "submission_data": {"html_body": ""},
                    "url": "/international/invest/contact/",
                    "published": datetime.now().isoformat(),
                }
            },
            "sort": [12345, "submission_type"],
        }

        arrange_call = random.choice(["yes", "no", "yes", "yes", "no", "yes"])
        email_consent = random.choice(["True", "False", "False", "True", "True", "True"])
        phone_consent = random.choice(["True", "False", "False", "True", "True", "True"])
        detail = {
            "company_name": faker.company(),
            "first_name": faker.name(),
            "last_name": faker.name(),
            "email": faker.email(),
            "phone": faker.phone_number(),
            "arrange_call": arrange_call,
            "email_consent": email_consent,
            "phone_consent": phone_consent,
            "skip": False,
        }
        html_body = table_template.format(**detail)
        item["_source"]["object"]["submission_data"]["html_body"] = html_body
        # make one item with incorrect url so that it gets skipped
        if i == 1:
            item["_source"]["object"]["url"] = "/international/trade/contact/"
            detail["skip"] = True

        response["hits"]["hits"].append(item)
        details.append(detail)

    return response, details

class ActivityStreamIntegrationTests(TestCase):

    @freeze_time()
    @mock.patch("app.enquiries.tasks.update_enquirer_consents.apply_async")
    def test_fetch_new_enquiries(self, mock_task):
        """
        Test that fetches sample enquiries data, parses them and creates
        Enquiry objects and asserts data matches with input data

        Checks that for enquiries which come through activity stream the
        date_received field is populated with the date of creation.
        """
        with requests_mock.Mocker() as m:
            url = settings.ACTIVITY_STREAM_SEARCH_URL
            data, details = get_enquiries_data()
            m.get(url, json=data)

            self.assertEqual(Enquiry.objects.count(), 0)
            assert mock_task.call_count == 0
            fetch_and_process_enquiries()
            assert mock_task.call_count == 4
            self.assertEqual(Enquiry.objects.count(), 2)
            enquiry = Enquiry.objects.all().first()
            assert enquiry.date_received == enquiry.created

            for detail in details:
                if not detail["skip"]:
                    enquiry = model_to_dict(
                        Enquiry.objects.filter(company_name=detail["company_name"]).first()
                    )
                    enquirer = model_to_dict(Enquirer.objects.get(id=enquiry["enquirer"]))
                    for k, v in detail.items():
                        if k == "arrange_call":
                            v = True if v == "yes" else False
                        if k in enquiry.keys():
                            self.assertEqual(enquiry[k], v)
                        if k in enquirer.keys():
                            self.assertEqual(enquirer[k], v)
                else:
                    self.assertEqual(
                        Enquiry.objects.filter(company_name=detail["company_name"]).count(), 0
                    )


#
#
#  File: load_redis_access_py3.py
#
#
#
import json

class Load_Redis_Access(object):

   def __init__( self, app, auth, request, redis_handle ):
       self.app           = app
       self.auth          = auth
       self.request      = request
       self.redis_handle  = redis_handle

       #
       # Redis simple values
       #
       self.rules = [ # simple key, values
                      [ "redis_keys",            self.redis_keys],
                      [ "redis_get",             self.redis_get],
                      [ "redis_set",             self.redis_set],
                      [ "redis_del",             self.redis_del],
                      # list operations
                      ["redis_llen"      , self.redis_llen    ],
                      ["redis_rpush"     , self.redis_rpush   ],
                      ["redis_rpop"       , self.redis_rpop     ],
                      ["redis_lpush"     , self.redis_lpush   ],
                      ["redis_lpop"       , self.redis_lpop    ],
                      ["redis_lget"      , self.redis_lget    ],
                      ["redis_lset"      , self.redis_lset    ],
                      ["redis_ldelete"   , self.redis_ldelete ],
                      ["redis_lrange"     , self.redis_lrange  ],
                      ["redis_ltrim"      , self.redis_ltrim    ],
                      # hash operations
                      [ "redis_hset",               self.redis_hset    ],
                      [ "redis_hkeys",              self.redis_hkeys   ],
                      [ "redis_hget",               self.redis_hget    ],
                      [ "redis_hgetall",            self.redis_hgetall ],
                      [ "redis_hexist",             self.redis_hexist  ],
                      [ "redis_hdel",               self.redis_hdel    ]]

       for i in self.rules:
          a1 = auth.login_required( i[1] )
          app.add_url_rule('/ajax/'+i[0],i[0],a1,methods=["POST"])

   #
   # Functions
   #
   #

   #
   #  Redis Key Value Functions
   #
   #

   def redis_keys( self ):
       parm = self.request.get_json()
       return_value = []
       for i in parm:
           return_value.extend(self.redis_handle.keys(i))
       return return_value

   def redis_get(self):
       return_value = {}
       param = self.request.get_json()
       for i in param:
           temp = self.redis_handle.get( i )
           return_value[i] = temp
       return json.dumps( return_value )

   def redis_set(self):
       return_value = []
       param = self.request.get_json()
       for i,item in param.items():
           self.redis_handle.set( i,item )
       return json.dumps('SUCCESS')

   def redis_del(self):
       return_value = []
       param = self.request.get_json()
       for i in param.keys():
           self.redis_handle.delete( i )
       return json.dumps('SUCCESS')

   #
   #
   # list functions llen rpush, rop, lpush,lpop,  lrange ,ltrim, lset,ldelete
   # list insert is not implemented right now
   #
   #

   def redis_llen( self ):
       return_value = {}
       param = self.request.get_json()
       for i in param:
           temp = self.redis_handle.llen( i )
           return_value[i] = temp
       return json.dumps( return_value )

   def redis_rpush( self ):
       return_value = []
       param = self.request.get_json()
       for i,item in param.items():
           self.redis_handle.rpush( i,item )
       return json.dumps('SUCCESS')

   def redis_rpop( self ):
       return_value = {}
       param = self.request.get_json()
       for i in param:
           temp = self.redis_handle.rpop( i )
           return_value[i] = temp
       return json.dumps( return_value )

   def redis_lpush( self ):
       return_value = []
       param = self.request.get_json()
       for i,item in param.items():
           self.redis_handle.lpush( i,item )
       return json.dumps('SUCCESS')

   def redis_lpop(self ):
       return_value = {}
       param = self.request.get_json()
       for i in param:
           temp = self.redis_handle.rpop( i )
           return_value[i] = temp
       return json.dumps( return_value )

   def redis_lget( self ):
       return_value = {}
       param = self.request.get_json()
       for i in params:
           temp = self.redis_handle.lget( i, items["index"] )
           return_value[i] = { index: items["index"], "value": temp }
       return json.dumps( return_value )

   def redis_lset( self ):
       return_value = []
       param = self.request.get_json()
       for i,items in param.items():
           self.redis_handle.set( i,items["index"],items["value"] )
       return json.dumps('SUCCESS')

   def redis_ldelete(self ):
       param = self.request.get_json()
       token = "------------~~~~~~~~~~~~~~~~~~-----------------"
       key = param["key"]
       list_indexes = param["list_indexes"]
       for i in list_indexes:

           self.redis_handle.lset( key, i, token)
       self.redis_handle.lrem(key,0,token)
       return json.dumps('SUCCESS')

   def redis_lrange( self ):
       return_value = []
       param    = self.request.get_json()
       key      = param["key"]
       start    = param["start"]
       end      = param["end"]
       temp  = self.redis_handle.lrange(key,start,end)
       for i in temp:
          return_value.append(i)
       return json.dumps(return_value)

   def redis_ltrim( self ):
       param    = self.request.get_json()
       key      = param["key"]
       start    = param["start"]
       end      = param["end"]
       self.redis_handle.ltrim(key,start,end)
       return json.dumps('SUCCESS')

   #
   #
   # Hash functions
   #
   #
   #

   def redis_hset(self ):
       return_value = []
       param = self.request.get_json()

       for j in param:
           self.redis_handle.hset( j["redis_key"],j["hash"],j["value"] )
       return json.dumps('SUCCESS')

   def redis_hkeys(self ):
       return_value = {}
       param = self.request.get_json()

       for i in params:
           temp = self.redis_handle.hkeys( i )
           return_value[i] = { "keys":temp }
       return json.dumps( return_value )

   def redis_hget(self ):  # tested
       return_value = {}
       param = self.request.get_json()
       for i in param["key_list"]:
           temp = self.redis_handle.hget( param["hash_name"], i )
           #print("***********",param["hash_name"],i,temp)
           return_value[i] = temp
       return json.dumps( return_value )

   def redis_hgetall(self ): #tested
       return_value = {}
       param = self.request.get_json()
       temp = self.redis_handle.hgetall(param)
       for i,item in temp.items():
           return_value[i] = item
       return json.dumps( return_value )

   def redis_hexist(self ):
       return_value = {}
       param = self.request.get_json()
       for i in params:
           temp = self.redis_handle.hexit( i, items["key"] )
           return_value[i] = temp
       return json.dumps( return_value )

   def redis_hdel(self ):
       return_value = []
       param = self.request.get_json()
       for i,items in param.items():
           self.redis_handle.set( i,items["key"] )
       return json.dumps('SUCCESS')