# -*- coding: utf-8 -*-
import base64
import json
import hashlib
import hmac
from jsonview.decorators import json_view

from django.conf import settings
from django.http import Http404, HttpResponse
from django.shortcuts import redirect
from django.contrib import messages
from django.template import loader, Context
from django.utils.translation import gettext as _
from django.db.models import Sum
from django.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt
from django.core.exceptions import PermissionDenied
from django.db.models import Count
from django.urls import reverse
from django.utils import timezone
from django.utils.dateformat import format

from .forms import CheckoutForm
from .models import Cart, CartItem, CartSet, CartSetItem, Orders, OrderItems, Payment, PaymentRaw, Promo, Phones, \
    NovaPoshtaCities, NovaPoshtaWarehouses, NovaPoshtaRegions
from apps.info.models import Config
from apps.liqpay import LiqPay
from apps.elephants.models import Balance
from apps.helpers import normalize_phone, send_sms, delivery_cost_sum

@json_view
def cart(request):
    cart, created = Cart.objects.get_or_create(session_key=request.session.session_key)
    cart.session = request.session.session_key
    cart.save()

    if not created:
        cart_items = CartItem.objects.filter(cart=cart)
        for c_i in cart_items:
            c_i.bal = Balance.objects.get(item=c_i.item, size=c_i.size).amount
    else:
        cart_items = []

    t = loader.get_template('orders/cart.html')
    c = {'cart': cart, 'cart_items': cart_items}
    html = t.render(c, request)

    return {'html': html}

@json_view
def cart_remove(request, id, set=False):
    cart, created = Cart.objects.get_or_create(session_key=request.session.session_key)

    if not created:
        if set:
            try:
                cart_set = CartSet.objects.get(id=id)
            except:
                raise
                return {'success': False}
            else:
                set_items = CartSetItem.objects.filter(cartset=cart_set)
                for item in set_items:
                    try:
                        cart_item = CartItem.objects.get(item=item.item, size=item.size)
                    except CartItem.DoesNotExist:
                        raise
                        return {'success': False}
                    else:
                        cart_item.amount -= cart_set.amount
                        cart_item.amount_set -= cart_set.amount
                        cart_item.save()

                        if cart_item.amount == 0:
                            cart_item.delete()

                cart_set.delete()

        else:
            try:
                cart_item = CartItem.objects.get(id=id)
            except CartItem.DoesNotExist:
                return {'success': False}
            else:
                cart_item.amount = cart_item.amount_set
                cart_item.save()

                if cart_item.amount == 0:
                    cart_item.delete()
    else:
        return {'success': False}

    cart_items = CartItem.objects.filter(cart=cart)
    for c_i in cart_items:
        c_i.bal = Balance.objects.get(item=c_i.item, size=c_i.size).amount
    t = loader.get_template('orders/cart.html')
    c = {'cart': cart, 'cart_items': cart_items}
    html = t.render(c, request)

    return {'html': html, 'count': cart_items.count()}

@json_view
def cart_plus(request, id, set=False, plus=True):
    cart, created = Cart.objects.get_or_create(session_key=request.session.session_key)
    if not created:
        if not set:
            try:
                cart_item = CartItem.objects.get(id=id)
            except CartItem.DoesNotExist:
                return {'success': False}
            else:
                if plus:
                    cart_item.amount += 1
                else:
                    cart_item.amount -= 1
                cart_item.save()
    else:
        return {'success': False}

    cart_items = CartItem.objects.filter(cart=cart)
    for c_i in cart_items:
        c_i.bal = Balance.objects.get(item=c_i.item, size=c_i.size).amount
    t = loader.get_template('orders/cart.html')
    c = {'cart': cart, 'cart_items': cart_items}
    html = t.render(c, request)

    return {'html': html, 'count': cart_items.count()}

@json_view
def cart_warehouses(request, city_id, warehouse_id):
    warehouses = [(w.id, w.description, w.id == warehouse_id) for w in
                  NovaPoshtaWarehouses.objects.filter(novaposhtacities__id=city_id).order_by('number')]
    return {'success': True, 'warehouses': warehouses}

@json_view
def cart_cities(request, region_id, city_id):
    try:
        region = NovaPoshtaRegions.objects.get(pk=region_id)
    except:
        return {'success': False}
    if city_id == 0:
        cities = [(c.id, c.description, region.areasenter_ref == c.ref) for c in
                  NovaPoshtaCities.objects.filter(novaposhtaregions__id=region_id)]
    else:
        cities = [(c.id, c.description, city_id == c.id) for c in
                  NovaPoshtaCities.objects.filter(novaposhtaregions__id=region_id)]
    return {'success': True, 'cities': cities}

def price_description(request):
    config = Config.objects.get()
    description = ''
    if request.session['valuta']=='grn':
        description = config.price_description
    if request.session['valuta']=='usd':
        description = config.price_description_usd
    if request.session['valuta']=='eur':
        description = config.price_description_eur

    return description

@json_view
def cart_checkout(request):
    cart, created = Cart.objects.get_or_create(session_key=request.session.session_key)

    if created:
        return {'success': False}

    form = CheckoutForm(request.user, cart=cart, language=request.LANGUAGE_CODE)

    no_avail_items = 0

    cart_items = CartItem.objects.filter(cart=cart)

    for item in cart_items:
        if not item.check_avail():
            no_avail_items += 1

    if no_avail_items:

        t = loader.get_template('orders/cart.html')
        c = {'cart': cart, 'cart_items': cart_items}
        html = t.render(c, request)

        return {'form': False, 'html': html}

    if request.method == 'POST':
        form = CheckoutForm(request.user, request.POST, cart=cart, language=request.LANGUAGE_CODE)
        if form.is_valid():

            discount_stocks = int(cart.get_discount())

            discount_promo = 0
            if not discount_stocks:
                if form.cleaned_data['promo']:
                    if discount_stocks == 0:
                        codes = Promo.objects.filter(code=form.cleaned_data['promo'], used=False)
                        if codes:
                            code = codes[0]
                            discount_promo = code.discount
                            code.used = True
                            code.save()

                            message1 = _('Thank you. Your bonus %s percent activated.') % code.discount
                            messages.add_message(
                                request,
                                messages.SUCCESS,
                                message1
                            )
                    else:
                        message1 = _('Your discount on the share is %(sum)s %(dsc)s.
') % {'sum': cart.discount_stocks_val(request), 'dsc': price_description(request)}
                        message1 += _('Your promo-code is not activated.')
                        messages.add_message(
                            request,
                            messages.SUCCESS,
                            message1
                        )

            phone = Phones.objects.filter(phone=normalize_phone(form.cleaned_data['phone']))

            if phone:
                p = phone[0]
                if discount_stocks == 0 and discount_promo == 0 and p.active:
                    discount_promo = settings.DISCOUNT_PHONE

                    message0 = _('Thank you. Your discount is %s percent.
') % settings.DISCOUNT_PHONE
                    messages.add_message(
                        request,
                        messages.SUCCESS,
                        message0
                    )
                p.news = True
                p.save()

            else:
                p = Phones()
                p.phone = normalize_phone(form.cleaned_data['phone'])
                p.lang_code = request.LANGUAGE_CODE
                p.save()

                message0 = _('Thank you. After payment of the order your discount will be %s percent.
') % settings.DISCOUNT_PHONE
                message0 += '%(text)s' % ({'url': reverse('messages_off', args=(p.id,)), 'text': _('Do not recive messages about promotion.')})
                messages.add_message(
                    request,
                    messages.SUCCESS,
                    message0
                )

            delivery_cost = 0
            if form.cleaned_data['delivery'] == 3:
                delivery_cost = delivery_cost_sum(form.cleaned_data['country'], cart)

            order = Orders()
            order.name = form.cleaned_data['name']
            order.last_name = form.cleaned_data['last_name']
            order.phone = normalize_phone(form.cleaned_data['phone'])
            order.email = form.cleaned_data['email']
            order.lang_code = request.LANGUAGE_CODE
            order.payment_method = form.cleaned_data['payment']
            order.delivery_method = form.cleaned_data['delivery']
            order.user_comment = form.cleaned_data['shipping']
            order.delivery_cost = delivery_cost
            order.discount_promo = discount_promo
            order.discount_stocks = cart.discount_stocks
            if form.cleaned_data['payment']==5:
                order.paid = True
                order.ttn = 0
                order.date_of_delivery = timezone.now()
                order.delivered = True
                order.packed = True
            order.save()

            cart_items = CartItem.objects.filter(cart=cart)

            for item in cart_items:
                balance = Balance.objects.get(item=item.item, size=item.size)

                orderitem = OrderItems()
                orderitem.order = order
                orderitem.balance = balance
                orderitem.amount = item.amount
                orderitem.price = item.item.get_actual_price()
                orderitem.save()

            items = OrderItems.objects.filter(order=order)
            sum = 0

            for i in items:
                sum += i.price * i.amount

            order.discount_set = sum - cart.get_total()
            order.save()

            if form.cleaned_data['payment'] == 5:
                p = Payment()
                p.order = order
                p.amount = order.get_total_price_grn()
                p.comment = _('In showroom')
                p.save()

            cart.delete()

            if order.payment_method == 2:
                if order.lang_code == 'en':
                    text = 'Your order #%(number)s has been taken. Card number is %(card)s (%(name)s) and sum is %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'card': settings.PRIVAT_CARD, 'name': settings.PRIVAT_NAME, 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                    text += ' Please indicate your name or order number in the payment order'
                elif order.lang_code == 'ru':
                    text = 'Ваш заказ №%(number)s был принят. Номер карты %(card)s (%(name)s). Сумма к оплате %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'card': settings.PRIVAT_CARD, 'name': settings.PRIVAT_NAME, 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                    text += ' Пожалуйста, укажите в назначении платежа свою фамилию или номер заказа'
                elif order.lang_code == 'uk':
                    text = 'Ваше замовлення №%(number)s було прийняте. Номер картки %(card)s (%(name)s). Сума до оплати %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'card': settings.PRIVAT_CARD, 'name': settings.PRIVAT_NAME, 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                    text += ' Буьласка, вкжіть в призначенні платежу своє прізвище або номер замовлення'
                else:
                    text = ''

                send_sms(order.phone, text)

            elif order.payment_method == 1:
                if order.lang_code == 'en':
                    text = 'Your order #%(number)s has been taken. Card number is %(card)s (%(name)s) and sum is %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'card': settings.MONO_CARD, 'name': settings.MONO_NAME, 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                    text += ' Please indicate your name or order number in the payment order'
                elif order.lang_code == 'ru':
                    text = 'Ваш заказ №%(number)s был принят. Номер карты %(card)s (%(name)s). Сумма к оплате %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'card': settings.MONO_CARD, 'name': settings.MONO_NAME, 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                    text += ' Пожалуйста, укажите в назначении платежа свою фамилию или номер заказа'
                elif order.lang_code == 'uk':
                    text = 'Ваше замовлення №%(number)s було прийняте. Номер картки %(card)s (%(name)s). Сума до оплати %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'card': settings.MONO_CARD, 'name': settings.MONO_NAME, 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                    text += ' Буьласка, вкжіть в призначенні платежу своє прізвище або номер замовлення'
                else:
                    text = ''

                send_sms(order.phone, text)

            else:
                if order.payment_method != 5:
                    if order.lang_code == 'en':
                        text = 'Your order #%(number)s has been taken. Total price is %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                        text += ' Please indicate your name or order number in the payment order'
                    elif order.lang_code == 'ru':
                        text = 'Ваш заказ №%(number)s был принят. Сумма к оплате %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                        text += ' Пожалуйста, укажите в назначении платежа свою фамилию или номер заказа'
                    elif order.lang_code == 'uk':
                        text = 'Ваше замовлення №%(number)s було прийняте. Сума до оплати %(sum)s %(dsc)s. CatCult' % {'number': order.get_number(), 'sum': order.get_total_price(request), 'dsc': price_description(request)}
                        text += ' Буьласка, вкжіть в призначенні платежу своє прізвище або номер замовлення'
                    else:
                        text = ''

                    if order.payment_method == 0:
                        send_sms(order.phone, text)

            if order.payment_method != 5:
                messages.add_message(
                    request,
                    messages.SUCCESS,
                    text
                )

            if order.phone:
                try:
                    ph_s = str(order.phone)
                except:
                    ph_s = _('Error in phone number.')
            else:
                ph_s = _('Phone number is not set.')

            message = _('Your order has been placed. We will contact you shortly.
Order details:
')
            message += str(order.get_number()) + '
' + ph_s + '
'
            for item in order.orderitems_set.all():
                message += item.balance.item.name + ' - '
                message += item.balance.size.name + ' - '
                message += str(item.amount) + '
'
            if delivery_cost:
                if request.session['valuta'] == 'grn':
                    pass
                else:
                    config = Config.objects.get()
                    rate = 1
                    if request.session['valuta'] == 'usd':
                        rate = config.dollar_rate
                    if request.session['valuta'] == 'eur':
                        rate = config.euro_rate
                    delivery_cost = round(delivery_cost / rate, 2)
                message += _('Cost of delivery:') + ' ' + str(delivery_cost) + ' ' + price_description(request) + '
'
            message += _('Total:') + ' ' + str(order.get_total_price(request)) + ' ' + price_description(request) + '
'

            messages.add_message(
                request,
                messages.SUCCESS,
                message
            )

            if order.payment_method == 3:
                """
                LiqPay form below.
                """
                """
                liqpay = LiqPay(settings.LIQPAY_PUBLIC_KEY, settings.LIQPAY_PRIVATE_KEY)
                payment_form = liqpay.cnb_form({
                    'action': 'pay',
                    'amount': order.get_total_price_grn(),
                    'currency': 'UAH',
                    'description': 'CatCult order',
                    'order_id': order.id,
                    'server_url': settings.LIQPAY_CALLBACK,
                    'result_url': settings.LIQPAY_SUCCESS
                })

                return {'payment_form': payment_form}
                """
                config = Config.objects.get()
                payment = {}
                payment['account'] = config.merchant_account
                payment['domain'] = config.merchant_domain_name
                payment['tr_type'] = 'SALE'
                payment['auth_type'] = 'SimpleSignature'
                payment['sign'] = ''
                payment['url'] = 'https://' + config.merchant_domain_name + reverse('wfp_callback')
                payment['order_id'] = order.id
                payment['order_date'] = format(order.added, 'U')
                payment['amount'] = order.get_total_price_grn()
                payment['currency'] = 'UAH'
                payment['products'] = []
                payment['prices'] = []
                payment['counts'] = []
                payment['first_name'] = order.name
                payment['last_name'] = order.last_name
                payment['phone'] = order.phone
                payment['lang'] = 'AUTO'

                for order_item in order.orderitems_set.all():
                    payment['products'].append(order_item.balance.item.name)
                    payment['prices'].append(order_item.price)
                    payment['counts'].append(order_item.amount)

                products_str = ';'.join(payment['products'])
                prices_str = ';'.join(str(x) for x in payment['prices'])
                counts_str = ';'.join(str(x) for x in payment['counts'])

                sign_str = ';'.join([
                    payment['account'], payment['domain'], str(payment['order_id']),
                    str(payment['order_date']), str(payment['amount']), payment['currency'],
                    products_str, str(counts_str), str(prices_str)
                ])
                payment['sign'] = hmac.new(
                    str.encode(config.merchant_secret),
                    str.encode(sign_str),
                    hashlib.md5
                ).hexdigest()

                return {'payment': payment}

            return {'form': False}

    t = loader.get_template('orders/cart_checkout.html')
    c = {'form': form}
    html = t.render(c, request)

    button_text = _('Place the order')

    return {'form': True, 'html': html, 'button_text': button_text}

@csrf_exempt
def liqpay_callback(request):
    if request.method == 'POST':
        raw = PaymentRaw()
        raw.data = request.POST.get('data', '')
        raw.sign = request.POST.get('signature', '')
        try:
            raw.data_decoded = base64.b64decode(request.POST.get('data', '')).decode()
        except:
            pass
        raw.save()

        liqpay = LiqPay(settings.LIQPAY_PUBLIC_KEY, settings.LIQPAY_PRIVATE_KEY)
        sign = liqpay.str_to_sign(
            settings.LIQPAY_PRIVATE_KEY +
            request.POST.get('data', '') +
            settings.LIQPAY_PRIVATE_KEY
        )

        if request.POST.get('signature', '') == sign.decode():
            response = json.loads(base64.b64decode(request.POST.get('data')).decode())

            if response['status'] == 'success':
                try:
                    order = Orders.objects.get(id=int(response['order_id']))
                except:
                    return HttpResponse()

                payment = Payment()
                payment.order = order
                payment.amount = int(response['amount'])
                payment.comment = 'LiqPay'
                payment.token = response['liqpay_order_id']
                payment.sender_phone = response['sender_phone']
                payment.save()

                if order.get_total_price_grn() == order.get_total_paid():
                    order.paid = True
                    order.save()
                else:
                    order.paid = False
                    order.save()

                try:
                    phone = Phones.objects.get(phone=order.phone)
                    phone.active = True
                    phone.save()
                except:
                    pass

                return HttpResponse()

            else:
                try:
                    order = Orders.objects.get(id=int(response['order_id']))
                except:
                    return HttpResponse()

                order.liqpay_wait_accept = True
                order.save()
                return HttpResponse()

@csrf_exempt
def wfp_callback(request):
    if request.method == 'POST':
        config = Config.objects.get()
        raw = PaymentRaw()
        raw.data = request.body.decode('utf-8')
        raw.sign = ''
        raw.save()
        try:
            data = json.loads(raw.data)
            raw.sign = data['merchantSignature']
            raw.save()
        except:
            raise

        sign_str = ';'.join([
            data['merchantAccount'], str(data['orderReference']), str(data['amount']),
            data['currency'], str(data['authCode']), data['cardPan'],
            data['transactionStatus'], str(data['reasonCode'])
        ])

        sign = hmac.new(
            str.encode(config.merchant_secret),
            str.encode(sign_str),
            hashlib.md5
        ).hexdigest()

        if sign == raw.sign:
            response_dict = {}
            response_dict['orderReference'] = data['orderReference']
            response_dict['status'] = 'accept'
            response_dict['time'] = format(timezone.now(), 'U')
            response_dict['signature'] = ''

            response_sign_str = ';'.join([
                response_dict['orderReference'], response_dict['status'],
                str(response_dict['time'])
            ])

            response_dict['signature'] = hmac.new(
                str.encode(config.merchant_secret),
                str.encode(response_sign_str),
                hashlib.md5
            ).hexdigest()

            if data['transactionStatus'] == 'Approved':
                try:
                    order = Orders.objects.get(id=int(data['orderReference']))
                except:
                    return HttpResponse(json.dumps(response_dict, ensure_ascii=False), content_type="text/plain")

                payment = Payment()
                payment.order = order
                payment.amount = int(data['amount'])
                payment.comment = 'WayForPay'
                payment.token = data['orderReference']
                payment.sender_phone = data['phone']
                payment.save()

                if order.get_total_price_grn() == order.get_total_paid():
                    order.paid = True
                    order.liqpay_wait_accept = False
                    order.save()
                else:
                    order.paid = False
                    order.save()

                try:
                    phone = Phones.objects.get(phone=order.phone)
                    phone.active = True
                    phone.save()
                except:
                    pass

                return HttpResponse(json.dumps(response_dict, ensure_ascii=False), content_type="text/plain")

            else:
                try:
                    order = Orders.objects.get(id=int(data['orderReference']))
                except:
                    return HttpResponse(json.dumps(response_dict, ensure_ascii=False), content_type="text/plain")

                order.liqpay_wait_accept = True
                order.wfp_status = '; '.join([data['transactionStatus'], str(data['reasonCode']), data['reason']])
                order.save()
                return HttpResponse(json.dumps(response_dict, ensure_ascii=False), content_type="text/plain")
        else:
            return HttpResponse()

def messages_off(request, id):
    try:
        phone = Phones.objects.get(id=id)
        phone.news = False
        phone.save()
        message = _('You were successfully unsubscribed.')
        messages.add_message(
            request,
            messages.SUCCESS,
            message
        )

    except:
        message = _('Something went wrong. Please try later or contact us.')
        messages.add_message(
            request,
            messages.WARNING,
            message
        )

    if request.headers.get('x-requested-with') == 'XMLHttpRequest':
        return HttpResponse(json.dumps({'message': message}), content_type = 'application/json')
    else:
        return redirect('main_page')

@json_view()
def cart_valuta(request):
    valuta = request.POST.get('valuta', 'grn')

    request.session['valuta'] = valuta

    return {'success': True}


from .read_dir import read_dir
from .write_file import write_file
import cv2
import math
import json
from threading import Thread
import numpy as np

def create_test_by_folder_thread(folder, items_per_class, base_dir, path, classId, video_cache):
    subdir = read_dir("{}\\{}".format(base_dir, folder))
    print("[{}] started".format(folder))
    usable_videos = []
    for image in subdir:
        if image[-4:] == ".png":
            if len(usable_videos) < items_per_class:
                file = video_cache[image]  # "{}\{}".format(path,image[:-4])
                print("[{}] {}%".format(folder, round((len(usable_videos) + 1) * 100 / items_per_class, 2)))
                vidcap = cv2.VideoCapture(file)
                vidcap.set(cv2.CAP_PROP_POS_MSEC, (30 * 1000))
                success, img = vidcap.read()
                offset = 1
                while success:
                    cropped_image = img[40:500, 20:480]
                    number_of_gray_pix = np.sum(cropped_image == 126)
                    if number_of_gray_pix > 10_000:
                        cv2.imwrite("data\\test\\{}-{}.png".format(classId, len(usable_videos)), cropped_image)
                        write_file(
                            "data\\test\\{}-{}.txt".format(classId, len(usable_videos)),
                            "{} 0.5 0.5 1 1".format(classId),
                        )
                        usable_videos.append(img[:-4])
                        success = False
                    else:
                        vidcap.set(cv2.CAP_PROP_POS_MSEC, ((30 + 10 * offset) * 1000))
                        success, img = vidcap.read()
                        offset = offset + 1
    print("[{}] done".format(folder))

def generate_testing_images(max_items):
    path = "G:\Videos\Valorant"
    base_dir = "data\\all_images"
    dir = read_dir(base_dir)

    # print(dir)

    video_cache = {}
    with open("data\\all_images.json", "r") as file:
        video_cache = json.loads(file.read().replace("\n", ""))

    items_per_class = math.ceil(max_items / len(dir))

    my_threads = []
    for folder in dir:
        my_threads.append(
            Thread(
                target=create_test_by_folder_thread,
                args=[folder, items_per_class, base_dir, path, len(my_threads), video_cache],
            )
        )
        my_threads[len(my_threads) - 1].start()

    for t in my_threads:
        t.join()
    print("done")


from selenium import webdriver
import sys

def test_scores_service():
    driver = webdriver.Chrome()
    driver.get('http://127.0.0.1:5000')
    score_value = driver.find_element('xpath', '//*[@id="score"]')
    score = score_value.text
    if int(score) > 1 and int(score) < 1000:
        return True
    else:
        return False

def main_function():
    if test_scores_service():
        return sys.exit(0)
    else:
        return sys.exit(1)

if __name__ == "__main__":
    main_function()


import requests
import json
import boto3
import botocore.auth
import botocore.awsrequest
import logging
import datetime

from main import DEV_MODE

def get_image_url(url):
  if url.startswith("s3://"):
    return convert_s3_to_http_url(url)
  elif not url.lower().endswith(('.jpg', '.png')):
    return download_and_upload_to_s3(url)
  else:
    return url

def convert_s3_to_http_url(s3_url):
    # Split the S3 URL into bucket and key
    parts = s3_url.replace("s3://", "").split("/")
    bucket = parts[0]
    key = "/".join(parts[1:])

    # Construct and return the HTTP URL
    http_url = f"http://{bucket}.s3.amazonaws.com/{key}"
    return http_url

def download_and_upload_to_s3(image_url):
    """
    Download image from a URL and upload it to Amazon S3 bucket.

    Parameters:
    image_url (str): URL of the image to be downloaded and uploaded.
    bucket_name (str): Name of the S3 bucket.
    s3_file_name (str): Desired file name to be used in S3.
    """
    # Initialize boto3 S3 client
    s3 = boto3.client('s3')

    # Get the current timestamp and convert it to a string
    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S_%f")

    bucket_name = "bookmark-scrapper-bucket"
    s3_file_name = f"{DEV_MODE.lower()}/uploaded_image_{timestamp}.jpg"
    logging.debug(f"download and upload, url: {image_url}")

    try:
        # Get image from URL
        response = requests.get(image_url, stream=True)
        response.raise_for_status()

        # Ensure the image is treated as binary data
        response.raw.decode_content = True

        # Upload image to S3
        s3.upload_fileobj(response.raw, bucket_name, s3_file_name)
        print(f"Successfully uploaded {s3_file_name} to {bucket_name}")

        public_url = f"https://{bucket_name}.s3.amazonaws.com/{s3_file_name}"
        return public_url

    except requests.exceptions.RequestException as e:
        print(f"Error getting image from URL: {e}")

    except Exception as e:
        print(f"An error occurred: {e}")


from bs4 import BeautifulSoup
from bs4.dammit import EncodingDetector
import requests
from wordcloud import WordCloud, ImageColorGenerator, STOPWORDS
import matplotlib.pyplot as plt
import sqlite3

# helps render image
from PIL import Image

# path functions to help access the image
from os import path, getcwd

# render image correctly for our function
import numpy as np

# import nltk
# nltk.download('all')

# import scipy.sparse.linalg as sp
# id = np.eye(13)
# vals, vecs = sp.eigsh(id, k=6)
# vals

# natural language processing toolkit to help process our data
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

# create function so that it is more generalized - can be used for other scenarios
def get_soup(html):
    """ get data for web page"""
    resp = requests.get(film_list)
    # if charcleacterset is in the header of content type then we'll convert to lower case or else we will not include it
    http_encoding = resp.encoding if 'charset' in resp.headers.get('content-type', '').lower() else None
    html_encoding = EncodingDetector.find_declared_encoding(resp.content, is_html=True)
    # encoding variable to include if it is http or html
    encoding = html_encoding or http_encoding
    # we'll get content of response from the request we made (see line 23) and we'll use this type of encoding to return soup object, which includes all html content for the website
    soup = BeautifulSoup(resp.content, features="html.parser")
    return soup

def get_links(soup):
    """ Get links from a web page """
    http_link_list = []
    for link in soup.find_all('a', href=True):
        if link['href']!= '/':
            http_link_list.append(link['href'].strip("'"))
    return http_link_list

def get_ps(soup):
    """ get <h1> tags from web page"""
    http_link_list = []
    for link in soup.find_all('h3'):
        http_link_list.append(link.get_text())
    return http_link_list

def get_text(text_array):
    """ get text from an array"""
    text = " ".join(text_array)
    return text

def get_film_text(film_list):
    """get text from all film in list"""
    text_return = []
    for i in film_list:
        print(i)
        soup = get_soup(i)
        text_array = get_ps(soup)
        full_text = get_text(text_array)
        text_return.append(full_text)
    return text_return

def punctuation_stop(text):
    """remove punctuation and stop words"""
    filtered = []
    stop_words = set(stopwords.words('english'))
    word_tokens = word_tokenize(text)
    for w in word_tokens:
        if w not in stop_words and w.isalpha():
            filtered.append(w.lower())
    return filtered

#webpage
film_list = "https://www.timeout.com/film/best-horror-films"

#gets word soup from website
soupout = get_soup(film_list)
soupout

#gets links from website
h_links = get_links(soupout)

html_links = h_links[0:30]

#return list of all episode text
text_return_list = get_film_text(html_links)
all_text = get_text(text_return_list)

#removed punctuation and stop words
filteredlst = punctuation_stop(all_text)

# #list of unwanted words
unwanted = ['noble']

#remove unwanted words
text = " ".join([ele for ele in filteredlst if ele not in unwanted])

#get the working directory
d = getcwd()

#numpy image file of mask image
mask = np.array(Image.open("halloween-logo.jpg"))

#create the word cloud object
wc= WordCloud(background_color="black", max_words=2000, max_font_size=90, random_state=1, mask=mask, stopwords=STOPWORDS)
wc.generate(text)

image_colors = ImageColorGenerator(mask)

plt.figure(figsize=[10,10])
plt.imshow(wc.recolor(color_func=image_colors), interpolation="bilinear")
plt.axis('off')
plt.show()


# -*- coding: utf-8 -*-
"""
Spyder Editor

"""

import os
import re
import zipfile
import tkinter
from tkinter import filedialog, messagebox

def show_error(text):
    tkinter.messagebox.showerror('Error',text)

def show_results(text):
    tkinter.messagebox.showinfo('Results',text)

def count(files):
    #define a dictionary to hold the filename and a count of number of slides:
    decks = {}
    results = ""
    #for each file check if it is a pptx file and set count to 0 or show error message
    for file in files:
        if os.path.abspath(file).endswith('.pptx'):
            decks[(os.path.abspath(file))] = 0
        else:
            show_error('The file %s is not a .pptx file and it will be ignored'%(file))
    #counting slides in each deck
    for deck, count in decks.items():
        try:
            #try to read the file as a zipfile since pptx works like a zipfile
            archive = zipfile.ZipFile(deck,'r')
            contents = archive.namelist()
            #We cannot directly count the len of contents to get the number of slides as the list contains elemetns like 'ppt','slides','docprops',etc.
        except Exception as e:
            #error in reading file
            show_error('Error reading %s (%s). Hence, count set to 0'%(os.path.abspath(deck),e))
        #if no exeption occurred
        else:
            for name in contents:
                if(re.findall('ppt/slides/slide',name)):
                    decks[deck] += 1
    results += ('Slides\tDeck\n')

    for deck, count in decks.items():
        results += ('%s\t\t%s\n'%(count,os.path.basename(deck)))

    if show_summary.get():
        results += ('\n- - - - -\n')
        total = 0
        for count in decks.values():
            total += count
        results += ('Total slides in %s decks: %s'%(len(decks),total))
    show_results(results)

#Creating the GUI to read the pptx files
root = tkinter.Tk()
root.geometry('275x175')
root.title("Slide Counter")

#create file dialogbox to select files
def openfilebutton():
    t = tkinter.filedialog.askopenfilenames()
    count(t)

#Design the dialog box
header = tkinter.Label(root,text='Welcome to Slide Counter!', fg='blue', font=('Times Bold', 18))
header.pack(side='top',ipady = 10)

text = tkinter.Label(root,text='Select some .pptx files, and the\n app will count how many slides\n are contained within them.')
text.pack()

show_summary = tkinter.BooleanVar() #create a variable
show_summary.set(True)
summary = tkinter.Checkbutton(root, text='Show summary', var=show_summary) #create a checkbutton and link it to the bool var
summary.pack(ipady = 10)

openfiles = tkinter.Button(root, text='Choose files', command=openfilebutton)
openfiles.pack(fill="x")

# Initialize Tk window.
root.mainloop()


# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from django.utils.translation import gettext_lazy as _
from horizon import exceptions
from horizon import tabs
from horizon import utils as horizon_utils

from tacker_horizon.openstack_dashboard import api
from tacker_horizon.openstack_dashboard.dashboards.nfv.nsmanager import tables
from tacker_horizon.openstack_dashboard.dashboards.nfv import utils

class NSManagerTab(tabs.TableTab):
    name = _("NSManager Tab")
    slug = "nsmanager_tab"
    table_classes = (tables.NSManagerTable,)
    template_name = ("horizon/common/_detail_table.html")
    preload = False

    def has_more_data(self, table):
        return self._has_more

    def get_nsmanager_data(self):
        try:
            tables.NSManagerItemList.clear_list()
            nss = api.tacker.ns_list(self.request)

            if len(nss) > horizon_utils.functions.get_page_size(
                    self.request):
                self._has_more = True
            else:
                self._has_more = False

            for ns in nss:
                try:
                    ns_desc_str = ns['description']
                except KeyError:
                    ns_desc_str = ""

                vim = ns['vim_id']
                obj = tables.NSManagerItem(
                    ns['name'],
                    ns_desc_str,
                    vim,
                    ns['status'],
                    ns['id'],
                    ns['error_reason'])
                tables.NSManagerItemList.add_item(obj)
            return tables.NSManagerItemList.NSLIST_P
        except Exception:
            self._has_more = False
            error_message = _('Unable to get instances')
            exceptions.handle(self.request, error_message)

            return []

class NSManagerTabs(tabs.TabGroup):
    slug = "nsmanager_tabs"
    tabs = (NSManagerTab,)
    sticky = True

class NSEventsTab(tabs.TableTab):
    name = _("Events Tab")
    slug = "events_tab"
    table_classes = (utils.EventsTable,)
    template_name = ("horizon/common/_detail_table.html")
    preload = False

    def has_more_data(self, table):
        return self._has_more

    def get_events_data(self):
        try:
            utils.EventItemList.clear_list()
            events = api.tacker.events_list(self.request,
                                            self.tab_group.kwargs['ns_id'])

            if len(events) > horizon_utils.functions.get_page_size(
                    self.request):
                self._has_more = True
            else:
                self._has_more = False

            for event in events:
                evt_obj = utils.EventItem(
                    event['id'], event['resource_state'],
                    event['event_type'],
                    event['timestamp'],
                    event['event_details'])
                utils.EventItemList.add_item(evt_obj)
            return utils.EventItemList.EVTLIST_P
        except Exception:
            self._has_more = False
            error_message = _('Unable to get events.')
            exceptions.handle(self.request, error_message)
            return []

class NSDetailsTabs(tabs.TabGroup):
    slug = "NS_details"
    tabs = (NSEventsTab,)
    sticky = True


import json
import os
import datetime

from django.views import View
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt

from django.shortcuts import render, redirect
from django.http import HttpResponse

# import urllib2
from django.urls import reverse

# from consts.request_params import RequestParams
from utility import UUID
from utility import send_now

from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth import update_session_auth_hash

from utility.session import Session

from fixkori_api.models import UserClient
from fixkori_api.models import UserServiceProvider
from fixkori_api.models import UserAdmin
from fixkori_api.models import Order
from fixkori_api.models import Area
from fixkori_api.models import Item

import constants

class Home(View):

    @staticmethod
    def get(request):
        if 'token' not in request.session:
            return render(request, 'customer/index.html')

        logged_in_user = Session.get_user_by_session(request.session['token'])
        if logged_in_user is None:
            return render(request, 'customer/index.html')

        if logged_in_user.user_type == constants.USER_TYPE_CLIENT:
            logged_in_user_object = UserClient.objects.get(user=logged_in_user)
            return render(request, 'customer/index.html', {'client': True,
                                                           'logged_in_user_object': logged_in_user_object})

        elif logged_in_user.user_type == constants.USER_TYPE_SERVICE_PROVIDER:
            '''service provider'''
            return render(request, 'admin_vendor/vendor_index.html')

        elif logged_in_user.user_type == constants.USER_TYPE_ADMIN:
            '''admin'''
            yesterday = datetime.date.today() - datetime.timedelta(days=1)
            total_order = Order.objects.all().count()
            pending_order = Order.objects.filter(status=constants.ORDER_STATUS_PENDING).count()
            total_user = UserClient.objects.all().count()
            new_users = UserClient.objects.filter(created_at__gt=yesterday).count()
            total_vendor = UserServiceProvider.objects.all().count()
            service_today = Order.objects.filter(status=constants.ORDER_STATUS_COMPLETED,
                                                 last_updated__gt=yesterday).count()
            last_5_orders = Order.objects.filter(status=constants.ORDER_STATUS_PENDING)[:5]
            last_5_users = UserClient.objects.all()[:5]
            last_5_vendors = UserServiceProvider.objects.all()[:5]
            logged_in_user_object = UserAdmin.objects.get(user=logged_in_user)
            return render(request, 'admin_vendor/admin_index.html', {'admin': True,
                                                                     'total_order': total_order,
                                                                     'logged_in_user_object': logged_in_user_object,
                                                                     'pending_order': pending_order,
                                                                     'total_user': total_user,
                                                                     'new_users': new_users,
                                                                     'total_vendor': total_vendor,
                                                                     'service_today': service_today,
                                                                     'last_5_orders': last_5_orders,
                                                                     'last_5_users': last_5_users,
                                                                     'last_5_vendors': last_5_vendors})

class PlaceOrder(View):

    @staticmethod
    @login_required(login_url='/login/')
    def post(request):
        logged_in_user = Session.get_user_by_session(request.session['token'])
        client = UserClient.objects.get(user=logged_in_user)
        area = Area.objects.get(area_name=request.POST['area'])
        item = Item.objects.get(item_name=request.POST['item'])
        new_order = Order(customer=client,
                          area=area,
                          item=item,
                          brand=request.POST['brand'],
                          model=request.POST['model'],
                          service_type=int(request.POST['service_type']),
                          date=request.POST['date'],
                          address=request.POST['address'],
                          instruction=request.POST['instruction'],
                          description=request.POST['description'])
        new_order.save()
        greeting_text = 'We received your order. Allow us some time, and we will contact you as soon as possible.' \
                        ' Happy Fixing!'
        send_now(client.phone_number, greeting_text)
        send_now('01737233902', 'New order! Please check fixkori!')
        return redirect(reverse('home'))

    @staticmethod
    @login_required(login_url='/login/')
    def get(request):
        logged_in_user = Session.get_user_by_session(request.session['token'])
        client = UserClient.objects.get(user=logged_in_user)
        # todo have to add a order taking page with client info
        return redirect(reverse('home'))

class OrderList(View):

    @staticmethod
    @login_required(login_url='/login/')
    def get(request):
        logged_in_user = Session.get_user_by_session(request.session['token'])
        client = UserClient.objects.get(user=logged_in_user)
        all_orders = Order.objects.filter(customer=client)
        # todo have to add a order taking page with client info and all_order List
        return redirect(reverse('home'))

class OrderDetails(View):

    @staticmethod
    @login_required(login_url='/login/')
    def get(request, oid):
        logged_in_user = Session.get_user_by_session(request.session['token'])
        client = UserClient.objects.get(user=logged_in_user)
        order = Order.objects.get(ok=oid)
        if order.customer == client:
            # send data
            pass
        else:
            # do not send data
            pass
        # todo have to add a order taking page with client info and order details
        return redirect(reverse('home'))

class CancelOrder(View):

    @staticmethod
    @login_required(login_url='/login/')
    def get(request, oid):
        logged_in_user = Session.get_user_by_session(request.session['token'])
        client = UserClient.objects.get(user=logged_in_user)
        order = Order.objects.get(ok=oid)
        if order.customer == client:
            # change order state
            pass
        else:
            # do not change order state
            pass
        # todo have to add a order taking page with client info and order details
        return redirect(reverse('home'))

class UserProfile(View):

    @staticmethod
    @login_required(login_url='/login/')
    def get(request, oid):
        logged_in_user = Session.get_user_by_session(request.session['token'])
        client = UserClient.objects.get(user=logged_in_user)
        # todo have to send user object
        return redirect(reverse('home'))


#!/usr/bin/python
# coding=utf-8
import sys
import zipfile
import shutil
import os
import os.path
import time
import datetime
import json
import xml.etree.ElementTree as ET
#include common.py
sys.path.append('../../')
sys.path.append('./')
from Config.Config import mainConfig
from Common import Source
from Config.AdConfig import mainAdConfig
from Project.Resource import mainResource
from Common.File.FileUtil import FileUtil
from AppInfo.AppInfo import mainAppInfo
from AppStore.AppstoreUploadiOS import mainAppstoreUploadiOS

DEVICE_IPADPRO = "ipadpro"
DEVICE_IPADPRO_2018 = "ipadpro"
DEVICE_IPHONE_6_5 = "iphone_6_5"
DEVICE_IPHONE_5_5 = "iphone"

list_language = ["cn", "en"]
listCountry = ["en-US", "zh-Hans","en-CA","en-AU","en-GB"]
listCountryLanguage = ["en", "cn","en","en","en"]

totalScreenshot = 5
# "Mac", "appletvos", "iOS-3.5-in", "iOS-4-in", "iOS-4.7-in", "iOS-5.5-in", "iOS-5.8-in", "iOS-Apple-Watch", "iOS-iPad", "iOS-iPad-Pro" or "iOS-iPad-Pro-10.5-in"

list_device = [DEVICE_IPHONE_5_5,DEVICE_IPADPRO]
#list_device = [DEVICE_IPADPRO, DEVICE_IPHONE_6_5,DEVICE_IPHONE_5_5]
gameName = " "
gameType = " "
enableScrenshot = False
class UpdateAppstore():
    def loadJson(self,isHd):
        cur_path = mainResource.GetProjectConfigApp()+"/appinfo"
        jsonfile = cur_path+'/appinfo.json'
        if isHd:
            jsonfile = cur_path+'/appinfo_hd.json'

        with open(jsonfile) as json_file:
            data = json.load(json_file)
            return data

    def loadXmlDescription(self,isHd):
        cur_path = mainResource.GetProjectConfigApp()+"/appinfo"
        xmlfile = cur_path+'/app_description.xml'
        if isHd:
            xmlfile = cur_path+'/app_description_hd.xml'

        tree = ET.parse(xmlfile)
        root = tree.getroot()

        # cn = root.find('en')
        # print cn.tag
        # print cn.text

        return root

    def getXmlDescriptionText(self,root,key):
        for child in root.findall(key):
            return child.text
        # return root.find(key).text

    def replaceIAP_noad(self,filePath,strReplace):
        f = open(filePath, 'r')
        strContent = f.read()

        strStart = "<in_app_purchase>"
        idx = strContent.find(strStart)
        strHead = strContent[0:idx] + strStart

        idx = idx + len(strStart)
        strOther = strContent[idx:]

        strMid = "<product_id>"
        idx = strOther.find(strMid)
        strHead2 = strOther[0:idx] + strMid
        strHead += strHead2

        strEnd = "</product_id>"
        idx = strOther.find(strEnd)
        strOther = strOther[idx:]
        strRet = strHead + strReplace + strOther

        f.close()
        self.saveString2File(strRet,filePath)

    def replaceString(self,strContent, strStart, strEnd, strReplace):
        idx = strContent.find(strStart)
        strHead = strContent[0:idx]

        idx = idx + len(strStart)
        strOther = strContent[idx:]
        # print "strOther1:"+strOther
        idx = strOther.find(strEnd)
        strOther = strOther[idx:]
        # print "strOther2:"+strOther
        strRet = strHead + strStart + strReplace + strOther
        return strRet

    def replaceStringOfFile(self,filePath, strStart, strEnd, strReplace):
        f = open(filePath, 'r')
        strFile = f.read()
        # print strFile
        strOut = self.replaceString(strFile, strStart, strEnd, strReplace)
        # print strOut
        # fp_name.seek(0)
        # fp_name.write(strOut)
        f.close()
        return strOut

    def replaceString2(self,strContent, strStart, strMid, strEnd, strReplace):
        idx = strContent.find(strStart)
        strHead = strContent[0:idx] + strStart

        idx = idx + len(strStart)
        strOther = strContent[idx:]
        # print "strOther1:"+strOther
        idx = strOther.find(strMid)
        strHead2 = strOther[0:idx] + strMid
        strHead += strHead2

        idx = strOther.find(strEnd)
        strOther = strOther[idx:]
        # print "strOther2:"+strOther
        strRet = strHead + strReplace + strOther
        return strRet

    def replaceStringOfFile2(self,filePath, strStart, strMid, strEnd, strReplace):
        f = open(filePath, 'r')
        strFile = f.read()
        # print strFile
        strOut = self.replaceString2(strFile, strStart, strMid, strEnd, strReplace)
        # print strOut
        # fp_name.seek(0)
        # fp_name.write(strOut)
        f.close()
        return strOut

    def saveString2File(self,str, file):
        f = open(file, 'wb')  # 若是'wb'就表示写二进制文件
        b = str.encode('utf-8',"ignore")
        f.write(b)
        f.close()

    def replaceXmlKey(self,filepath,language,key,title):

        strStart = language
        # <keyword>
        strMid = "<"+key+">"
        # </keyword>
        strEnd = "</"+key+">"
        strOut = self.replaceStringOfFile2(
            filepath, strStart, strMid, strEnd, title)
        self.saveString2File(strOut, filepath)
    # <software_screenshots></software_screenshots>
    # <!-- <software_screenshots></software_screenshots> -->
    # 注释xmlkey
    def disableXmlKey(self,filePath,key):
        strFrom = "<"+key+">"+"</"+key+">"
        strTo = "<!-- <"+key+">"+"</"+key+"> -->"
        strFile = FileUtil.GetFileString(filePath)
        strFile = strFile.replace(strFrom,strTo)
        self.saveString2File(strFile,filePath)

    def getScreenshotFileName(self,device,language,idx):
        return language+"_"+device+"_"+str(idx+1)+".jpg";

    def getScreenshotFullFilePath(self,isHd,device,language,idx):
        strDir_itmsp = "app.itmsp"
        if isHd:
            strDir_itmsp = "app_pad.itmsp"
        strDirRootTo = mainResource.GetProjectConfigApp()+"/appstore/ios/"+strDir_itmsp
        strFileTo = strDirRootTo+"/"+self.getScreenshotFileName(device,language,idx)
        return strFileTo

    def copy_or_delete_one_screenshot(self,isHd,device,language,idx,isDel):
        strDirHorV = "shu"
        if isHd:
            strDirHorV = "heng"

        strDirRootFrom =mainResource.GetProjectOutPutApp()+"/screenshot"
        strFileFrom = strDirRootFrom+"/"+strDirHorV+"/"+language+"/"+device+"/"+str(idx+1)+".jpg";

        strFileTo = self.getScreenshotFullFilePath(isHd,device,language,idx)

        if isDel:
            if os.path.isfile(strFileTo):
                os.remove(strFileTo)
        else:
            # print strFileFrom
            if os.path.isfile(strFileFrom):
                shutil.copyfile(strFileFrom,strFileTo)

    def copy_screenshots(self):
        list_hd = [False, True]

        for device in list_device:
            print ("copy_screenshots device="+device)
            for language in list_language:
                for ishd in list_hd:
                    for i in range(0, totalScreenshot):
                        self.copy_or_delete_one_screenshot(ishd,device,language,i,False)

    def delete_screenshots(self):
        list_hd = [False, True]

        for device in list_device:
            for language in list_language:
                for ishd in list_hd:
                    for i in range(0, totalScreenshot):
                        self.copy_or_delete_one_screenshot(ishd,device,language,i,True)

    # /*
    # <software_screenshot display_target="iOS-5.5-in" position="1">
    #                                   <file_name>iphone_1.jpg</file_name>
    #                                   <size>263616</size>
    #                                   <checksum type="md5">dc695d677a5c33392bc88ba4eb9d719f</checksum>
    #                                </software_screenshot>
    #                                */
    def getXmlStringOneScreenshot(isHd,device,language,idx):
        filePath = self.getScreenshotFullFilePath(isHd,device,language,idx)
        strRet = " "
        if enableScrenshot:
            strRet = "<software_screenshot display_target=\""+getAppStoreScreenshotDeviceName(device)+"\" position=\""+str(idx+1)+"\"> <file_name>"+getScreenshotFileName(device,language,idx)+"</file_name> <size>"+str(mainResource.get_FileSize(filePath))+"</size> <checksum type=\"md5\">"+mainResource.get_MD5_checksum_file(filePath)+"</checksum> </software_screenshot>"
        return strRet

    def getXmlStringScreenshots(self,isHd,language):

        strRet = " "
        for device in list_device:
            for i in range(0, totalScreenshot):
                strFileTo = self.getScreenshotFullFilePath(isHd,device,language,i)
                if os.path.isfile(strFileTo):
                    strRet+="\n"+getXmlStringOneScreenshot(isHd,device,language,i)
        return strRet

    def getAppStoreScreenshotDeviceName(self,device):
        strRet = device
        if device==DEVICE_IPADPRO:
            strRet = "iOS-iPad-Pro"
        if device==DEVICE_IPHONE_5_5:
            strRet = "iOS-5.5-in"
        if device==DEVICE_IPHONE_6_5:
            strRet = "iOS-6.5-in"

        return strRet

    def DeleteInAppPurchasesScreenshot(self,isHd):
        rootConfig = mainResource.GetProjectConfigApp()
        dst = rootConfig + "/appstore/ios/app.itmsp"
        if isHd:
            dst = rootConfig + "/appstore/ios/app_pad.itmsp"
        filepath =dst+"/in_app_purchases_screenshot.png"

        if os.path.exists(filepath):
            os.remove(filepath)

    def CopyInAppPurchasesScreenshot(self,isHd):
        # src =mainResource.GetProjectConfig() + "/default/appstore/in_app_purchases_screenshot.png"
        src =mainResource.GetDirProductCommon() + "/in_app_purchases_screenshot.png"
        rootConfig = mainResource.GetProjectConfigApp()
        dst = rootConfig + "/appstore/ios/app.itmsp"
        if isHd:
            dst = rootConfig + "/appstore/ios/app_pad.itmsp"
        dst =dst+"/in_app_purchases_screenshot.png"

        if not os.path.isfile(dst):
            shutil.copyfile(src,dst)

    def IsOldVersion(self,data):
        isOld = True
        if ("appname" in data) :
            isOld = False

        return isOld

    def LoadJsonIAP(self,isHD,stros):

        if stros==Source.ANDROID:
            jsonfile = mainResource.GetConfigDataDir()+"/IAP/IAP_android.json"
            if isHD:
                jsonfile = mainResource.GetConfigDataDir()+"/IAP/IAP_android_hd.json"

        if stros==Source.IOS:
            jsonfile = mainResource.GetConfigDataDir()+"/IAP/IAP_ios.json"
            if isHD:
                jsonfile = mainResource.GetConfigDataDir()+"/IAP/IAP_ios_hd.json"

        jsonfile = os.path.normpath(jsonfile)
        strfile = FileUtil.GetFileString(jsonfile)
        return json.loads(strfile)

    def DeleteAllScreenshots(self,isHd):
        verison = mainAppInfo.GetAppVersion(Source.IOS,isHd)

        rootConfig = mainResource.GetProjectConfigDefault()
        str_metadata_xml = FileUtil.GetFileString(rootConfig + "/appstore/metadata_clear_screenshots.xml")
        str_metadata_xml=str_metadata_xml.replace("_VENDOR_ID_",mainAppInfo.GetAppSKU(isHd))
        str_metadata_xml=str_metadata_xml.replace("_VERSION_",verison)

        rootConfig = mainResource.GetProjectConfigApp()
        file_metadata_ios = rootConfig + "/appstore/ios/app.itmsp/metadata.xml"
        if isHd:
            file_metadata_ios = rootConfig + "/appstore/ios/app_pad.itmsp/metadata.xml"

        FileUtil.SaveString2File(str_metadata_xml,file_metadata_ios)
        mainAppstoreUploadiOS.Run(isHd)

    def UpdateIAPInfo(self,isHd):
        self.CopyInAppPurchasesScreenshot(isHd)
        self.UploadIAPInfo(isHd,Source.IOS)
        self.DeleteInAppPurchasesScreenshot(isHd)

    def UploadIAPInfo(self,isHd,stros):
        package = mainAppInfo.GetAppPackage(stros,isHd)
        rootJson = self.LoadJsonIAP(isHd,stros)
        rootConfig = mainResource.GetProjectConfigDefault()
        striap = FileUtil.GetFileString(rootConfig + "/appstore/KEY_IAP.xml")

        listIAP =[]
        for item in rootJson["items"]:
            if item["isSkip"]:
                continue

            name = item["key"]
            striap=striap.replace("_NAME_",name)
            product_id = package+"."+item["id"]
            striap=striap.replace("_ID_",product_id)

            # consumable non-consumable
            isConsume = item["isConsume"]
            product_type = "non-consumable"
            if isConsume:
                product_type = "consumable"

            striap=striap.replace("_TYPE_",product_type)

            title_cn = item["title"]["cn"]
            striap=striap.replace("_TITLE_CN_",title_cn)
            title_en = item["title"]["en"]
            striap=striap.replace("_TITLE_EN_",title_en)

            title_cn = item["detail"]["cn"]
            striap=striap.replace("_DETAIL_CN_",title_cn)
            title_en = item["detail"]["en"]
            striap=striap.replace("_DETAIL_EN_",title_en)

            price = item["price_tier"]
            striap=striap.replace("_PRICE_",price)

            listIAP.append(striap)

        str_metadata_xml = FileUtil.GetFileString(rootConfig + "/appstore/IAP_metadata.xml")
        str_metadata_xml=str_metadata_xml.replace("_VENDOR_ID_",mainAppInfo.GetAppSKU(isHd))
        strkeyiap = ""
        for strtmp in listIAP:
            strkeyiap+=strtmp

        str_metadata_xml=str_metadata_xml.replace("_KEY_IAP_",strkeyiap)

        rootConfig = mainResource.GetProjectConfigApp()
        file_metadata_ios = rootConfig + "/appstore/ios/app.itmsp/metadata.xml"
        if isHd:
            file_metadata_ios = rootConfig + "/appstore/ios/app_pad.itmsp/metadata.xml"

        FileUtil.SaveString2File(str_metadata_xml,file_metadata_ios)
        mainAppstoreUploadiOS.Run(isHd)

    def updateAppstore(self,isHd):

        self.CopyInAppPurchasesScreenshot(isHd)

        rootConfig = mainResource.GetProjectConfigApp()
        strHD = "HD"

        metadata_ios = rootConfig + "/appstore/ios/app.itmsp/metadata.xml"

        if isHd:
            metadata_ios = rootConfig + "/appstore/ios/app_pad.itmsp/metadata.xml"

        xmlRoot = self.loadXmlDescription(isHd)

        # filePath = rootConfig + "appstore/ios/app.itmsp/in_app_purchases_screenshot.png"
        # print mainResource.get_MD5_checksum_file(filePath)

        # loadJson
        data = self.loadJson(isHd)

        isOld = self.IsOldVersion(data)
        if isOld:
            # APP_NAME_CN_ANDROID = data["APP_NAME_CN_ANDROID"]
            APPSTORE_VERSION_UPDATE = data["APPSTORE_VERSION_UPDATE"]
            APPSTORE_TITLE = data["APPSTORE_TITLE"]
            APPSTORE_SUBTITLE = data["APPSTORE_SUBTITLE"]
            APPSTORE_PROMOTION = data["APPSTORE_PROMOTION"]
            PACKAGE = data["PACKAGE_IOS"]
            # APPSTORE_DESCRIPTION = data["APPSTORE_DESCRIPTION"]
            APPSTORE_KEYWORD = data["APPSTORE_KEYWORD"]
            APPVERSION_IOS = data["APPVERSION_IOS"]
        else:
            APPVERSION_IOS =  data["appversion"][Source.IOS]["value"]
            APPSTORE_KEYWORD =  data["appstore"]["aso"]
            PACKAGE = data["apppackage"][Source.IOS]["default"]
            APPSTORE_VERSION_UPDATE = data["appstore"]["version_update"]
            APPSTORE_PROMOTION =  data["appstore"]["promotion"]
            APPSTORE_SUBTITLE = data["appstore"]["subtitle"]
            APPSTORE_TITLE = data["appstore"]["title"]

        software_url = data["software_url"]
        privacy_url = data["privacy_url"]
        support_url = data["support_url"]
        sku_app = data["sku_app"]
        # need_upload_screenshot = data.get("need_upload_screenshot",False)
        need_upload_screenshot = False
        global enableScrenshot
        enableScrenshot = False

    # ios
    #     sku_app
        strStart = "<vendor_id>"
        strEnd = "</vendor_id>"

        strOut = self.replaceStringOfFile(
            metadata_ios, strStart, strEnd, sku_app)
        self.saveString2File(strOut, metadata_ios)

        print("APPVERSION_IOS=",APPVERSION_IOS)
        # APPVERSION_IOS
        # <version string="1.0.0">
        strStart = "<version string=\""
        strEnd = "\">"
        strOut = self.replaceStringOfFile(
            metadata_ios, strStart, strEnd, APPVERSION_IOS)
        self.saveString2File(strOut, metadata_ios)

        # 版本更新说明
        key = "version_whats_new"
        if APPVERSION_IOS=="1.0.0":
            self.disableXmlKey(metadata_ios,key)
        else:
            jsonData = APPSTORE_VERSION_UPDATE
            idx = 0
            for country in listCountry:
                lan = listCountryLanguage[idx]
                self.replaceXmlKey(metadata_ios,country,key,jsonData[lan])
                idx += 1

        # APPSTORE_TITLE
        key = "title"
        jsonData = APPSTORE_TITLE
        idx = 0
        for country in listCountry:
            lan = listCountryLanguage[idx]
            self.replaceXmlKey(metadata_ios,country,key,jsonData[lan])
            idx += 1

        # APPSTORE_TITLE
        key = "subtitle"
        jsonData = APPSTORE_SUBTITLE
        idx = 0
        for country in listCountry:
            lan = listCountryLanguage[idx]
            self.replaceXmlKey(metadata_ios,country,key,jsonData[lan])
            idx += 1

    # APPSTORE_PROMOTION
        key = "promotional_text"
        jsonData = APPSTORE_PROMOTION
        idx = 0
        for country in listCountry:
            lan = listCountryLanguage[idx]
            self.replaceXmlKey(metadata_ios,country,key,jsonData[lan])
            idx += 1

        # APPSTORE_DESCRIPTION
        key = "description"
        # jsonData = APPSTORE_DESCRIPTION
        idx = 0
        for country in listCountry:
            lan = listCountryLanguage[idx]
            desc = self.getXmlDescriptionText(xmlRoot,lan)
            self.replaceXmlKey(metadata_ios,country,key,desc)
            idx += 1

        # APPSTORE_KEYWORD
        key = "keyword"
        jsonData = APPSTORE_KEYWORD
        idx = 0
        for country in listCountry:
            lan = listCountryLanguage[idx]
            self.replaceXmlKey(metadata_ios,country,key,jsonData[lan])
            idx += 1

        # software_url
        key = "software_url"
        jsonData = software_url
        idx = 0
        for country in listCountry:
            self.replaceXmlKey(metadata_ios,country,key,jsonData)
            idx += 1

        # support_url
        key = "support_url"
        jsonData = support_url
        idx = 0
        for country in listCountry:
            lan = listCountryLanguage[idx]
            self.replaceXmlKey(metadata_ios,country,key,jsonData)
            idx += 1

        # privacy_url
        key = "privacy_url"
        jsonData = privacy_url
        idx = 0
        for country in listCountry:
            lan = listCountryLanguage[idx]
            self.replaceXmlKey(metadata_ios,country,key,jsonData)
            idx += 1

    # screenshot
        # key = "software_screenshots"
        # if enableScrenshot:
        #     screenshot_cn = self.getXmlStringScreenshots(isHd,"cn")
        #     screenshot_en = self.getXmlStringScreenshots(isHd,"en")
        #     self.replaceXmlKey(metadata_ios,"en-US",key,screenshot_en)
        #     self.replaceXmlKey(metadata_ios,"zh-Hans",key,screenshot_cn)
        #     # replaceXmlKey(metadata_ios,"en-CA",key,screenshot_en)
        #     # replaceXmlKey(metadata_ios,"en-AU",key,screenshot_en)
        #     # replaceXmlKey(metadata_ios,"en-GB",key,screenshot_en)
        # else:
        #     self.disableXmlKey(metadata_ios,"software_screenshots")

    # noad
        self.replaceIAP_noad(metadata_ios,PACKAGE+".noad")
        # replaceIAP_noad(metadata_ios,"noad")

# 主函数的实现
    def Run(self,isHd):
        print ("UpdateAppstore Run")
        gameName = mainResource.getGameName()
        gameType = mainResource.getGameType()

        print (gameName)
        print (gameType)

        if len(sys.argv)>2:
            if sys.argv[2] == "delete_screenshot":
                # delete_screenshots()
                sys.exit(0)

        #先从default 拷贝 文件模版
        dir_default = mainResource.GetProjectConfigDefault()
        dir_to = mainResource.GetProjectConfigApp()
        dir1 = dir_default+"/appstore"
        dir2 = dir_to + "/appstore"
        flag = os.path.exists(dir2)
        print ("UpdateAppstore dir1="+dir1+"dir2="+dir2)
        if flag:
            shutil.rmtree(dir2)

        shutil.copytree(dir1,dir2)

        # self.copy_screenshots()

        self.updateAppstore(isHd)
        # self.updateAppstore(True)

        print ("UpdateAppstore sucess")

mainUpdateAppstore = UpdateAppstore()


import keras
from keras.models import Sequential
from keras.models import load_model
from keras.layers import Dense, LSTM
from keras.optimizers import Adam
from keras import regularizers
from keras import initializers
from keras.layers import *
from keras.models import *
from keras import layers, models, optimizers
from keras import backend as K
import numpy as np
import random
from collections import deque

class Agent:
    def __init__(self, state_size, is_eval=False, model_name=""):
        self.state_size = state_size # normalized previous days
        self.action_size = 3 # sit, buy, sell
        self.memory = deque(maxlen=1000)
        self.inventory = []
        self.model_name = model_name
        self.is_eval = is_eval

        self.gamma = 0.95
        self.epsilon = 1.0
        self.epsilon_min = 0.01
        self.epsilon_decay = 0.995

        self.model = load_model("/models/" + model_name) if is_eval else self._model()

    def _model(self):
        input_tensor = Input((self.state_size,1,))
        x = input_tensor
        x = LSTM(8,return_sequences = True)(x)
        x = LSTM(16,return_sequences = True)(x)
        #x = LSTM(32*2**2,return_sequences = True)(x)
        x = Dropout(0.5)(x)
        x = Flatten()(x)
        x = Dense(self.action_size, activation='linear', kernel_initializer = 'normal')(x)
        model = Model(inputs=input_tensor, outputs=x)
        model.compile(loss="mse", optimizer=Adam(lr=0.001))

        return model

    def act(self, state):
        if not self.is_eval and random.random() <= self.epsilon:
            return random.randrange(self.action_size)

        options = self.model.predict(state)
        return np.argmax(options[0])

    def expReplay(self, batch_size):
        mini_batch = []
        l = len(self.memory)
        for i in range(l - batch_size + 1, l):
            mini_batch.append(self.memory[i])
            #print("mini_batch")

        for state, action, reward, next_state, done in mini_batch:
            target = reward
            #print('brfe if')
            if not done:
                #print('in if before target')
                target = reward + self.gamma * np.amax(self.model.predict(np.reshape(next_state,(next_state.shape[0],next_state.shape[1],1)))[0])
            #print('out if after target')
            target_f = self.model.predict(np.reshape(state,(state.shape[0],state.shape[1],1)))
            target_f[0][action] = target
            self.model.fit(np.reshape(state,(state.shape[0],state.shape[1],1)), target_f, epochs=1, verbose=0)
            #print('after if')
            if self.epsilon > self.epsilon_min:
                self.epsilon *= self.epsilon_decay


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

from bs4 import BeautifulSoup as bs
import os
import re
import time
import copy
from db_func import DBConnect

class HtmlParser(object):
    def __init__(self, files_path):
        self.html_path = files_path
        self.node_temp = dict(id = '', name='', url='', childrens=[])
        self.leaf_node_temp = dict(id = '', name='', url='')
        self.node_list = []
        self.dbc_obj = DBConnect('temp_data.db')
        self.create_node_table()
        self.insert_sqls = []

    def create_node_table(self):
        table_is_exists_sql = '''
        select * from sqlite_master where type = 'table' and name = '{0}'
        '''.format('tree_node')
        drop_table_sql = '''
        drop table {0}
        '''.format('tree_node')
        if self.dbc_obj.execute_sqls(table_is_exists_sql):
            self.dbc_obj.execute_sqls(drop_table_sql)
        create_sql = '''
        create table if not exists {0}
        (id int, pId int, name varchar(255), url varchar(255), sum_num int, del_num int)
        '''.format('tree_node')
        self.dbc_obj.execute_sqls(create_sql)

    def insert_node(self, node_id, pid, name, url):
        pattern = re.compile(r'(.*)\[(\d+)/(\d+)\]$')
        flag = pattern.search(name)
        if flag:
            name = flag.group(1).strip()
            sum_num = flag.group(2)
            del_num = flag.group(3)
        else:
            sum_num = None
            del_num = None
        insert_sql = '''
        insert into {0} (id, pId, name, url, sum_num, del_num) values ('{1}', '{2}', '{3}', '{4}', '{5}', '{6}')
        '''.format('tree_node', node_id, pid, name, url, sum_num, del_num)
        self.insert_sqls.append(insert_sql)

    def catalog_parser(self):
        with open(os.path.join(self.html_path, 'Report', 'catalog.html')) as f:
            data_list = f.readlines()
            pattern = re.compile(r'{.*}')
            dict_temp = dict(id='', pId='', name='', url='')
            for data in data_list:
                if pattern.match(data):
                    dict_act = copy.deepcopy(dict_temp)
                    dict_act['id'] = re.findall(r"id:'*(.*?)'*,", data)[0]
                    dict_act['pId'] = re.findall(r"pId:'*(.*?)'*,", data)[0]
                    dict_act['name'] = re.findall(r"name:'*(.*?)'*,", data)[0]
                    dict_act['url'] = re.findall(r"url:'*(.*?)'*,", data)[0]
                    self.node_list.append(dict_act)
                    self.insert_node(dict_act['id'], dict_act['pId'], dict_act['name'], dict_act['url'])
            self.dbc_obj.execute_sqls(self.insert_sqls)

    def case_report_parser(self, html_name):
        with open(os.path.join(self.html_path, 'Report', html_name), 'r') as f:
            html_data = f.read()
        dict_list = []
        soup = bs(html_data, 'html.parser')
        tr_tag_list_dou = [tag.select('tr') for tag in soup.select('div#content > table > tbody')]
        for tr_tag_list in tr_tag_list_dou:
            dict_temp = {}
            for tr_tag in tr_tag_list:
                td_tag_list = tr_tag.select('td')
                dict_temp[td_tag_list[0].get_text().strip()] = td_tag_list[1].get_text().strip()
            dict_list.append(copy.deepcopy(dict_temp))
        return dict_list

    def common_html_parser(self, html_name):
        with open(os.path.join(self.html_path, 'Report', html_name), 'r') as f:
            html_data = f.read()
        soup = bs(html_data, 'lxml')
        info_dict = dict(name='', total_num=0, del_num=0, datas=[])
        span_tag_texts = [x.get_text().strip(' |(|)') for x in soup.select('span.s14')]
        info_dict['name'] = span_tag_texts[0]
        info_dict['total_num'] = int(span_tag_texts[1])
        # thead_th_texts = [x.get_text().strip() for x in soup.select('div#content > table > thead th')]
        tbody_tr_tags = soup.select('div#content > table > tbody tr')
        for tr_tag in tbody_tr_tags:
            td_tag_texts = []
            for tag in tr_tag.select('td'):
                if tag.select('img'):
                    img_src = tag.select('img')[0].attrs['src']
                    td_tag_texts.append(img_src)
                    if 'deleted.png' in img_src:
                        info_dict['del_num'] += 1
                else:
                    td_tag_texts.append(tag.get_text().replace(u'\xa0', u' ').strip())
            # info_dict['datas'].append(dict(zip(thead_th_texts, td_tag_texts)))
            info_dict['datas'].append(td_tag_texts)
        # try:
        #     assert len(info_dict['datas']) == info_dict['total_num'],  u'标题数据显示的条数与实际条数不同'
        # except AssertionError:
        #     return []
        return info_dict

if __name__ == '__main__':
    file_path = r'E:\testdata\Xiaomi_Redmi 4A_20190130140611401.20190314094738-html'
    htmlp = HtmlParser(file_path)
    htmlp.catalog_parser()


from django.test import TestCase
from django.urls import reverse

from rest_framework import status

from Dormroom.models import Dormroom
from SIFUser.mixins import AuthTestMixin
from StudentVillage.models import StudentVillage
from Washlist.jobs import reset_washlists
from Washlist.models.Templates import TemplateListItem, TemplateWashList
from Washlist.models.WashLists import ListItem
from Washlist.serializer import TemplateWashListSerializer

class WashListTemplateTest(TestCase):
    room = None

    def setUp(self):
        village = StudentVillage.objects.create(name="Moholt")
        self.room = Dormroom.objects.create(number=1, village=village)

        temp_list = TemplateWashList.objects.create(title="Moholt")
        village.templateWashList = temp_list
        village.save()

    def test_add_to_template_adds_to_each_list(self):
        desc = "Vask badet"
        temp_list = TemplateWashList.objects.get(title="Moholt")

        TemplateListItem.objects.create(description=desc, washlist=temp_list).save()
        self.assertEqual(desc, ListItem.objects.get(dormroom=self.room).description)

class WeeklyResetOfWashlistsTest(TestCase):
    def setUp(self):
        """
        Create a Washlist item that is completed
        the method also sets up a village and a room to relate the Washlist item to
        satisfy the db constraints
        """

        village = StudentVillage.objects.create(name="Moholt")
        self.room = Dormroom.objects.create(number=1, village=village)

        temp_list = TemplateWashList.objects.create(title="Moholt")
        village.templateWashList = temp_list
        village.save()

        self.item = ListItem.objects.create(
            pk=1, dormroom=self.room, desc="Vask badet", completed=True
        )
        self.item.save()

    def test_job_resets_items(self):
        """
        Test that job to reset Washlist items when run manually actually rests the databases
        Washlist items
        """
        reset_washlists()
        self.assertEqual(False, ListItem.objects.get(pk=1).completed)

class WashlistTemplateAPITest(AuthTestMixin):
    def setUp(self):
        super().setUp()
        self.temp_list = TemplateWashList.objects.create(title="Moholt")
        village = StudentVillage.objects.create(
            name="Moholt", templateWashList=self.temp_list
        )
        self.room = Dormroom.objects.create(number=1, village=village)
        self.item = ListItem.objects.create(
            pk=1, dormroom=self.room, desc="Vask badet", completed=True
        )

    def test_get_template_list(self):
        url = reverse("templatewashlist-list")
        response = self.client.get(url, HTTP_AUTHORIZATION=self.auth)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(
            response.data[0],
            TemplateWashListSerializer(
                TemplateWashList.objects.get(title="Moholt")
            ).data,
        )

    def test_get_detail_template_list(self):
        url = reverse("templatewashlist-detail", args=[1])
        response = self.client.get(url, HTTP_AUTHORIZATION=self.auth)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(
            response.data,
            TemplateWashListSerializer(
                TemplateWashList.objects.get(title="Moholt")
            ).data,
        )

    def test_add_template_washlist(self):
        url = reverse("templatewashlist-list")
        response = self.client.post(
            url, {"title": "Tyholt", "village": 1}, HTTP_AUTHORIZATION=self.auth
        )

        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(
            response.data,
            TemplateWashListSerializer(
                TemplateWashList.objects.get(title="Tyholt")
            ).data,
        )

    def test_partial_update(self):
        url = reverse("templatewashlist-detail", args=[1])
        response = self.client.patch(
            url, {"title": "Berg"}, HTTP_AUTHORIZATION=self.auth
        )

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(
            response.data,
            TemplateWashListSerializer(TemplateWashList.objects.get(title="Berg")).data,
        )

    def test_destroy(self):
        url = reverse("templatewashlist-detail", args=[1])
        response = self.client.delete(url, HTTP_AUTHORIZATION=self.auth)

        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
        self.assertEqual(TemplateWashList.objects.count(), 0)


# -*- coding: utf-8 -*-
"""
unitcalc - Create template python app.
"""

from setuptools import find_packages
from setuptools import setup

dependencies = ["python-levenshtein"]
version = 0.01

setup(
    name="unitcalc",
    version=version,
    url="https://github.com/jakeogh/unitcalc",
    license="PUBLIC DOMAIN",
    author="jakeogh",
    author_email="github.com@v6y.net",
    description="Replace text in files(s) or stdin.",
    long_description=__doc__,
    packages=find_packages(exclude=["tests"]),
    package_data={"unitcalc": ["py.typed"]},
    include_package_data=True,
    zip_safe=False,
    platforms="any",
    install_requires=dependencies,
    entry_points={
        "console_scripts": [
            "unitcalc = unitcalc.cli:cli",
        ],
    },
    classifiers=[
        # 'Development Status :: 1 - Planning',
        # 'Development Status :: 2 - Pre-Alpha',
        # 'Development Status :: 3 - Alpha',
        "Development Status :: 4 - Beta",
        # 'Development Status :: 5 - Production/Stable',
        # 'Development Status :: 6 - Mature',
        # 'Development Status :: 7 - Inactive',
        "Environment :: Console",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: BSD License",
        "Operating System :: POSIX",
        "Operating System :: MacOS",
        "Operating System :: Unix",
        "Operating System :: Windows",
        "Programming Language :: Python",
        "Programming Language :: Python :: 3",
        "Topic :: Software Development :: Libraries :: Python Modules",
    ],
)


import sys
import datetime
import os
from docx import Document

def main():

    start, end, days, doc_name = schedule_info()

    # Make date list

    dates = date_list(start, end, days)

    print('dates are ')
    print(dates)

    make_word(dates, doc_name)

    os.system( 'open ' + doc_name)

def date_list(start, end, days):

    # Make list of Strings of American format dates.
    # Assumes that days is a list of the numerical weekdays in sorted order.
    # e.g for MW days = [0, 2]

    # date.weekday()  Monday = 0, Tues = 1, Weds = 3 ....

    # TODO (does it?) assumes start and end are on the day of week as days in days string.  Should fix.

    include_weekday = len(days) > 1

    delta = datetime.timedelta(days=1)

    counter_date = start

    date_list = []

    while counter_date <= end:

        print('loop ', counter_date)

        # is this date one for the schedule?
        if counter_date.weekday() in days:
            date_list.append(date_format(counter_date, include_weekday))

        # Add 1 to counter_date
        counter_date += delta

    return date_list

def make_word(dates, filename):

    document = Document()

    table = document.add_table(rows=1, cols = 4)

    # TODO can create border for table?

    # Create header
    # This is really cool
    # https://python-docx.readthedocs.io/en/latest/

    hdr_cells = table.rows[0].cells
    hdr_cells[0].text = 'Session'
    hdr_cells[1].text = 'Date'
    hdr_cells[2].text = 'Topics'
    hdr_cells[3].text = 'Assignments'

    counter = 1

    for d in dates:

        row_cells = table.add_row().cells
        row_cells[0].text = str(counter)
        row_cells[1].text = d

        counter += 1

    document.save(filename)

def date_format(d, include_weekday):
    # Return string for schedule. e.g. "Mon May 4 2017"
    # or "May 4 2017"

    if (include_weekday):
        return d.strftime('%a, %b %d %Y')
    else :
        return d.strftime('%b %d %Y')

def schedule_info():

    args = sys.argv
    if len(args) is 5:

        start = args[1]
        end = args[2]
        weekly = args[3]
        doc_name = args[4]

    else :

        print('Need more data.')
        start = input('Enter start date as DD-MM-YYYY: ')
        end = input('Enter end date as DD-MM-YYYY: ')
        weekly = input('Enter days of week to generate e.g. M or TW or MTH:')
        doc_name = input('Enter document name')

    # Validate. TODO replace with loop.

    start_date = ensure_date(start)
    end_date = ensure_date(end)
    days = ensure_days(weekly)
    docname = ensure_valid_filename(doc_name)

    print('Your args are ', start_date, end_date, days, docname)

    return start_date, end_date, days, doc_name

def ensure_valid_filename(name):

    #does it ends with docx (or append docx)

    if name.endswith('doc'):
        return name + 'x'

    if name.endswith('docx'):
        return name

    return name + 'docx'

    # TODO check if valid filename, does file exist?

def ensure_days(weekly):

    weekly = weekly.upper()

    map

    valid = 'MTWTF'

    for d in weekly:
        if d not in valid:
            return None

    weekdays = weekly.replace('M', '0')
    weekdays = weekdays.replace('T', '1')
    weekdays = weekdays.replace('W', '2')
    weekdays = weekdays.replace('T', '3')
    weekdays = weekdays.replace('F', '4')

    weekdays_int = [ int(day) for day in weekdays ]
    weekdays_int.sort()   # That makes sorting easier :)

    print(weekdays_int)

    return weekdays_int

def ensure_date(date_string):

    try:
        dmy = date_string.split('-')
        assert len(dmy) is 3
        dmy = [ int(item) for item in dmy ]

        if dmy[2] < 99:
            dmy[2] += 2000  # This is how millenium bugs happen

        date = datetime.date(dmy[2], dmy[1], dmy[0])
        return date
    except:
        return None

if __name__ == '__main__':
    main()


import json
import re
from enum import Enum
from pathlib import Path
from typing import List
from typing import Pattern

from replayresizer.tools import color16_to_colour, colour_to_color16

def parse_int(value: str):
    try:
        return int(value)
    except ValueError:
        return 0

class CloseAction(Enum):
    CLOSE = 0
    CLOSE_AND_DELETE_SOURCE = 1
    CLOSE_AND_DELETE_RESIZE = 2
    CLOSE_AND_DELETE_ALL = 3

class AutoActionWhen(Enum):
    ON_COMPLETED = 0
    ON_DRAGGED = 1

class AppConfiguration(object):
    def __init__(self, path: Path):
        self._path = path
        # shadow
        self.setup = True
        self.first_start = True
        self.pause = False
        self.rename_format = "{name}_resized.{ext}"
        # generic
        self.input_directory = ""
        self.output_directory = ""
        self.ffmpeg_command = "ffmpeg"
        self.ffprobe_command = "ffprobe"
        self.listen_delay = 0
        self.color = 0x592e31
        self.thumbnail = True
        self.draw_media_info = False
        self.silent_popup = False
        self.ignore_error = False
        self.close_action = 2
        self.close_action_with_shift = 0
        self.auto_close_delay = 5
        self.auto_close_when = 0
        # encode
        self.size_limit = 8170
        self.hq_bitrate = 1200
        self.ulq_bitrate = 260
        self.normalized_volume = True
        self.volume_db = 2.0
        self.volume_normalize_limit_db = 20.0
        #   HQ
        self.hq_fps30 = True
        self.hq_no_audio = False
        self.hq_width = 1280
        self.hq_height = 0
        self.hq_size_adjust = 100.0
        self.hq_encoder_params = "-deadline realtime -cpu-used -8"
        #   LQ
        self.lq_fps30 = True
        self.lq_no_audio = False
        self.lq_width = 640
        self.lq_height = 0
        self.lq_size_adjust = 96.0
        self.lq_encoder_params = "-preset veryfast"
        #   ULQ
        self.ulq_fps16 = True
        self.ulq_no_audio = False
        self.ulq_width = 320
        self.ulq_height = 0
        self.ulq_size_adjust = 96.0
        self.ulq_encoder_params = "-preset veryfast"
        # target files
        self.targets = ["1:\\.mp4$"]
        self.ignores = ["1:^\\."]

        # cached
        self._active_targets = []  # type: List[Pattern]
        self._active_ignores = []  # type: List[Pattern]
        self.compile_targets()

    def load_from_panel(self, panel):
        """
        :type panel: replayresizer.settings_panel.SettingsFrame
        """
        self.input_directory = str(panel.tc_dir_input.GetValue())
        self.output_directory = str(panel.tc_dir_output.GetValue())
        self.ffmpeg_command = str(panel.tc_ffmpeg.GetValue())
        self.ffprobe_command = str(panel.tc_ffprobe.GetValue())
        self.listen_delay = int(panel.spin_listen_delay.GetValue())
        self.color = colour_to_color16(panel.btn_my_color.GetColour())
        self.thumbnail = bool(panel.check_thumbnail.GetValue())
        self.draw_media_info = bool(panel.check_draw_media_info.GetValue())
        self.silent_popup = bool(panel.check_silent_popup.GetValue())
        self.ignore_error = bool(panel.check_ignore_error.GetValue())
        self.close_action = int(panel.choice_close_action.GetSelection())
        self.close_action_with_shift = int(panel.choice_close_action_with_shift.GetSelection())
        self.auto_close_delay = int(panel.spin_auto_close_delay.GetValue())
        self.auto_close_when = int(panel.choice_auto_close_when.GetSelection())
        self.size_limit = int(panel.spin_size_limit.GetValue())
        self.hq_fps30 = bool(panel.check_hq_fps30.GetValue())
        self.hq_no_audio = bool(panel.check_hq_no_audio.GetValue())
        self.hq_width = parse_int(panel.tc_hq_scale_width.GetValue())
        self.hq_height = parse_int(panel.tc_hq_scale_height.GetValue())
        self.hq_size_adjust = float(panel.spin_hq_size_adjust.GetValue())
        self.hq_encoder_params = str(panel.tc_hq_encoder_params.GetValue())
        self.lq_fps30 = bool(panel.check_lq_fps30.GetValue())
        self.lq_no_audio = bool(panel.check_lq_no_audio.GetValue())
        self.lq_width = parse_int(panel.tc_lq_scale_width.GetValue())
        self.lq_height = parse_int(panel.tc_lq_scale_height.GetValue())
        self.lq_size_adjust = float(panel.spin_lq_size_adjust.GetValue())
        self.lq_encoder_params = str(panel.tc_lq_encoder_params.GetValue())
        self.ulq_fps16 = bool(panel.check_ulq_fps16.GetValue())
        self.ulq_no_audio = bool(panel.check_ulq_no_audio.GetValue())
        self.ulq_width = parse_int(panel.tc_ulq_scale_width.GetValue())
        self.ulq_height = parse_int(panel.tc_ulq_scale_height.GetValue())
        self.ulq_size_adjust = float(panel.spin_ulq_size_adjust.GetValue())
        self.ulq_encoder_params = str(panel.tc_ulq_encoder_params.GetValue())
        self.hq_bitrate = parse_int(panel.tc_hq_bitrate.GetValue()) or 1200
        self.ulq_bitrate = parse_int(panel.tc_ulq_bitrate.GetValue()) or 260
        self.normalized_volume = bool(panel.check_normalized_volume.GetValue())
        self.volume_db = float(panel.spin_volume_db.GetValue())
        self.volume_normalize_limit_db = float(panel.spin_volume_normalize_limit_db.GetValue())
        self.targets = [f"{int(panel.list_target.IsChecked(idx))}:{entry}"
                        for idx, entry in enumerate(panel.list_target.GetItems())]
        self.ignores = [f"{int(panel.list_ignore.IsChecked(idx))}:{entry}"
                        for idx, entry in enumerate(panel.list_ignore.GetItems())]
        self.compile_targets()

    def load_to_panel(self, panel):
        """
        :type panel: replayresizer.settings_panel.SettingsFrame
        """
        panel.tc_dir_input.SetValue(str(self.input_directory or ""))
        panel.tc_dir_output.SetValue(str(self.output_directory or ""))
        panel.tc_ffmpeg.SetValue(str(self.ffmpeg_command or ""))
        panel.tc_ffprobe.SetValue(str(self.ffprobe_command or ""))
        panel.spin_listen_delay.SetValue(max(0, int(self.listen_delay or 0)))
        panel.btn_my_color.SetColour(color16_to_colour(int(self.color or 0)))
        panel.check_thumbnail.SetValue(bool(self.thumbnail or False))
        panel.check_draw_media_info.SetValue(bool(self.draw_media_info or False))
        panel.check_silent_popup.SetValue(bool(self.silent_popup or False))
        panel.check_ignore_error.SetValue(bool(self.ignore_error or False))
        panel.choice_close_action.Select(max(0, min(4, int(self.close_action or 0))))
        panel.choice_close_action_with_shift.Select(max(0, min(4, int(self.close_action_with_shift or 0))))
        panel.spin_auto_close_delay.SetValue(max(0, int(self.auto_close_delay or 0)))
        panel.choice_auto_close_when.Select(max(0, min(1, int(self.auto_close_when or 0))))
        panel.spin_size_limit.SetValue(max(200, min(99999999, int(self.size_limit or 0))))
        panel.check_hq_fps30.SetValue(bool(self.hq_fps30 or False))
        panel.check_hq_no_audio.SetValue(bool(self.hq_no_audio or False))
        panel.tc_hq_scale_width.SetValue(str(max(0, int(self.hq_width or 0))))
        panel.tc_hq_scale_height.SetValue(str(max(0, int(self.hq_height or 0))))
        panel.spin_hq_size_adjust.SetValue(float(self.hq_size_adjust or 0))
        panel.tc_hq_encoder_params.SetValue(str(self.hq_encoder_params or ""))
        panel.check_lq_fps30.SetValue(bool(self.lq_fps30 or False))
        panel.check_lq_no_audio.SetValue(bool(self.lq_no_audio or False))
        panel.tc_lq_scale_width.SetValue(str(max(0, int(self.lq_width or 0))))
        panel.tc_lq_scale_height.SetValue(str(max(0, int(self.lq_height or 0))))
        panel.spin_lq_size_adjust.SetValue(float(self.lq_size_adjust or 0))
        panel.tc_lq_encoder_params.SetValue(str(self.lq_encoder_params or ""))
        panel.check_ulq_fps16.SetValue(bool(self.ulq_fps16 or False))
        panel.check_ulq_no_audio.SetValue(bool(self.ulq_no_audio or False))
        panel.tc_ulq_scale_width.SetValue(str(max(0, int(self.ulq_width or 0))))
        panel.tc_ulq_scale_height.SetValue(str(max(0, int(self.ulq_height or 0))))
        panel.spin_ulq_size_adjust.SetValue(float(self.ulq_size_adjust or 0))
        panel.tc_ulq_encoder_params.SetValue(str(self.ulq_encoder_params or ""))
        panel.tc_hq_bitrate.SetValue(str(int(self.hq_bitrate or 1200)))
        panel.tc_ulq_bitrate.SetValue(str(int(self.ulq_bitrate or 260)))
        panel.check_normalized_volume.SetValue(bool(self.normalized_volume or False))
        panel.spin_volume_db.SetValue(float(self.volume_db or 0))
        panel.spin_volume_normalize_limit_db.SetValue(float(self.volume_normalize_limit_db or 0))
        panel.tc_target_value.SetValue("")
        panel.list_target.Clear()
        for entry in self.targets:
            index = panel.list_target.Append(entry[2:])
            if entry.startswith("1:"):
                panel.list_target.Check(index)
        panel.tc_ignore_value.SetValue("")
        panel.list_ignore.Clear()
        for entry in self.ignores:
            index = panel.list_ignore.Append(entry[2:])
            if entry.startswith("1:"):
                panel.list_ignore.Check(index)

    def load_from_json_file(self, *, save_default=True):
        if not self._path.is_file():
            if save_default:
                self.save_to_json_file()
            return

        with self._path.open(encoding="utf-8") as file:
            data = json.load(file)

        for key, value in self.__dict__.items():
            if key.startswith("_") or key not in data:
                continue

            setattr(self, key, data.get(key))

    def save_to_json_file(self):
        Path(self._path.parent).mkdir(parents=True, exist_ok=True)

        if self._path.exists():
            with self._path.open(encoding="utf-8") as file:
                data = json.load(file)
        else:
            data = {}

        for key, value in self.__dict__.items():
            if key.startswith("_"):
                continue

            data[key] = value

        with self._path.open("w", encoding="utf-8") as file:
            json.dump(data, file, ensure_ascii=False, indent=2)

    @property
    def active_targets(self) -> List[Pattern]:
        return self._active_targets

    @property
    def active_ignores(self) -> List[Pattern]:
        return self._active_ignores

    @property
    def close_action_enum(self):
        try:
            return CloseAction(self.close_action)
        except ValueError:
            return CloseAction.CLOSE

    @property
    def close_action_shift_enum(self):
        try:
            return CloseAction(self.close_action_with_shift)
        except ValueError:
            return CloseAction.CLOSE

    @property
    def auto_close_when_enum(self):
        try:
            return AutoActionWhen(self.auto_close_when)
        except ValueError:
            return AutoActionWhen.ON_COMPLETED

    #

    def compile_targets(self):
        self._active_targets = [re.compile(entry[2:]) for entry in self.targets if entry.startswith("1:")]
        self._active_ignores = [re.compile(entry[2:]) for entry in self.ignores if entry.startswith("1:")]