from __future__ import print_function
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gfgp_db.settings")
django.setup()
import sys
from users.models import User, Organisation
from faker import Faker
import random
import time

fake = Faker()
fake.seed_instance(1)

def seed_organisations(num_entries=10, overwrite=True):

    if overwrite:
        print("Overwriting fake organisations")
        Organisation.objects.all().delete()

    count = 0
    for _ in range(num_entries):
        legalname = fake.company()
        address = fake.address()
        city = fake.city()
        size_index = fake.random_int(min=0, max=3)
        expenditure_index = fake.random_int(min=0, max=3)

        org = Organisation.objects.create(
            legal_name=legalname,
            address_1=address,
            city=city,
            size=Organisation.SIZE[size_index][0],
            annual_expenditure=Organisation.ANNUAL_EXPENDITURE[expenditure_index][0]
        )
        org.save()
        count += 1
        percentage_complete = count / num_entries * 100

        print("Adding {} new organisations: {:.2f}%".format(num_entries, percentage_complete), end='\r')
        sys.stdout.flush()

    print()

def seed_users(num_entries=10, overwrite=True):

    if overwrite:
        print("Overwriting fake users")
        User.objects.all().delete()

    count = 0
    for _ in range(num_entries):
        name = fake.name()
        usermobile = fake.phone_number()
        jobrole = fake.company_suffix()
        org = list(Organisation.objects.all())

        u = User.objects.create(
            name=name,
            user_mobile=usermobile,
            job_role=jobrole,
            organisation=random.choice(org)
        )
        u.save()
        count += 1
        percentage_complete = count / num_entries * 100

        print("Adding {} new Users: {:.2f}%".format(num_entries, percentage_complete), end='\r')
        sys.stdout.flush()

    print()

def seed_all():

    start_time = time.time()
    seed_organisations(num_entries=10, overwrite=True)
    seed_users(num_entries=20, overwrite=False)

    elapsed_time = time.time() - start_time
    minutes = int(elapsed_time // 60)
    seconds = int(elapsed_time % 60)
    print("Script Execution took: {} minutes {} seconds".format(minutes, seconds))

seed_all()
print('Data populated successfully')


"""
    给出集合 [1,2,3,…,n]，其所有元素共有 n! 种排列。
    按大小顺序列出所有排列情况，并一一标记，当 n = 3 时, 所有排列如下：
        "123"
        "132"
        "213"
        "231"
        "312"
        "321"
    给定 n 和 k，返回第 k 个排列。
    说明：
        给定 n 的范围是 [1, 9]。
        给定 k 的范围是[1,  n!]。

    示例 1:
        输入: n = 3, k = 3
        输出: "213"
    示例 2:
        输入: n = 4, k = 9
        输出: "2314"
"""
import math

class Solution:
    def getPermutation(self, n: int, k: int) -> str:
        pass

    @classmethod
    def solve_1(cls, n: int, k: int):
        info = [str(i) for i in range(1, n + 1)]
        res = ""
        k = k - 1

        while n > 0:
            n -= 1
            a, k = divmod(k, math.factorial(n))
            res += info.pop(a)
        return res

    @classmethod
    def solve_2(cls, n: int, k: int):
        """
            参考 https://leetcode-cn.com/problems/permutation-sequence/solution/hui-su-jian-zhi-python-dai-ma-java-dai-ma-by-liwei/
        """

        def dfs(k_, index):
            if index == n:
                return
            cnt = factorial[n - index - 1]
            for i in range(1, n + 1):
                if used[i]:
                    continue
                if cnt < k_:
                    k_ -= cnt
                    continue
                res.append(i)
                used[i] = True
                dfs(k_, index + 1)

        factorial = [1 for i in range(n + 1)]
        for i in range(2, n + 1):
            factorial[i] = factorial[i - 1] * i

        used = [False for i in range(n + 1)]

        res = []

        dfs(k, 0)

        return "".join(map(str, res))


#!/usr/bin/env python3
import os
import sys
import web3
from web3 import Web3
import json
import requests

# Change these values to your values....
ESCROW = '0xC24F371c8656A06844207B312879b44053b55Ee9'
RANSOM = '0x435Eadd7743AcF8504d3AC141129350555C6b78b'
VICTIM_ID = '0xeb56d54d25c88a14edcb8ccf0190a3aa056086308b62cd5e141c136fc13d4aa0'
REGISTRY = ''
URL = 'https://codebreaker.ltsnet.net/eth/3a6f3a9ea2b9e53d/8e49a73b727d217fe13f45f70d8a8eaa71d9ae89f16b5b5158660260b9bfcc4e'

def connect_to_web3(url=None):
    if url is None: url = os.environ['URL']
    return Web3(Web3.HTTPProvider(url))

def increase_value_by(value, by):
    if len(value) == 32:
        hex_value = value.hex()
    else:
        hex_value = value

    int_value = int(hex_value, 16)

    if type(by) == int:
        int_by = by
    else:
        if len(by) == 32:
            hex_by = by.hex()
        else:
            hex_by = by
        int_by = int(hex_by, 16)

    hex_result = "%064x" % (int_value + int_by)
    return bytes.fromhex(hex_result)

def main(argv):

    # Connect to web3
    w3 = connect_to_web3(URL)
    escrow = w3.eth.contract(ESCROW)
    ransom = w3.eth.contract(RANSOM)
    # Accessing escrow, from Escrow.sol
    """
        Storage NAME                            Storage Number
        -------------------------------------------------------
        address owner;                          // 0
        uint ownerBalance;                      // 1
        address registry;                       // 2
        mapping(uint => address) vicToPayerMap; // 3
        mapping(uint => Victim) victimMap;      // 4
        mapping(uint => bytes32) decKeyMap;     // 5
        mapping(address => uint) ransomMap;     // 6
        mapping(uint => uint) escrowMap;        // 7
        mapping(uint => string) encFileMap;     // 8
        address[] ransomContracts;              // 9
        address oracleAccount;                  // 10
    """

    # Accessing each variables. Use getStorageAt(address, storage_number)

    # owner is at 0
    escrow_owner = w3.eth.getStorageAt(ESCROW, 0)
    print('Escrow owner: ' + escrow_owner.hex())

    # owner balance is at 1
    escrow_owner_balance = w3.eth.getStorageAt(ESCROW, 1)
    print('Escrow ownerBalance: ' + escrow_owner_balance.hex())

    # accessing array, ransomContracts at 9
    # accessing 9 returns the length
    escrow_ransom_array_length = w3.eth.getStorageAt(ESCROW, 9)
    print("Escrow ransomContracts length: " + escrow_ransom_array_length.hex())

    # store the length of array
    array_length = int(escrow_ransom_array_length.hex(), 16)

    # Accessing array element
    # 1) we need to get the index sum from the array.
    #    that is, sha3 of the index.
    #    so for the array at position 9, we need to get a sum for
    # i ='0000000000000000000000000000000000000000000000000000000000000009'
    #    '0' * 63 + '9'.
    #    and then we will calculate
    #    index_sum = w3.sha3(i)
    # 2) add array index to that sum.
    #    index_sum is a 256bit integer, and we will add the element index
    #    of the array to access it via getStorageAt().
    #    To do this, we will use increase_value_by(sum, idx) function.
    #    In other words, increase_value_by(a, b) will add b to a.
    # See: https://medium.com/aigang-network/how-to-read-ethereum-contract-storage-44252c8af925

    # create an hexadecimal index for the ransomContracts, 9,
    # justified with 63 zeros (make it to be a 64 digit hex integer)
    index = bytes.fromhex("%064x" % 9)
    index_sum = w3.sha3(index)

    for i in range(array_length):
        array_idx_i = increase_value_by(index_sum, i)
        array_elem_i = w3.eth.getStorageAt(ESCROW, array_idx_i)
        print('IDX  %d: ' % i + array_idx_i.hex())
        print('ELEM %d: ' % i + array_elem_i.hex())

    # Map access. Let's access ransomMap at 6 using the ransom address that we have...
    # ransomMap[RANSOM_ADDRESS] = victim_id
    # To do this, we need to do:
    # 1) create index by concatenating key + storage index.
    #  e.g., [64 digit hexadecimal RANSOM_ADDRESS][64 digit storage index, 6]
    # We can do this as follows.
    # index = "%064x" % int(RANSOM.lower(), 16) + "%064x" % 6
    #         ^ 64 digit ransom address in hex    ^ 64 digit storage index in hex
    # 2) Change that into bytestream and apply sha3
    # ransom_addr_sum = w3.sha3(bytes.fromhex(index))
    # 3) access with that sum
    # w3.eth.getStorageAt(ESCROW, ransom_addr_sum)
    # See: https://medium.com/coinmonks/a-practical-walkthrough-smart-contract-storage-d3383360ea1b
    map_index = bytes.fromhex("%064x" % 6)
    # Translate RANSOM address to 256bit hex
    ransom_hex = "%064x" % int(RANSOM.lower(), 16)
    ransom_addr_index = bytes.fromhex(ransom_hex) + map_index
    print(ransom_addr_index.hex())
    ransom_addr_sum = w3.sha3(ransom_addr_index)
    print(ransom_addr_sum.hex())
    ransom_map_result = w3.eth.getStorageAt(ESCROW, ransom_addr_sum)
    # this must be the same as your victim ID
    print("Escrow ransomMap[VICTIM_ID]: " + ransom_map_result.hex())

def load_contract(w3, json_path):
    with open(json_path) as fobj:
        info = json.load(fobj)
        return w3.eth.contract(abi=info['abi'], bytecode=info['bytecode'])

##################################

if __name__ == '__main__':
    sys.exit(main(sys.argv))


MAX = 1000;

def replaceSpaces(string):

	string = string.strip()

	i = len(string)

	space_count = string.count(' ')

	new_length = i + space_count * 2

	if new_length > MAX:
		return -1
	index = new_length - 1

	string = list(string)

	for f in range(i - 2, new_length - 2):
		string.append('0')

	for j in range(i - 1, 0, -1):

		if string[j] == ' ':
			string[index] = '0'
			string[index - 1] = '2'
			string[index - 2] = '%'
			index = index - 3
		else:
			string[index] = string[j]
			index -= 1

	return ''.join(string)

if __name__ == '__main__':
	s = "Mr John Smith "
	s = replaceSpaces(s)
	print(s)


import numpy as np
import torch
#code sourse(euclidean_proj_simplex):https://github.com/icdm-extract/extract/blob/18d6e8509f2f35719535e1de6c88874ec533cfb9/python/algo/l1project.py
def euclidean_proj_simplex(v, s=1):
    """ Compute the Euclidean projection on a positive simplex
    Solves the optimisation problem (using the algorithm from [1]):
        min_w 0.5 * || w - v ||_2^2 , s.t. \sum_i w_i = s, w_i >= 0
    Parameters
    ----------
    v: (n,) numpy array,
       n-dimensional vector to project
    s: int, optional, default: 1,
       radius of the simplex
    Returns
    -------
    w: (n,) numpy array,
       Euclidean projection of v on the simplex
    Notes
    -----
    The complexity of this algorithm is in O(n log(n)) as it involves sorting v.
    Better alternatives exist for high-dimensional sparse vectors (cf. [1])
    However, this implementation still easily scales to millions of dimensions.
    References
    ----------
    [1] Efficient Projections onto the .1-Ball for Learning in High Dimensions
        John Duchi, Shai Shalev-Shwartz, Yoram Singer, and Tushar Chandra.
        International Conference on Machine Learning (ICML 2008)
        http://www.cs.berkeley.edu/~jduchi/projects/DuchiSiShCh08.pdf
    """
    assert s > 0, "Radius s must be strictly positive (%d <= 0)" % s
    n, = v.shape  # will raise ValueError if v is not 1-D
    # check if we are already on the simplex
    if v.sum() == s and np.alltrue(v >= 0):
        # best projection: itself!
        return v
    # get the array of cumulative sums of a sorted (decreasing) copy of v
    u = np.sort(v)[::-1]
    cssv = np.cumsum(u)
    # get the number of > 0 components of the optimal solution
    rho = np.nonzero(u * np.arange(1, n+1) > (cssv - s))[0][-1]
    # compute the Lagrange multiplier associated to the simplex constraint
    theta = float(cssv[rho] - s) / rho
    # compute the projection by thresholding v using theta
    w = (v - theta).clip(min=0)
    return w

#code sourse(euclidean_proj_l1ball):https://github.com/icdm-extract/extract/blob/18d6e8509f2f35719535e1de6c88874ec533cfb9/python/algo/l1project.py
def euclidean_proj_l1ball(v, s=1):
    """ Compute the Euclidean projection on a L1-ball
    Solves the optimisation problem (using the algorithm from [1]):
        min_w 0.5 * || w - v ||_2^2 , s.t. || w ||_1 <= s
    Parameters
    ----------
    v: (n,) numpy array,
       n-dimensional vector to project
    s: int, optional, default: 1,
       radius of the L1-ball
    Returns
    -------
    w: (n,) numpy array,
       Euclidean projection of v on the L1-ball of radius s
    Notes
    -------
    Solves the problem by a reduction to the positive simplex case
    See also
    --------
    euclidean_proj_simplex
    """
    assert s > 0, "Radius s must be strictly positive (%d <= 0)" % s
    n, = v.shape  # will raise ValueError if v is not 1-D
    # compute the vector of absolute values
    u = np.abs(v)
    #print(u.sum())
    # check if v is already a solution
    if u.sum() <= s:
        # L1-norm is <= s
        return v
    # v is not already a solution: optimum lies on the boundary (norm == s)
    # project *u* on the simplex
    w = euclidean_proj_simplex(u, s=s)
    # compute the solution to the original problem on v
    w *= np.sign(v)
    return w

def euclidean_proj_simplex_l2ball(v, s=1):
    """
        compute the euclidean projection in L2-ball
        :param v: vector which needed to be projected
        :param s:radius of a unit ball
        :return w:vector after projection into L2-ball
    """
    n, = v.shape  # will raise ValueError if v is not 1-D
    u=np.power(v,2)
    if np.sqrt(u.sum()) == s and np.alltrue(u >= 0):# check if v is l2-ball itself
        return v
    w=np.min([1/np.linalg.norm(v),1])*v
    return w

def euclidean_proj_l2ball(v, s=1):
    """
        check date if in the l2-ball and return the euclidean projection in L2-ball
        :param v: vector which needed to be projected
        :param s:radius of a unit ball
        :return w:vector after projection into L2-ball
    """

    n, = v.shape
    u = v**2
    if np.sqrt(u.sum())  <= s:#check if is in the l2-norm ball
        return v
    w = euclidean_proj_simplex_l2ball(v, s=s)
    return w


from django.urls import path
from .views import Login, Logout, Signup, home, userdashboard ,dashboard, event_detail, event_create, event_update, event_delete, event_list, book_ticket
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
	path('', home, name='home'),
    path('signup/', Signup.as_view(), name='signup'),
    path('login/', Login.as_view(), name='login'),
    path('logout/', Logout.as_view(), name='logout'),
	path('dashboard/', dashboard, name='dashboard'),
	path('events/', event_list, name='event-list'),
    path('event/<int:event_id>/ticket', book_ticket, name='ticket'),
	path('userdashboard/', userdashboard, name='userdashboard'),

	#path('profile/<int:user_id>/', profile, name='profile'),
    path('event/<int:event_id>/', event_detail, name='event-detail'),
    path('event/create/', event_create, name='event-create'),
    path('event/<int:event_id>/update/', event_update, name='event-update'),
    path('event/<int:event_id>/delete/', event_delete, name='event-delete'),

]
if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)


#coding:utf-8
import json
from datetime import datetime

from django.http import HttpResponse, HttpResponseNotAllowed
from django.views.generic import View
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required

from extra.extension import customer_sql, CJsonEncoder, prev_month

today = datetime.now().strftime('%Y-%m-%d')
lastMonth = prev_month().strftime('%Y-%m-%d')

class Performance(View):

	@method_decorator(login_required())
	def get(self, request):
		start_at = request.GET.get('start_at', lastMonth)
		end_at = request.GET.get('end_at', today)
		company = request.GET.get('company', request.user.sub_company)
		clerk = request.GET.get('clerk', None)
		is_settle = request.GET.get('is_settle', None)
		company_sql =  is_settle_sql =  clerk_sql = '';
		if company and company !='drop':
			company_sql = "and sub_company = '{company}'".format(company=company)
		if clerk and clerk !='drop':
			clerk_sql = "and clerk='{clerk}'".format(clerk=clerk)
		if is_settle and is_settle !='drop':
			is_settle_sql = "and is_settle = {is_settle}".format(is_settle=is_settle)
		sql = '''
			SELECT
				sub_company,
				clerk,
				count(id) as number,
				FORMAT(sum(product_weight),2) as weight,
				FORMAT(sum(product_weight_bef),2) as gross_wt,
				FORMAT(sum(product_weight_fee),2) as charge_wt,
				FORMAT(sum(product_volumn),2) as volumn,
				sum(income) as incomes,
				sum(costs) as cost,
				FORMAT((sum(income) - sum(costs)),2) AS profit,
				FORMAT((sum(income)/sum(costs))*100,2) as profit_m
			FROM
				logistics_income_costs
			WHERE
				air_start_at >= '{start_at}' and air_start_at <= '{end_at}'  {company_sql}  {clerk_sql} {is_settle_sql}
 			GROUP BY
				clerk
			ORDER BY profit desc
		'''.format(start_at=start_at, end_at=end_at, company_sql=company_sql, clerk_sql=clerk_sql, is_settle_sql=is_settle_sql)
		res = customer_sql(sql)
		sdata = json.dumps({'data':res,'count':len(res), 'start_at':start_at, 'end_at':end_at}, cls=CJsonEncoder)
		return HttpResponse(sdata, content_type="application/json")

@login_required
def profit(request):
	start_at = request.GET.get('start_at', lastMonth)
	end_at = request.GET.get('end_at', today)
	clerk = request.GET.get('clerk')
	is_settle = request.GET.get('is_settle', None)
	settle_sql=""
	if is_settle != 'drop':
		settle_sql = "and is_settle={is_settle}".format(is_settle=is_settle)
	sql = '''
		select * from logistics_income_costs
		where clerk = '{clerk}'
			and air_start_at >='{start_at}'
			and air_start_at<='{end_at}'
			{settle_sql}
	'''.format(start_at=start_at,end_at=end_at,clerk=clerk,settle_sql=settle_sql)
	res = customer_sql(sql)
	sdata = json.dumps({ 'data':res, 'count':len(res)}, cls=CJsonEncoder)
	return HttpResponse(sdata, content_type="application/json")


"""
Program to search in NCPR Pril 4 list for MAHs whose declarations should be submitted during the current month
Result is printed on the screen and exported to an Excel with 2 sheets: Products and Debug

NB: Downloaded NCPR file should be manipulated. Expected file:
- name: pril4towork.xlsx (or change on row 34)
- type: xlsx
- columns:
  1 - INN
  2 - Name
  3 - MAH
  4 - Note
  5 - Date of decision
  6 - Effective date

For now:
- MAH should be manually changed in 'searched MAH' (row 35)
- month should be manually changed in "current month' else it is the month from today (row 48)
"""

import openpyxl
from openpyxl.styles import Font
from datetime import datetime

# define columns
col_inn = 1
col_name = 2
col_MAH = 3
col_note = 4
col_decdate = 5
col_effdate = 6

# define files and MAH to search
file_NCPR = "pril4towork.xlsx"
searchedMAH = "Бакстер"
searched_months = []

# open file and load current sheet
file = openpyxl.load_workbook(file_NCPR)
sheet = file.active

#
today = datetime.now()
today_string = str(today)
month_today = today_string.split("-")
curr_month = month_today[1]
current_month = int(curr_month)
# current_month = 9

# get total number of rows in the sheet
row_count = int(sheet.max_row)

total_error_messages = 0

# make a variable for total number of products
total_products = 0

# create a new Excel file with name MAH+current month and make two sheets in it
name_for_export = searchedMAH + str(current_month) + ".xlsx"
new_file = openpyxl.Workbook()
first_sheet = new_file.get_active_sheet()
first_sheet.title = "Products"
second_sheet = new_file.create_sheet(title="Debug", index=1)

# main body

print("Starting to search for MAH " + searchedMAH +
      " to be submitted to NCPR until the end of month " + str(current_month) + " ... \n")

# find and exclude strikethrough rows
font = Font(strikethrough=None)
for i in range (3, row_count):
    MAH = sheet.cell(row=i, column=col_MAH).value
    current_font = sheet.cell(row=i, column=col_MAH).font.strike
    date_string = sheet.cell(row=i, column=col_effdate).value

# check if "Date" cell is empty and print a message + export to the Debug sheet in the output file
    if date_string == None:
        # print("     Debugging: No date on row " + str(i) + " - MAH is " + MAH)
        curr_cell = second_sheet["A" + str(total_error_messages + 1)]
        message = "No date on row " + str(i) + " - MAH is " + MAH
        curr_cell.value = message
        total_error_messages += 1
        pass
    else:
        # check if "date" is not a string but an integer - if integer skip and print a message
        # + export to the Debug sheet in the output file
        try:
            date_string == int(date_string)
            # print("     Debugging: Check date format on row " + str(i) + " - MAH is " + MAH)
            curr_cell = second_sheet["A" + str(total_error_messages + 1)]
            message = "Check date format on row " + str(i) + " - MAH is " + MAH
            curr_cell.value = message
            total_error_messages += 1
        except ValueError: #so date IS a string
            date_for_search = date_string.replace(",",".").rstrip(" г.").split(".")
            month = int(date_for_search[1])
            # prepare to check for current month and 6 months before
            if current_month < 7:
                searched_months = [current_month, current_month + 6]
            else:
                searched_months = [current_month, current_month - 6]
            if searchedMAH in MAH and current_font != True and month in searched_months: #print only non-strikethrough MAH to be submitted
                print("MAH " + searchedMAH + " exists on row " + str(i) +
                      " - and the product is: " + sheet.cell(row=i, column=col_name).value)
                curr_cell = first_sheet["A" + str(total_products + 1)]
                message = "MAH " + searchedMAH + " exists on row " + str(i) + \
                          " - and the product is: " + sheet.cell(row=i, column=col_name).value
                curr_cell.value = message
                total_products +=1
print("Total products to prepare: " + str(total_products))
new_file.save(name_for_export)


"""
"""

import sys

try:
    from wheezy.html.utils import escape_html as escape
except ImportError:
    import cgi
    escape = cgi.escape

PY3 = sys.version_info[0] >= 3
s = PY3 and str or unicode

ctx = {
    'table': [dict(a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, i=9, j=10)
              for x in range(1000)]
}

# region: wheezy.template

try:
    from wheezy.template.engine import Engine
    from wheezy.template.loader import DictLoader
    from wheezy.template.ext.core import CoreExtension
except ImportError:
    test_wheezy_template = None
else:
    engine = Engine(loader=DictLoader({'x': s("""\
@require(table)

    @for row in table:

        @for key, value in row.items():
        @key!h	@value!s
        @end

    @end

""")}), extensions=[CoreExtension()])
    engine.global_vars.update({'h': escape})
    wheezy_template = engine.get_template('x')

    def test_wheezy_template():
        return wheezy_template.render(ctx)

def run(number=100):
    import profile
    from timeit import Timer
    from pstats import Stats
    names = globals().keys()
    temp = [(name)
            for name in names if name.startswith('test_')]

    names = sorted([(name, globals()[name])
                    for name in names if name.startswith('test_')])
    print("                     msec    rps  tcalls  funcs")
    for name, test in names:
        if test:
            assert isinstance(test(), s)
            t = Timer(setup='from __main__ import %s as t' % name,
                      stmt='t()')
            t = t.timeit(number=number)
            st = Stats(profile.Profile().runctx(
                'test()', globals(), locals()))
            print('%-17s %7.2f %6.2f %7d %6d' % (name[5:],
                                                 1000 * t / number,
                                                 number / t,
                                                 st.total_calls,
                                                 len(st.stats)))
        else:
            print('%-26s not installed' % name[5:])

if __name__ == '__main__':
    run()


class DLinkedNode:
    def __init__(self, key=None, value=None):
        self.pre = None
        self.nxt = None
        self.key = key
        self.value = value

class LRUCache:
    def __init__(self, capacity: int):
        self.cache = {}
        self.head = DLinkedNode()
        self.tail = DLinkedNode()
        self.size = 0
        self.capacity = capacity
        self.head.nxt = self.tail
        self.tail.pre = self.head

    def get(self, key: int) -> int:
        node = self.cache.get(key)
        if not node:
            return -1

        self._move_to_head(node)

        return node.value

    def put(self, key: int, value: int) -> None:
        node = self.cache.get(key)
        if not node:
            new_node = DLinkedNode(key, value)
            self.cache[key] = new_node
            self._add_to_head(new_node)
            self.size += 1
            if self.size > self.capacity:
                tail = self._remove_tail()
                self.cache[tail.key] = None
                self.size -= 1

            return

        node.value = value
        self._move_to_head(node)

    def _move_to_head(self, node: DLinkedNode):
        self._remove_node(node)
        self._add_to_head(node)

    def _add_to_head(self, node: DLinkedNode):
        nxt = self.head.nxt
        self.head.nxt = node
        node.pre = self.head
        node.nxt = nxt
        nxt.pre = node

    def _remove_node(self, node: DLinkedNode):
        nxt = node.nxt
        pre = node.pre

        nxt.pre = pre
        pre.nxt = nxt

    def _remove_tail(self) -> DLinkedNode:
        node = self.tail.pre
        self._remove_node(node)
        return node

# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)


"""
Install pyaudio here: http://people.csail.mit.edu/hubert/pyaudio/

"""
import argparse

import pyaudio
import wave

from subscriber import Subscriber

CHUNK = 1024

class Bumper(Subscriber):
    """Simple object that listens to beat output and hits the bass, yo"""
    def __init__(self, bass_path, channels=None, **kwargs):
        # pubsub connection
        if channels is None:
            channels = ['dance-beat']
        super(Bumper, self).__init__(channels, **kwargs)

        # audio player
        self.bass_path = bass_path

    def on_subscribe(self):
        self.fp = wave.open(self.bass_path, 'rb')
        self.audio = pyaudio.PyAudio()
        self.audio_stream = self.audio.open(
            format=self.audio.get_format_from_width(self.fp.getsampwidth()),
            channels=self.fp.getnchannels(),
            rate=self.fp.getframerate(),
            output=True
        )

    def on_close(self):
        self.audio_stream.stop_stream()
        self.audio_stream.close()
        self.audio.terminate()
        self.fp.close()

    def on_event(self, beat):
        data = self.fp.readframes(CHUNK)
        while data:
            self.audio_stream.write(data)
            data = self.fp.readframes(CHUNK)
        self.fp.rewind()

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Subscribes to pubsub and outputs a bass bump")
    parser.add_argument('--bass_file', default='bass.wav')
    args = parser.parse_args()
    bumper = Bumper(args.bass_file)
    bumper.subscribe()


#Working with Modules:
#The below is coming from my module.py file
#mport module
#to import all Modules use the following:
from module import *

num1 = int(input("Enter your first number "))
num2 = int(input("Enter your second number "))

addit(num1, num2)

#Passing a list to a function
# def greet(names):
#   for name in names:
#     print("hello " + name)

# array = ["Mike", "Abby", "Meeka"]
# greet(array)

#Functions which return values
# def addit(num1, num2):
#   return num1 + num2

# answer = addit(2,3)
# print(answer)


# ian.heywood@physics.ox.ac.uk
# Very experimental

import glob
import pickle
import shutil
import time

def stamp():
    return str(time.time()).replace('.','')

# ------- Parameters

myuvrange = '>300m'
myspw = '850~900MHz'

project_info = pickle.load(open('project_info.p','rb'))
myms = project_info['master_ms']
bpcal = project_info['primary'][0] # Using field names because targets will be removed
pcals = project_info['secondary']
primary_tag = project_info['primary_tag']
ref_ant = project_info['ref_ant']

# ------- Setup names

tt = stamp()

ktab0 = 'cal_'+myms+'_'+tt+'.K0'
bptab0 = 'cal_'+myms+'_'+tt+'.B0'
gtab0 = 'cal_'+myms+'_'+tt+'.G0'
gtab1 = 'cal_'+myms+'_'+tt+'.G1'
ftab1 = 'cal_'+myms+'_'+tt+'.flux'

# --------------------------------------------------------------- #
# --------------------------------------------------------------- #
# --------------------------- STAGE 0 --------------------------- #
# --------------------------------------------------------------- #
# --------------------------------------------------------------- #

# ------- Setup models

if primary_tag == '1934':
    setjy(vis=myms,
        field=bpcal,
        standard='Perley-Butler 2010',
        scalebychan=True,
        usescratch=True)

elif primary_tag == '0408':
    bpcal_mod = ([27.907,0.0,0.0,0.0],[-1.205],'850MHz')
    setjy(vis=myms,
        field=bpcal,
        standard='manual',
        fluxdensity=bpcal_mod[0],
        spix=bpcal_mod[1],
        reffreq=bpcal_mod[2],
        scalebychan=True,
        usescratch=True)

# ------- K0 (primary)

gaincal(vis=myms,
    field=bpcal,
    #uvrange=myuvrange,
    spw=myspw,
    caltable=ktab0,
    refant = str(ref_ant),
    gaintype = 'K',
    solint = 'inf',
    parang=False)

# ------- G0 (primary; apply K0)

gaincal(vis=myms,
    field=bpcal,
    uvrange=myuvrange,
    spw=myspw,
    caltable=gtab0,
    gaintype='G',
    solint='inf',
    calmode='p',
    minsnr=5,
    gaintable=[ktab0],
    gainfield=[bpcal],
    interp=['nearest'])

# ------- B0 (primary; apply K0, G0)

bandpass(vis=myms,
    field=bpcal,
    uvrange=myuvrange,
    caltable=bptab0,
    refant = str(ref_ant),
    solint='inf',
    combine='',
    solnorm=False,
    minblperant=4,
    minsnr=3.0,
    bandtype='B',
    fillgaps=64,
    parang=False,
    gainfield=[bpcal,bpcal],
    interp = ['nearest','nearest'],
#    spwmap = [[0,0,0,0,0,0,0,0],[]],
    gaintable=[ktab0,gtab0])

# ------- G1 (primary; a&p sols per scan / SPW)

gaincal(vis = myms,
    field = bpcal,
    uvrange = myuvrange,
    spw=myspw,
    caltable = gtab1,
    refant = str(ref_ant),
    solint = 'inf',
    solnorm = False,
    combine = '',
    minsnr = 3,
    calmode = 'ap',
    parang = False,
    gaintable = [ktab0,gtab0,bptab0],
    gainfield = [bpcal,bpcal,bpcal],
    interp = ['nearest','nearest','nearest'],
    append = False)

for i in range(0,len(pcals)):

    pcal = pcals[i][0] # Using field names

    # --- G2 (secondary)

    gaincal(vis = myms,
        field = pcal,
        uvrange = myuvrange,
        spw=myspw,
        caltable = gtab1,
        refant = str(ref_ant),
        smodel = [1,0,0,0],
        minblperant = 4,
        minsnr = 3,
        solint = 'inf',
        solnorm = False,
        gaintype = 'G',
        combine = '',
        calmode = 'ap',
        parang = False,
        gaintable=[ktab0,gtab0,bptab0],
        gainfield=[bpcal,bpcal,bpcal],
        interp=['nearest','nearest','nearest'],
        append=True)

# ------- F2

fluxscale(vis=myms,
    caltable = gtab1,
    fluxtable = ftab1,
    reference = bpcal,
    append = False,
    transfer = '')

# ------- Apply final tables to secondaries

for i in range(0,len(pcals)):

    pcal = pcals[i][1]

    # --- Correct secondaries with K0, G0, B0, F1

    applycal(vis = myms,
        gaintable = [ktab0,gtab0,bptab0,ftab1],
        field = pcal,
        parang = False,
        gainfield = [bpcal,bpcal,bpcal,''],
        interp = ['nearest','linear','linear','linear'])

# ------- Apply final tables to targets

for targ in targets:

    target = targ[1]
    related_pcal = pcals[targ[3]][1]

    # --- Correct targets with K0, G0, B0, F1

    applycal(vis=myms,
        field=target,
        gaintable = [ktab0,gtab0,bptab0,ftab1],
        parang = False,
        gainfield = [bpcal,bpcal,bpcal,''],
        interp = ['nearest','linear','linear','linear'])


import sys
import time
import threading

from alice import Alice

class AliceCliService:
    """
    ALICE CLI
    コマンドライン用チャット
    データはSQLiteに保存する

    生理的反応:
    オレキシン: 覚醒、安静を制御
    ドーパミン: 快、不快を制御
    覚醒x快: 喜び、快感
    覚醒x不快: 怒り、恐怖
    安静x快: 冷静、優しさ
    安静x不快: 悲しみ、うつ
    """

    alice = Alice()
    alice.load()

    # フラット時間
    flat_time = 0

    # 限界時間
    flat_time_limit = 5

    # 推定した次の入力
    # これがこないとストレスになる。時間がたってもストレスになる。
    next_input = ''

    def input_loop(self):
        """
        入力ループ
        """
        inputstr = input('')
        if len(inputstr) > 0:
            self.alice.input(inputstr, True)
        t = threading.Timer(1, self.input_loop)
        t.start()

    # モード
    mode = 'think'

    # 待ち時間
    flatTime = 0

    # 待ち限界時間
    flatTimeThresh = 5

    action = ''

    def think_action(self):
        """
        アクションを考える
        """
        a = 0

    def decide_action(self):
        """
        アクションを決める
        """
        a = 0
        return 'えー'

    def change_mode(self, next):
        self.flatTime = 0
        self.mode = next

    def run(self):
        """
        メインループ
        """

        # 入力ループ
        t = threading.Thread(target=self.input_loop)
        t.start()

        # aliceループ
        self.flat_time = 0
        while True:
            # 入力は常に受ける
            result = []

            # フレームに分解
            self.alice.parse(result)
            # フレームが見つからなかったら問い合わせ

            # 解析
            self.alice.analyze(result)
            # 解析できなかったら問い合わせ

            # 解析した結果、次の応答が一致したかチェック

            time.sleep(1)
            self.flat_time += 1
            if self.flat_time > self.flat_time_limit:
                self.flat_time = 0
                print('alice> もしもーし')
                # 相手に言葉を伝えたことを記憶
                # 次の応答を推定する
                next_input = '応答'

            # 不明なものがあったらここか問い合わせを行う
            # ユーザーへの問い合わせ、もしくは、SILVIEへの問い合わせ

            # 入力結果を判断する
            # 複数の結果があればSILVIEがNNで処理するのを待つ(think)
            # 1つの結果なら次の行動が決まるのを待つ(think)
            # 何もなければidleになる

            if self.mode == 'wait':
                # 入力待ちのとき
                if self.flatTime >= self.flatTimeThresh:
                    self.think_action()
                    self.change_mode('think')
            elif self.mode == 'think':
                # 決定待ちのとき
                if self.flatTime >= self.flatTimeThresh:
                    self.action = self.decide_action()
                    self.change_mode('action')
            elif self.mode == 'action':
                # アクションを決めたとき
                print(self.action)
                # アクションの結果を推定し、待つ
                self.change_mode('wait')

            # イベントが来たら処理する
            # 生理的反応
            # 記憶による反応

            time.sleep(1)
            self.flatTime += 1

clis = AliceCliService()
clis.run()


from setuptools import setup, find_packages
import os

version = '0.1'

setup(name='bika.uw',
      version=version,
      description="Bika UW",
      long_description="Bika customisations for UW",
      classifiers=[
        "Programming Language :: Python",
        ],
      keywords='',
      author='',
      author_email='',
      url='http://bikalabs.com',
      license='GPL',
      packages=find_packages(exclude=['ez_setup']),
      namespace_packages=['bika'],
      include_package_data=True,
      zip_safe=False,
      install_requires=[
          'setuptools',
          # -*- Extra requirements: -*-
          'bika.lims',
          'archetypes.schemaextender',
          'Products.DataGridField',
      ],
      extras_require={
          'test': [
              'plone.app.testing',
              'robotsuite',
              'robotframework-selenium2library',
              'plone.app.robotframework',
              'Products.PloneTestCase',
              'robotframework-debuglibrary',
              'plone.resource',
              'plone.app.textfield',
          ]
      },
      entry_points="""
      # -*- Entry points: -*-
      [z3c.autoinclude.plugin]
      target = plone
      """,
      )


import argparse
import json
import os
import sys
from datetime import datetime
from typing import NoReturn
from typing import Optional
from typing import Union

import RPi.GPIO as GPIO
from serial.serialutil import SerialException
from tkinter import Button
from tkinter import DISABLED
from tkinter import E
from tkinter import font
from tkinter import HORIZONTAL
from tkinter import Label
from tkinter import mainloop
from tkinter import NORMAL
from tkinter import Scale
from tkinter import Tk
from tkinter import W
from tkinter.ttk import Separator

from crowdbike.helpers import CONFIG_DIR
from crowdbike.helpers import create_logger
from crowdbike.helpers import get_ip
from crowdbike.helpers import get_wlan_macaddr
from crowdbike.helpers import sat_vappressure
from crowdbike.helpers import setup_config
from crowdbike.helpers import upload_to_cloud
from crowdbike.helpers import vappressure
from crowdbike.sensors import DHT22
from crowdbike.sensors import GPS
from crowdbike.sensors import PmSensor
from crowdbike.sensors import SHT85

if sys.version_info < (3, 8):  # pragma: no cover (>=py38)
    import importlib_metadata
else:  # pragma: no cover (<py38)
    import importlib.metadata as importlib_metadata

class ArgumentParser(argparse.ArgumentParser):
    def exit(self, status: int = 0, message: Optional[str] = None) -> NoReturn:
        GPIO.cleanup()
        if message:
            self._print_message(message, sys.stderr)
        exit(status)

parser = ArgumentParser()
parser.add_argument('command', choices=['init', 'run', 'upload'])
parser.add_argument(
    '-V', '--version',
    action='version',
    version=f'%(prog)s {importlib_metadata.version("crowdbike")}',
)
parser.add_argument(
    '--logfile',
    type=str,
    default=os.path.expanduser('~/crowdbike.log'),
    help='file to write the system logs to',
)
parser.add_argument(
    '--loglevel',
    type=str,
    default='WARNING',
    choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
)
args = parser.parse_args()
if args.command == 'init':
    setup_config()
    GPIO.cleanup()
    exit(0)

logger = create_logger(logdir=args.logfile, loglevel=args.loglevel)
logger.info('started crowdbike...')
logger.info(f'arguments passed: {args}')

# load config files
with open(os.path.join(CONFIG_DIR, 'config.json')) as cfg:
    config = json.load(cfg)
    logger.info(f'configuration loaded: {json.dumps(config, indent=2)}')

if args.command == 'upload':
    if args.loglevel == 'DEBUG':
        verbose = True
    else:
        verbose = False

    upload_to_cloud(verbose=verbose, config=config, logger=logger)
    GPIO.cleanup()
    exit(0)

pi_id = config['user']['bike_nr']
studentname = config['user']['studentname']
mac = get_wlan_macaddr()

with open(os.path.join(CONFIG_DIR, 'calibration.json')) as cal:
    calib = json.load(cal)
    logger.info(f'calibration loaded: {json.dumps(calib, indent=2)}')

# calibration params
temperature_cal_a1 = calib['temp_cal_a1']
temperature_cal_a0 = calib['temp_cal_a0']
hum_cal_a1 = calib['hum_cal_a1']
hum_cal_a0 = calib['hum_cal_a0']

window_title = f'Crowdbike {pi_id}'
logfile_path = config['user']['logfile_path']
os.makedirs(logfile_path, exist_ok=True)

counter = 0

# initialize threads
gpsp = GPS(logger)
gpsp.start()

temp_hum_sensor: Union[DHT22, SHT85]
sensor_type = config['user']['sensor_type']
if sensor_type == 'SHT85':
    temp_hum_sensor = SHT85(logger)
    logger.info('using SHT85 sensor')
elif sensor_type == 'DHT22':
    temp_hum_sensor = DHT22(logger)
    logger.info('using DHT22 sensor')
else:
    raise NameError('sensor type unknown, must be either SHT85 or DHT22')

temp_hum_sensor.start()
nova_pm = PmSensor(dev='/dev/ttyUSB0', logger=logger)

# global variables
logfile = ''
with open(os.path.join(CONFIG_DIR, 'theme.json')) as t:
    theme = json.load(t)
    logger.info(f'theme loaded: {json.dumps(theme, indent=2)}')

recording = False

pm_status = nova_pm.running = config['user']['pm_sensor']
# switch off sensor if it is running prior to starting the app
if pm_status is False:
    try:
        nova_pm.sensor_sleep()
    except SerialException:
        logger.warning('could not set PM sensor to sleep mode (startup)')

sampling_rate = config['user']['sampling_rate']

cnames = [
    'id',
    'record',
    'raspberry_time',
    'gps_time',
    'altitude',
    'latitude',
    'longitude',
    'speed',
    'temperature',
    'temperature_raw',
    'rel_humidity',
    'rel_humidity_raw',
    'vapour_pressure',
    'pm10',
    'pm2_5',
    'mac',
    'sensor_id',
]

def exit_program() -> None:
    logger.info('exiting programm...')
    master.destroy()
    gpsp.running = False
    gpsp.stop()
    gpsp.join()
    temp_hum_sensor.running = False
    temp_hum_sensor.join()
    nova_pm.running = False
    # only try joining the thread if it was running
    if nova_pm.isAlive():
        nova_pm.join()
    GPIO.cleanup()
    exit(0)

def record_data() -> None:
    global recording
    global logfile
    recording = True
    b_stop.config(state=NORMAL)
    b_record.config(state=DISABLED)
    b_upload.config(state=DISABLED)
    log_time = datetime.utcnow().strftime('%Y-%m-%d_%H%M%S')
    logfile_name = f"{pi_id}_{studentname.replace(' ', '_')}_{log_time}.csv"
    logfile = os.path.join(logfile_path, logfile_name)
    logger.info(f'writing measurement logs to {logfile}')

    if os.path.isfile(logfile):
        return
    else:
        f0 = open(logfile, 'w')
        for i in range(0, len(cnames)-1):
            f0.write(f'{cnames[i]},')
        f0.write(f'{cnames[len(cnames)-1]}\n')
        f0.close()

def stop_data() -> None:
    global recording
    recording = False
    logger.info('recording stopped')
    b_record.config(state=NORMAL)
    b_stop.config(state=DISABLED)
    b_upload.config(state=NORMAL)

# tkinter button slider function
def set_pm_status(value: str) -> None:
    global pm_slider
    global pm_status
    global nova_pm
    if value == '1':
        pm_status = True
        pm_slider['troughcolor'] = '#20ff20'
        try:
            nova_pm.sensor_wake()
            # reinitialize thread so it gets a new PID
            nova_pm = PmSensor(dev='/dev/ttyUSB0', logger=logger)
            nova_pm.running = True
            nova_pm.start()
        except Exception as e:
            logger.warning(f'failed reading the PM sensor (main): {e}')
            pass
    else:
        pm_status = False
        pm_slider['troughcolor'] = '#c10000'
        try:
            nova_pm.running = False
            nova_pm.join()
            nova_pm.sensor_sleep()
        except Exception as e:
            logger.warning(f'failed setting the PM to sleep mode (main) {e}')
            pass

def start_counting(label: Label) -> None:
    counter = 0

    def count() -> None:
        global counter
        counter += 1
        computer_time = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')

        # get sensor readings from DHT-sensor
        try:
            humidity = temp_hum_sensor.humidity or float('nan')
            temperature = temp_hum_sensor.temperature or float('nan')
        except Exception as e:
            logger.warning(f'reading the temp sensor failed (main): {e}')
            humidity = float('nan')
            temperature = float('nan')

        # calculate temperature with sensor calibration values
        temperature_raw = round(temperature, 5)
        temperature_calib = round(
            temperature * temperature_cal_a1 + temperature_cal_a0,
            3,
        )
        humidity_raw = round(humidity, 5)
        humidity_calib = round(
            humidity * hum_cal_a1 + hum_cal_a0,
            3,
        )

        saturation_vappress = sat_vappressure(temperature_calib)
        vappress = round(
            vappressure(
                humidity_calib,
                saturation_vappress,
            ), 5,
        )

        # read pm-sensor
        if pm_status is True:
            pm2_5 = nova_pm.pm2_5
            pm10 = nova_pm.pm10
        else:
            pm2_5 = float('nan')
            pm10 = float('nan')

        if humidity > 100:
            humidity = 100

        # Get GPS position
        gps_time = gpsp.timestamp
        gps_altitude = gpsp.alt
        gps_latitude = gpsp.latitude
        gps_longitude = gpsp.longitude
        gps_speed = round(gpsp.speed * 1.852, 2)
        f_mode = gpsp.satellites  # store number of satellites
        has_fix = False  # assume no fix

        if f_mode == 2:
            value_counter.config(bg='orange')
        elif f_mode > 2:
            has_fix = True
            value_counter.config(bg='#20ff20')
        else:
            value_counter.config(bg='red')

        # __format value display in gui__
        value_ctime.config(text=computer_time)
        value_altitude.config(text=f'{gps_altitude:.3f} m ASL')
        value_latitude.config(text=f'{gps_latitude:.6f} °N')
        value_longitude.config(text=f'{gps_longitude:.6f} °E')
        value_speed.config(text=f'{gps_speed:.1f} km/h')
        value_time.config(text=gps_time)
        value_temperature.config(
            text='{:.1f} °C'.format(
                temperature_calib,
            ),
        )
        value_humidity.config(text=f'{humidity_calib:.1f} %')
        value_vappress.config(text=f'{vappress:.3f} kPa')

        value_pm10.config(text=f'{pm10:.1f} \u03BCg/m\u00B3')
        value_pm2_5.config(text=f'{pm2_5:.1f} \u03BCg/m\u00B3')

        label.config(text=str(counter))
        label.after(1000 * sampling_rate, count)

        if recording and has_fix:
            with open(logfile, 'a') as f0:
                f0.write(f'{pi_id},')
                f0.write(f'{counter},')
                f0.write(f'{computer_time},')
                if has_fix:
                    f0.write(f'{gps_time},')
                else:
                    f0.write('nan,')

                f0.write(f'{gps_altitude:.3f}' + ',')
                f0.write(f'{gps_latitude:.6f}' + ',')
                f0.write(f'{gps_longitude:.6f}' + ',')
                f0.write(f'{gps_speed:.1f}' + ',')

                f0.write(f'{temperature_calib},')
                f0.write(f'{temperature_raw},')

                f0.write(f'{humidity_calib},')
                f0.write(f'{humidity_raw},')

                f0.write(f'{vappress},')

                f0.write(f'{pm10},')
                f0.write(f'{pm2_5},')

                f0.write(f'{mac},')
                f0.write(f"{config['user']['sensor_id']}\n")

    count()

# define widgets
master = Tk()
master.protocol('WM_DELETE_WINDOW', exit_program)
master.configure(background=theme['bg_col'])
default_font = font.nametofont('TkDefaultFont')
default_font.configure(size=theme['font_size'], family=theme['f_family'])
master.title(window_title)
Label(
    master, text=' Name', fg=theme['fg_header'],
    bg=theme['bg_col'],
).grid(row=0, column=0, sticky=W)
Label(
    master, text=studentname + "'s Crowdbike", fg=theme['fg_header'],
    bg=theme['bg_col'],
).grid(row=0, column=1, sticky=W, columnspan=2)
Label(
    master, text=f'IP: {get_ip()}', fg=theme['fg_header'], bg=theme['bg_col'],
).grid(row=1, column=1, sticky=E, columnspan=2)
Label(
    master, text=' PM-Sensor', fg=theme['fg_header'],
    bg=theme['bg_col'],
).grid(row=1, column=0, sticky=W, columnspan=2)
Separator(master, orient=HORIZONTAL).grid(
    row=2, columnspan=3, sticky='ew', pady=(10, 10),
)
# define labels
label_speed = Label(
    master, text=' Speed',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_speed.grid(row=3, column=0, sticky=W)

label_counter = Label(
    master, text=' Counter',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_counter.grid(row=4, column=0, sticky=W)

label_ctime = Label(
    master, text=' Time',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_ctime.grid(row=5, column=0, sticky=W)

label_altitude = Label(
    master, text=' Altitude',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_altitude.grid(row=6, column=0, sticky=W)

label_latitude = Label(
    master, text=' Latitude',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_latitude.grid(row=7, column=0, sticky=W)

label_longitude = Label(
    master, text=' Longitude',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_longitude.grid(row=8, column=0, sticky=W)

label_time = Label(
    master, text=' GPS Time',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_time.grid(row=9, column=0, sticky=W)

label_temperature = Label(
    master, text=' Temperature',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_temperature.grid(row=10, column=0, sticky=W)

label_humidity = Label(
    master, text=' Rel. Humidity',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_humidity.grid(row=11, column=0, sticky=W)

label_vappress = Label(
    master, text=' Vap. Pressure   ',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_vappress.grid(row=12, column=0, sticky=W)

# labels for pm sensor
label_pm10 = Label(
    master, text=' PM 10 ',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_pm10.grid(row=13, column=0, sticky=W)

label_pm2_5 = Label(
    master, text=' PM 2.5 ',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
label_pm2_5.grid(row=14, column=0, sticky=W)

# define values (constructed also as labels, text will be modified in count)
value_speed = Label(
    master, text=' Speed',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_speed.grid(row=3, column=1, sticky=W, columnspan=2)

value_counter = Label(master, text=' Counter', bg='red', fg=theme['fg_col'])
value_counter.grid(row=4, column=1, sticky=W, columnspan=2)

value_ctime = Label(
    master, text=' Time',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_ctime.grid(row=5, column=1, sticky=W, columnspan=2)

value_altitude = Label(
    master, text=' Altitude',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_altitude.grid(row=6, column=1, sticky=W, columnspan=2)

value_latitude = Label(
    master, text=' Latitude',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_latitude.grid(row=7, column=1, sticky=W, columnspan=2)

value_longitude = Label(
    master, text=' Longitude',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_longitude.grid(row=8, column=1, sticky=W, columnspan=2)

value_time = Label(
    master, text='GPS Time ---------------',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_time.grid(row=9, column=1, sticky=W, columnspan=2)

value_temperature = Label(
    master, text=' Temperature',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_temperature.grid(row=10, column=1, sticky=W, columnspan=2)

value_humidity = Label(
    master, text=' Rel. Humidity',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_humidity.grid(row=11, column=1, sticky=W, columnspan=2)

value_vappress = Label(
    master, text=' Vap. Pressure ',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_vappress.grid(row=12, column=1, sticky=W, columnspan=2)

value_pm10 = Label(
    master, text=' PM 10 ',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_pm10.grid(row=13, column=1, sticky=W, columnspan=2)
value_pm2_5 = Label(
    master, text=' PM 2.5 ',
    bg=theme['bg_col'], fg=theme['fg_col'],
)
value_pm2_5.grid(row=14, column=1, sticky=W, columnspan=2)

# initialize value_counter
start_counting(value_counter)
Separator(master, orient=HORIZONTAL).grid(
    row=15, columnspan=3, sticky='ew', pady=(10, 0),
)
# define buttons
b_record = Button(
    master,
    text='Record',
    width=7,
    state=DISABLED,
    bg=theme['b_col'],
    fg=theme['fg_col'],
    font=(theme['f_family'], 12, 'bold'),
    disabledforeground=theme['b_disabled'],
    command=record_data,
    activeforeground=theme['fg_col'],
    activebackground=theme['b_hover'],
    highlightcolor=theme['b_hl_border'],
    highlightbackground=theme['b_hl_border'],
    highlightthickness=1,

)
b_record.grid(row=16, column=0, sticky=W, padx=(20, 0), pady=(20, 20))

b_stop = Button(
    master,
    text='Stop',
    width=7,
    bg=theme['b_col'],
    fg=theme['fg_col'],
    font=(theme['f_family'], 12, 'bold'),
    state=DISABLED, command=stop_data,
    disabledforeground=theme['b_disabled'],
    activeforeground=theme['fg_col'],
    activebackground=theme['b_hover'],
    highlightcolor=theme['b_hl_border'],
    highlightbackground=theme['b_hl_border'],
    highlightthickness=1,
)
b_stop.grid(row=16, column=1, sticky=W, padx=(20, 40), pady=(20, 20))

b_exit = Button(
    master,
    text='Exit',
    width=7,
    bg=theme['b_col'],
    fg=theme['fg_col'],
    font=(theme['f_family'], 12, 'bold'),
    state=NORMAL, command=exit_program,
    activeforeground=theme['fg_col'],
    activebackground=theme['b_hover'],
    highlightcolor=theme['b_hl_border'],
    highlightbackground=theme['b_hl_border'],
    highlightthickness=1,
)
b_exit.grid(row=16, column=2, sticky=W, pady=(20, 20))

b_upload = Button(
    master,
    text='upload',
    width=7,
    state=DISABLED,
    command=lambda: upload_to_cloud(
        verbose=False, config=config, logger=logger,
    ),
    fg=theme['fg_col'],
    bg=theme['b_col'],
    font=(theme['f_family'], 12, 'bold'),
    disabledforeground=theme['b_disabled'],
    activeforeground=theme['fg_col'],
    activebackground=theme['b_hover'],
    highlightcolor=theme['b_hl_border'],
    highlightbackground=theme['b_hl_border'],
    highlightthickness=1,
)
b_upload.grid(row=16, column=0, sticky=E, padx=(0, 20), pady=(20, 20))

# slider
pm_slider = Scale(
    orient=HORIZONTAL, length=80, to=1, label='',
    showvalue=False, sliderlength=40, troughcolor='#666666',
    width=30, command=set_pm_status,
    fg=theme['fg_col'],
    bg=theme['b_col'],
    activebackground=theme['b_hover'],
    highlightcolor=theme['b_hl_border'],
    highlightbackground=theme['b_hl_border'],
    highlightthickness=1,
)
if pm_status:
    pm_slider['troughcolor'] = '#20ff20'
else:
    pm_slider['troughcolor'] = '#c10000'

pm_slider.set(int(pm_status))
pm_slider.grid(row=1, column=1, sticky=W)

recording = True
record_data()
mainloop()


class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        ans, left, sums = 100001, 0, 0 # ans <= 10^5
        for i in range(len(nums)):
            sums += nums[i]
            while sums >= target:
                ans = min(ans, i+1-left)
                sums -= nums[left]
                left += 1
        return ans if ans < 100001 else 0


import asyncio
import aiohttp

url = "https://job.alibaba.com/zhaopin/socialPositionList/doList.json"
headers = {
    "referer": "https://job.alibaba.com/zhaopin/positionList.htm",
    "x-requested-with": "XMLHttpRequest",
    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
}

async def aio_post(session, url, params):
    """
    根据url和参数发送post请求
    """
    async with session.post(url, headers=headers, data=params) as response:
        res = await response.json()
        data = res["returnValue"]["datas"]
        print(data)

async def crawl(session):
    """
    根据页数创建抓取任务
    """
    tasks = []
    params = "pageSize=10&t=0.9576984861702043&pageIndex={}&keyWord=&location=&second=&first="
    for page in range(1, 613):  # 手动获取页数，当然也可以根据第一页返回的页数自动翻页
        # 此处一定要使用create_task，不能直接await，否则不能并发运行
        task = asyncio.create_task(aio_post(session, url, params.format(page)))
        tasks.append(task)
    # 等待所有任务执行完毕
    for task in tasks:
        await task

async def main():
    # 等同于普通爬虫的 session = request.session()
    session = aiohttp.ClientSession()
    # 生成一个事件循环
    loop = asyncio.get_event_loop()
    # 通过 await 方式调用协程程序
    await crawl(session)

    await session.close()

if __name__ == "__main__":
    asyncio.run(main())


from tkinter import *
grid_spacing = 2
frame_size = 700
XandO_width = frame_size/12
#cant make the x and o 's bigger than the grid box :/
XandO_size = 0.5
colourX = 'light blue'
colourO = 'orange'
draw_colour = 'green'# colour displayed if the game ends in a draw
line_colour = 'light grey' # colour of the grid lines
background_colour = 'white' #colour of the grid while the game is beign played

player1 = 2
 # 2 = O
 # 1 - X

dimension_size = frame_size / 3 # 3 by 3 dimension
# present states
main_screen_state = 0
xState = 1
oState = 2
end_state = 3 #when the game is over*
# allows game to keep track...
blank = 0
X = 1
O = 2
class Game(Tk):
    """
    Main class
    """
    def __init__(self): #self note: the __init__ method of a class is called as soon as an instance of that class is created*

        Tk.__init__(self)
        self.canvas = Canvas(
            height=frame_size, width=frame_size,
            bg=background_colour)
        self.canvas.pack()  #self note: geometry manager that organizes widgets in blocks before placing them in the parent widget
        self.bind('<x>', self.exit)
        self.canvas.bind('<Button-1>', self.button_)
        self.gamestate = main_screen_state
        self.mainScreen()
        self.board = [
            [blank, blank, blank],
            [blank, blank, blank],
            [blank, blank, blank]]
    def mainScreen(self):
    # placeholder main screen
        self.canvas.delete('all') #precaution
        self.canvas.create_rectangle(
            0, 0,
            frame_size, frame_size,
            fill=colourO,
            outline='')
        self.canvas.create_rectangle(
            int(frame_size/15), int(frame_size/15),
            int(frame_size*14/15), int(frame_size*14/15),
            width=int(frame_size/20),
            outline=colourX)
        self.canvas.create_rectangle(
            int(frame_size/10), int(frame_size/10),
            int(frame_size*9/10), int(frame_size*9/10),
            fill=colourX,
            outline='')
        self.canvas.create_text(
            frame_size/2,
            frame_size/3,
            text='TIC TAC TOE', fill='white',
            font=('cambria', int(-frame_size/12), 'bold'))  #colours/fonts used through out are from tkinter colour/font chart
        self.canvas.create_text(
            int(frame_size/2),
            int(frame_size/2.5),
            text='[play]', fill='white',
            font=('cambria', int(-frame_size/25)))

    def gridReset(self):
        self.canvas.delete('all')
        # reset
        self.board = [
            [blank, blank, blank],
            [blank, blank, blank],
            [blank, blank, blank]]
        # draw grid
        for n in range(1, 3):
            # top to bottom
            self.canvas.create_line(
                dimension_size*n, 0,
                dimension_size*n, frame_size,
                width=grid_spacing, fill=line_colour)
            # left to riight
            self.canvas.create_line(
                0, dimension_size*n,
                frame_size, dimension_size*n,
                width=grid_spacing, fill=line_colour)

    def gameover_screen(self, outcome):
        self.canvas.delete('all')
        if outcome == 'X WINS':
            wintext = 'X wins'
            wincolor = colourX
        elif outcome == 'O WINS':
            wintext = 'O wins'
            wincolor = colourO
        elif outcome == 'DRAW':
            wintext = 'Draw'
            wincolor = draw_colour
        self.canvas.create_rectangle(
            0, 0,
            frame_size, frame_size,
            fill=wincolor, outline='')
        self.canvas.create_text(
            int(frame_size/2), int(frame_size/2),
            text=wintext, fill='white',
            font=('cambria', int(-frame_size/6), 'bold'))
        self.canvas.create_text(
                int(frame_size/2), int(frame_size/1.65),
                text='[Click to play again]', fill='white',
                font=('cambria', int(-frame_size/25)))

    def button_(self, event):
        x = self.anit_gridPixel(event.x)
        y = self.anit_gridPixel(event.y)
        if self.gamestate == main_screen_state:
            self.gridReset()
            self.gamestate = player1
        #repeate...
        elif (self.gamestate == xState and
                self.board[y][x] == blank):
            self.new_move(X, x, y)
            if self.winGame(X):
                self.gamestate = end_state
                self.gameover_screen('X WINS')
            elif self.drawGame():
                self.gamestate = end_state
                self.gameover_screen('DRAW')
            else:
                self.gamestate = oState
        elif (self.gamestate == oState and
                self.board[y][x] == blank):
            self.new_move(O, x, y)
            if self.winGame(O):
                self.gamestate = end_state
                self.gameover_screen('O WINS')
            elif self.drawGame():
                self.gamestate = end_state
                self.gameover_screen('DRAW')

            else:
                self.gamestate = xState

        elif self.gamestate == end_state:
            #start over
            self.gridReset()
            self.gamestate = player1

    def new_move(self, player, grid_x, grid_y):

        #coordinates
        if player == X:
            self.draw_X(grid_x, grid_y)
            self.board[grid_y][grid_x] = X

        elif player == O:
            self.draw_O(grid_x, grid_y)
            self.board[grid_y][grid_x] = O
            #symbol allocations.....
    def draw_X(self, grid_x, grid_y):

        x = self.gridPixel(grid_x)
        y = self.gridPixel(grid_y)
        delta = dimension_size/2*XandO_size

        self.canvas.create_line(
            x-delta, y-delta,
            x+delta, y+delta,
            width=XandO_width, fill=colourX)

        self.canvas.create_line(
            x+delta, y-delta,
            x-delta, y+delta,
            width=XandO_width, fill=colourX)

    def draw_O(self, grid_x, grid_y):
        x = self.gridPixel(grid_x)
        y = self.gridPixel(grid_y)
        delta = dimension_size/2*XandO_size

        self.canvas.create_oval(
            x-delta, y-delta,
            x+delta, y+delta,
            width=XandO_width, outline=colourO)

    def winGame(self, symbol):
        for y in range(3):
            if self.board[y] == [symbol, symbol, symbol]:
                return True
        for x in range(3):
            if self.board[0][x] == self.board[1][x] == self.board[2][x] == symbol:
                return True
        if self.board[0][0] == self.board[1][1] == self.board[2][2] == symbol:
            return True

        elif self.board[0][2] == self.board[1][1] == self.board[2][0] == symbol:
            return True
        return False

    def drawGame(self):
        for row in self.board:
            if blank in row:
                return False
        return True

    def gridPixel(self, grid_coord):
        pixel_coord = grid_coord * dimension_size + dimension_size / 2
        return pixel_coord

    def anit_gridPixel(self, pixel_coord):
        # left over pixels on the right & bottom side
        if pixel_coord >= frame_size:
            pixel_coord = frame_size - 1
        grid_coord = int(pixel_coord / dimension_size)
        return grid_coord
    def exit(self, event):
        self.destroy()
def main():
    root = Game()
    root.mainloop()

main()


from pj2.simulator import to_layer_three
class packet:
    def __init__(self, seqnum=0, acknum=0, payload=0):
        self.seqnum = seqnum
        self.acknum = acknum
        self.payload = payload
        self.checksum=0
        self.checksum = self.get_checksum()

    def get_checksum(self):
        # map the packet data to an integer
        checksum=0
        if self.payload!=0:
            for i in range(20):
                checksum= checksum + ord(self.payload.data[i])
        checksum = checksum+self.seqnum+self.acknum
        return checksum

def send_ack(AorB,ack):
    pkt=packet(acknum=ack)
    pkt.checksum=pkt.get_checksum()
    to_layer_three(AorB,pkt)


import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import sem
import scipy.constants as sc
from scipy.constants import codata
from uncertainties import ufloat

def lande(name, J, S):
    (3 * J * (J + 1) + S * (S+1) - L * (L+1)) / (2 * J * (J + 1))

#constants
kb = sc.Boltzmann
mu_0 = sc.mu_0
mu_b = codata.value('Bohr magneton')
na = sc.N_A

T = 294.15 #21°C

#spule
n = 250
F = 86.6 * 1e-6
I = 135 * 1e-3
R = 0.7 #Ohm
r3 = 1000.5

#speisespannung, verstärkung
U_sp = 1
amp = 100

#dictionaries
names = {'gd': "GD2O3",
         'dy': "Dy2O3",
         'nd': "Nd2O3"}

#in kg
mass =  {'gd': 14.08e-3,
         'dy': 18.6e-3,
         'nd': 9.0e-3}

#in m
length =    {'gd': 17.6e-2,
            'dy': 17.9e-2,
            'nd': 17.9e-2}

#in kg / m^3
densitiy = {'gd': 7400,
            'dy': 7800,
            'nd': 7240}

#in V und Ohm

umrechnung_u = 1e-3
umrechnung_r = 5 * 1e-3
U0_Gd = np.array([11.5, 20.0, 20.1]) * umrechnung_u
U0_Dy = np.array([15.5, 13.5, 18.5]) * umrechnung_u
U0_Nd = np.array([14.5, 15.0, 16.0]) * umrechnung_u

U1_Gd = np.array([35.8, 39.8, 39.0]) * umrechnung_u
U1_Dy = np.array([81.1, 82.0, 81.5]) * umrechnung_u
U1_Nd = np.array([16.3, 17.9, 16.5]) * umrechnung_u

R0_Gd = np.array([713, 713, 713]) * umrechnung_r
R0_Dy = np.array([713, 713, 713]) * umrechnung_r
R0_Nd = np.array([718, 716, 709]) * umrechnung_r

R1_Gd = np.array([561, 556, 548]) * umrechnung_r
R1_Dy = np.array([323, 331, 335]) * umrechnung_r
R1_Nd = np.array([688, 694, 692]) * umrechnung_r

print(np.mean(R0_Gd), "+/", sem(R0_Gd))
print(R0_Nd * 1e3)
print(R0_Dy * 1e3)

print(R1_Gd * 1e3)
print(R1_Dy * 1e3)
print(R1_Nd * 1e3)

print(R)
R0 = {'gd': R0_Gd,
      'dy': R0_Dy,
      'nd': R0_Nd}

dU = {'gd': U1_Gd - U0_Gd,
      'dy': U1_Dy - U0_Dy,
      'nd': U1_Nd - U0_Nd}

dR = {'gd': R0_Gd - R1_Gd,
      'dy': R0_Dy - R1_Dy,
      'nd': R0_Nd - R1_Nd}

print("delta r", dR.values())
print("delta u", dU.values())

#experimentelle Bestimmung
#via Spannung U
susuw = ([])

def sus_u(name):
    sus_3 = 4 * F / mass[name] * length[name] * densitiy[name] * dU[name] / U_sp / amp
    print(names[name], "suszept via U alle Messungen", sus_3)
    sus_m = np.mean(sus_3)
    sus_err = sem(sus_3)
    sus = ufloat(sus_m, sus_err)
    print(names[name], "suszept via U:", sus)
    susuw.append(sus)

sus_u("gd")
sus_u("dy")
sus_u("nd")

susrw = ([])

def sus_r(name):
    sus_3r = 2 * dR[name] / (r3 + R0[name]) * F * length[name] * densitiy[name] / mass[name]
    print(names[name], "suszept via R alle Messungen", sus_3r)
    sus_rm = np.mean(sus_3r)
    sus_rerr = sem(sus_3r)
    susr = ufloat(sus_rm, sus_rerr)
    print(names[name], "suszept via R", susr)
    susrw.append(susr)

print("--")
sus_r("gd")
print("--")
sus_r("dy")
print("--")
sus_r("nd")

#theoretische Bestimmung
#s. altprotogut.pdf

s = {'gd': 3.5,
        'dy': 2.5,
        'nd': 1.5}

l = {'gd': 0,
     'dy': 5,
     'nd': 6}

j = {'gd': 3.5,
     'dy': 7.5,
     'nd': 4.5}

#atomare masseneinheit
u = 1.660538921 * 1e-27

molm = {'gd': 362.4982 * u,
        'dy': 372.9982 * u,
        'nd': 336.4822 * u}

def N(name):
    2 * na * densitiy[name] / molm[name]

def lande(name):
    (3 * j[name] * (j[name] + 1) + s[name] * (s[name] + 1) - l[name] * (l[name] + 1)) / (2 * j[name] * (j[name] + 1))

Ndic = {'gd': lande("gd")}

theow = ([])

def sus_t(name):
    lande = (3 * j[name] * (j[name] + 1) + s[name] * (s[name] + 1) - l[name] * (l[name] + 1)) / (2 * j[name] * (j[name] + 1))
    print(names[name], "lande-faktor", lande)
    N = 2 * densitiy[name] / molm[name]
    print(names[name], "Anzahl der Momente pro volumneneinehit N", N)
    sust = mu_0 * mu_b**2 * (lande**2) * N * j[name] * (j[name] + 1) / 3 / kb / T
    print(names[name], "theoretische susz.", sust)
    theow.append(sust)

print("--")
sus_t("gd")
print("--")
sus_t("dy")
print("--")
sus_t("nd")

print("--abbww---")
#gd, dy, nd

print("gd T", theow[0],
      "U", susuw[0],
      "R", susrw[0],
      "abw U", np.absolute((susuw[0] - theow[0]) / susuw[0]),
      "abw R", np.absolute((susrw[0] - theow[0]) / susrw[0] ))

print("dy T", theow[1],
      "U", susuw[1],
      "R", susrw[1],
      "abw U", np.absolute((susuw[1] - theow[1]) / susuw[1]),
      "abw R", np.absolute((susrw[1] - theow[1]) / susrw[1]))

print("nd T", theow[2],
      "U", susuw[2],
      "R", susrw[2],
      "abw U", np.absolute((susuw[2] - theow[2]) / susuw[2]),
      "abw R", np.absolute((susrw[2] - theow[2]) / susrw[2]))


import json
#문자열에서 문자하나 카운트 해주는 모듈
class Ccfs():
    def __init__(self, sentense, character):

        if(len(character)!=1):
            self.count = -1
        else:
            self.count = sentense.count(character)

        self.length = len(sentense)
    def getJson(self):
        return json.dumps({"count":self.count,"length":self.length})

if __name__ == "__main__":
    #test
    print(Ccfs("ashjjjjjs salsl    ","s").getJson())


"""
<description>
"""

import subprocess
import math
import curses
import time
import cProfile

def get_term_size():
    height = int(subprocess.check_output(["tput", "lines"]))
    width = int(subprocess.check_output(["tput", "cols"]))
    return height, width

def test_screen(bar_width=6, num_bars=3):
    lines, cols = get_term_size()
    bar_str = "=" + "#" * bar_width + "=" + " "* bar_width
    screen = [c*cols for c in bar_str * num_bars]
    return screen

def test(term, duration=4, speed=60):
    decay = speed / duration

    term_h, term_w = get_term_size()
    curses.curs_set(0)
    term.clear()
    term.touchwin()
    term.refresh()
    curses.doupdate()

    screen = test_screen()
    lines = []
    while len(lines) < term_h:
        lines += screen
    num_lines = len(lines)
    lines *= 2
    top = 0
    t_after = time.time()
    while speed > 0:
        t_before = t_after

        i_top = int(top) % num_lines
        i_bot = i_top + term_h - 1
        vis = lines[i_top:i_bot]

        for y, line in enumerate(vis):
            term.addstr(y, 0, line)

        term.addstr(math.floor(term_h/2), term_w-2, "<=", curses.A_BOLD)
        term.refresh()

        t_after = time.time()
        delta_t = t_after - t_before

        top += speed * delta_t
        speed -= decay * delta_t

    time.sleep(1)
    return 1

winner = None
cProfile.run("winner = curses.wrapper(test)")
print(winner)


import os
import praw
import csv
import requests
import pandas as pd
from datetime import datetime
from bs4 import BeautifulSoup

# praw_url = 'https://www.reddit.com/r/movies/comments/a6qh98/official_discussion_aquaman_us_release_spoilers/'
# boxoffice_url = 'https://www.the-numbers.com/movie/Aquaman-(2018)#tab=box-office'

praw_url = input()
boxoffice_url = input()

client_id = "your reddit app client id"
client_secret = "your reddit app client secret"
user_agent = "your reddit user agent"

def get_boxoffice(boxoffice_url):
    """

    """
    r = requests.get(boxoffice_url)
    soup = BeautifulSoup(r.content)

    divTag = soup.find_all("div", {"id": "box-office"})
    for tag in divTag:
        tdTags = tag.find_all("table")

    # Weekend Boxoffice
    df_weekend = pd.read_html(
        tdTags[1].prettify(), skiprows=1, flavor="bs4")[0]
    df_weekend.columns = [
        "Date",
        "Rank",
        "Gross",
        "% Change",
        "Theaters",
        "Per Theater",
        "Total Gross",
        "Week",
    ]

    # Daily Boxoffice
    df_daily = pd.read_html(tdTags[2].prettify(), skiprows=1, flavor="bs4")[0]
    df_daily.columns = [
        "Date",
        "Rank",
        "Gross",
        "% Change",
        "Theaters",
        "Per Theater",
        "Total Gross",
        "Days",
    ]

    # Weekly Boxoffice
    df_weekly = pd.read_html(tdTags[2].prettify(), skiprows=1, flavor="bs4")[0]
    df_weekly.columns = [
        "Date",
        "Rank",
        "Gross",
        "% Change",
        "Theaters",
        "Per Theater",
        "Total Gross",
        "Week",
    ]

    # Title of the movie
    titleTag = soup.find("h1", {"itemprop": "name"}, text=True)
    title = titleTag.get_text()

    return df_daily, df_weekend, df_weekly, title

def get_reddit_comments():

    reddit = praw.Reddit(
        client_id=client_id, client_secret=client_secret, user_agent=user_agent
    )

    subreddit = reddit.subreddit("movies")
    submission = reddit.submission(url=praw_url)

    """
    The script works for every post. You just need to edit the desired subreddit and submission
    """

    comment_list = []

    """
    submissions use tree traversal to grab comments and its child comments.
    there's a lot of info that can be retrieved from a single comment. Check reddit api docs or praw docs for more info.
    """

    submission.comments.replace_more(limit=None)
    for comment in submission.comments.list():
        try:
            author = comment.author.id
            body = comment.body
            created_at = datetime.fromtimestamp(int(comment.created_utc)).strftime(
                "%Y-%m-%d %H:%M:%S"
            )
            gilded = comment.gilded
            upvotes = comment.ups

            comment_list.append([author, body, created_at, gilded, upvotes])
        except AttributeError as e:
            print(e)
            pass

    return comment_list

def save_data(df_daily, df_weekend, df_weekly, title, comment_list):

    path = "/content/gdrive/My Drive/Colab Notebooks/rmovies_nlp/data/{}".format(
        title)

    try:
        os.mkdir(path)
    except OSError:
        print("Creation of the directory %s failed" % path)
    else:
        print("Successfully created the directory %s " % path)

    df_daily.to_csv(
        "/content/gdrive/My Drive/Colab Notebooks/rmovies_nlp/data/{}/{}_daily.csv".format(
            title, title
        ),
        sep=";",
    )
    df_weekend.to_csv(
        "/content/gdrive/My Drive/Colab Notebooks/rmovies_nlp/data/{}/{}_weekend.csv".format(
            title, title
        ),
        sep=";",
    )
    df_weekly.to_csv(
        "/content/gdrive/My Drive/Colab Notebooks/rmovies_nlp/data/{}/{}_weekly.csv".format(
            title, title
        ),
        sep=";",
    )

    with open(
        "/content/gdrive/My Drive/Colab Notebooks/rmovies_nlp/data/{}/{}.csv".format(
            title, title
        ),
        "w",
        encoding="utf-8",
    ) as myfile:
        wr = csv.writer(myfile, quoting=csv.QUOTE_ALL)
        for list_ in comment_list:
            wr.writerow(list_)

    print("done")
    return

"""df_daily, df_weekend, df_weekly, title = get_boxoffice()
comment_list = get_reddit_comments()
save_data(df_daily, df_weekend, df_weekly, title, comment_list)"""


import json
import os
import re
import sys
import time

import pandas

import run_DCP

def parse_image_names(imlist,filter_in, filter_out="jibberish"):
    image_dict = {}
    for image in imlist:
        if '.nd2' in image:
            if filter_in.lower() in image.lower():
                if filter_out.lower() not in image.lower():
                    prePlate,platePlus = image.split('images/')
                    plate,cycle,imname = platePlus.split('/')
                    well = imname[:imname.index('_')]
                    if plate not in image_dict.keys():
                        image_dict[plate] = {well:{cycle:[imname]}}
                    else:
                        if well not in image_dict[plate].keys():
                            image_dict[plate][well] = {cycle:[imname]}
                        else:
                            if cycle not in image_dict[plate][well].keys():
                                image_dict[plate][well][cycle] = [imname]
                            else:
                                image_dict[plate][well][cycle] += [imname]
    return image_dict

def return_full_wells(image_dict,expected_cycles,one_or_many, files_per_well=1):
    im_dict_out = {}
    expected_cycles = int(expected_cycles)
    platelist = image_dict.keys()
    for eachplate in platelist:
        print('Checking compeleteness of plate', eachplate)
        platedict = image_dict[eachplate]
        well_list = platedict.keys()
        #first let's see how many wells have every cycle
        full_wells = []
        for eachwell in well_list:
            cycle_list = platedict[eachwell].keys()
            if len(cycle_list) == expected_cycles:
                has_all_files = True
                #let's also make sure each cycle has all its files; for Cycle 1, that's 1, for the rest it's 5
                for cycle in cycle_list:
                    if len(platedict[eachwell][cycle]) not in (files_per_well,files_per_well*5):
                        has_all_files = False
                        print ("Plate", eachplate, "Well", eachwell, "Cycle", cycle, "only had", len(platedict[eachwell][cycle]), "files")
                if has_all_files:
                    full_wells.append(eachwell)

        #Initialize our output dictionary for the plate
        print('Writing out the output for plate',eachplate,'has full wells',full_wells)
        per_cycle_dict={}
        for cycle in range(1,expected_cycles+1):
            per_cycle_dict[cycle]={}
        for eachwell in full_wells:
            cycle_list = platedict[eachwell].keys()
            for cycle in cycle_list:
                match = re.search('[-_]c[_-]{0,1}[0-9]{1,2}',cycle)
                out = match.group(0)
                cycle_num = int(out[out.index('c')+1:])
                if cycle_num == 1 and one_or_many =='one':
                    per_cycle_dict[cycle_num][eachwell]=[cycle,platedict[eachwell][cycle]*5]
                else:
                    temp_list = platedict[eachwell][cycle]
                    temp_list.sort()
                    per_cycle_dict[cycle_num][eachwell]=[cycle,temp_list]
        im_dict_out[eachplate] = per_cycle_dict
    return im_dict_out

def download_and_read_metadata_file(s3, bucket_name, metadata_file_name, metadata_on_bucket_name):
    with open(metadata_file_name, 'wb') as f:
        s3.download_fileobj(bucket_name,  metadata_on_bucket_name, f)
    with open(metadata_file_name, 'r') as input_metadata:
        metadata = json.load(input_metadata)
    return metadata

def write_metadata_file(s3, bucket_name, metadata, metadata_file_name, metadata_on_bucket_name):
    with open(metadata_file_name, 'wb') as f:
        json.dump(metadata, f)
    with open(metadata_file_name, 'r') as metadata:
        s3.put_object(Body = metadata, Bucket = bucket_name, Key = metadata_on_bucket_name)

def paginate_a_folder(s3,bucket_name,prefix):
    paginator = s3.get_paginator('list_objects_v2')
    pages = paginator.paginate(Bucket=bucket_name, Prefix=prefix)
    image_list = []
    #image_list = s3.list_objects_v2(Bucket=bucket_name,Prefix=)['Contents']
    for page in pages:
        image_list += [x['Key'] for x in page['Contents']]
    return image_list

def check_if_run_done(s3, bucket_name, filter_prefix, expected_len, current_app_name, prev_step_app_name, sqs, dup_queue_name, filter_in = None, filter_out = None):
    #Step 1- how many files are there in the illum folder?
    image_list = paginate_a_folder(s3, bucket_name, filter_prefix)
    done = False

    if filter_in != None:
        image_list = [x for x in image_list if filter_in in x]
    if filter_out != None:
        image_list = [x for x in image_list if filter_out not in x]

    if len(image_list) >= expected_len:
        done = True
    else:
        print('Only ',len(image_list),' output files so far')

    #Maybe something died, but everything is done, and you have a monitor on that already cleaned up your queue
    queue_url = check_named_queue(sqs, prev_step_app_name+'Queue')
    if queue_url == None:
        done = True

    else:
        #Maybe something died, and now your queue is just at 0 jobs
        attributes = sqs.get_queue_attributes(QueueUrl=queue_url,AttributeNames=['ApproximateNumberOfMessages','ApproximateNumberOfMessagesNotVisible'])
        if attributes['Attributes']['ApproximateNumberOfMessages'] + attributes['Attributes']['ApproximateNumberOfMessagesNotVisible'] == 0:
            done = True

    #If indeed we are done, we want to check we're not overlapping and starting the same next job many times
    if done:
        # Check if current queue exists already (job already triggered)
        current_queue_url = check_named_queue(sqs, current_app_name+'Queue')
        if current_queue_url != None:
            return False
        # Check FIFO queue
        dup_queue_url=check_named_queue(sqs, dup_queue_name)
        nmess = sqs.get_queue_attributes(QueueUrl=dup_queue_url,AttributeNames=['ApproximateNumberOfMessages'])['Attributes']['ApproximateNumberOfMessages']
        sqs.send_message(QueueUrl=dup_queue_url, MessageBody=prev_step_app_name, MessageGroupId='0')
        time.sleep(2)
        nmess2 = sqs.get_queue_attributes(QueueUrl=dup_queue_url,AttributeNames=['ApproximateNumberOfMessages'])['Attributes']['ApproximateNumberOfMessages']
        if nmess2 != nmess: #aka, if we're the first job to report in as finished
            return True

    #or, we're just not done yet
    return False

def check_named_queue(sqs, SQS_QUEUE_NAME):
    result = sqs.list_queues()
    if 'QueueUrls' in result.keys():
        for u in result['QueueUrls']:
            if u.split('/')[-1] == SQS_QUEUE_NAME:
                return u
    return None

def try_to_run_monitor(s3, bucket_name, prefix, batch, step, prev_step_app_name):
    prev_step_monitor_bucket_name = prefix + 'monitors/'+batch+'/'+step+'/'+prev_step_app_name + 'SpotFleetRequestId.json'
    prev_step_monitor_name = '/tmp/'+prev_step_app_name + 'SpotFleetRequestId.json'
    print('Trying to shut down ',prev_step_monitor_bucket_name)
    with open(prev_step_monitor_name, 'wb') as f:
        s3.download_fileobj(bucket_name,  prev_step_monitor_bucket_name, f)
    print('Grabbing config for batch',batch,'step',step)
    run_DCP.grab_batch_config(bucket_name,prefix,batch,step)
    import boto3_setup
    boto3_setup.monitor()

def try_a_shutdown(s3, bucket_name, prefix, batch, prev_step_number, prev_step_app_name):
    print('Trying monitor')
    try:
        import botocore
        try_to_run_monitor(s3, bucket_name, prefix, batch, str(prev_step_number), prev_step_app_name)
    except botocore.exceptions.ClientError as error:
        print('Monitor cleanup of previous step failed with error: ',error)
        print('Usually this is no existing queue by that name, maybe a previous monitor cleaned up')
    except:
        print('Monitor cleanup of previous step failed with error',sys.exc_info()[0])
        pass

def concat_some_csvs(s3,bucket_name,file_list,csvname):
    tmp_name = os.path.join('/tmp',csvname)
    df_dict={}
    count = 0
    for eachfile in file_list:
        with open(tmp_name, 'wb') as f:
            s3.download_fileobj(bucket_name,  eachfile, f)
        df_dict[eachfile]=pandas.read_csv(tmp_name,index_col=False)
        count+=1
        if count % 100 == 0:
            print(count)
    df_merged = pandas.concat(df_dict, ignore_index=True)
    return df_merged


# -*- encoding: utf-8 -*-
# 2018/3/22 13:46

import random, os, sys, datetime, time
import json, re, math,json
import psutil
import requests
import threading
import urllib.request
from lxml import etree
from config import *

import smtplib
from email.header import Header
from email.mime.text import MIMEText

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
import mysqlc
import mssqlc
from func import *

def robot_check(tree, platform='', asin=''):
    yzm = tree.xpath(rvx['robot'])
    if yzm:                                              # 验证码
        print('验证码 {} {} '.format(platform, asin))
        DIC['yzm'] = DIC['yzm'] + 1
        return 1

def wcountry(all=0):
    if all == 'us': return " and Country='美国'"
    if all == 'uk': return " and Country='英国'"
    if all == 'fr': return " and Country='法国'"
    if all == 'jp': return " and Country='日本'"
    if all == 'de': return " and Country='德国'"
    if all == 'other': return " and Country not in ('美国','英国','法国','日本','德国')"
    return ""

# 解析店铺的产品列表页, 得到店铺的产品
# 店铺的产品页会根据访客IP地址，得到不同的产品总数，不同地址得到的产品数会不一样
def parse_store_product_list(S_ID, PAGE=1):
    db = mssqlc.mssql(CONFIG3) if IS_MSSQL else mysqlc.mysql(CONFIG)

    row = db.one("select Country, StoreID, Category, CreateTime from ck_stores where S_ID={}".format(S_ID))
    if not row: return

    Country, StoreID, Category, CreateTime = row

    if not StoreID: return

    host = DIC['pf'][Country]

    url = 'https://{0}/s/ref=sr_il_to_merchant-items?me={1}&page={2}&ie=UTF8'.format(host, StoreID, PAGE)
    # url = 'http://localhost/python/amastore/00.txt'

    HEADERS['User-Agent'] = random.choice(USER_AGENT_LIST)
    HEADERS['Accept-Language'] = random.choice(ACCEPT_LANGUAGE_LIST)
    HEADERS['referer'] = 'https://{}/sp?_encoding=UTF8&orderID=&seller={}'.format(host, StoreID)
    HEADERS['Cookie'] = random.choice(COOKIES1[host])

    req = requests.get(url, timeout=10, headers=HEADERS)
    req.encoding = 'utf-8'

    print("status_code {} {}\n".format(req.status_code, url))

    if req.status_code != 200:
        db.close()
        return

    tree = etree.HTML(req.text, parser=etree.HTMLParser(remove_comments=True))

    if robot_check(tree, url):  # 验证码
        db.close()
        return

    spx = spx1
    boxs = tree.xpath(spx['box'])

    if not boxs: spx = spx2
    boxs = tree.xpath(spx['box'])

    if not boxs:
        # file_write('00test.log', req.text, 'w')
        print("store has no boxs", spx['box'], sep=", ")
        db.close()
        return

    t_pnum = tree.xpath(spx['pnum'])
    if t_pnum and PAGE == 1:
        print("产品数量 {}, {}, {}".format(get_pronum(t_pnum[0]), S_ID, StoreID))

    if PAGE == 1:  # 采集第二页以后的页数
        n_pages = tree.xpath(spx['pager'])
        pages = len(n_pages) - 2 if n_pages else 1

        n_pager2 = tree.xpath(spx['pager2'])

        pages = int(n_pager2[0].strip()) if n_pager2 else pages

        print("pages: {}".format(pages))

        if pages > 1:
            pages = min(pages, 5)  # 只采集前5页
            args2 = [[S_ID, i] for i in range(2, pages + 1)]
            threads_run(parse_store_product_list, args2)  # 开启多线程，去爬取第2页以后的页数
            print('---------------------------------------')

    for box in boxs:
        dd2 = {}
        dd2['Country'] = Country
        dd2['S_ID'] = S_ID
        dd2['Category'] = Category
        dd2['CreateTime'] = now()
        dd2['IsExists'] = 1

        n_url = box.xpath(spx['spurl'])
        if n_url:
            ret2 = re.search('/dp/(\w+)', n_url[0].get("href"), re.IGNORECASE)
            dd2['ASIN'] = ret2.group(1).strip() if ret2 else ''

        print(dd2)

        if 'ASIN' not in dd2: continue

        cond = "Country='{}' and ASIN='{}'".format(Country, dd2['ASIN'])
        db.update_or_add('ck_products', dd2, cond, 0)

    db.update('ck_stores', {'Cjtime': now()}, "S_ID='{}'".format(S_ID), 0)           # 更新店铺的采集时间
    db.close()
    return

# 评论列表页
def parse_review_page(product_id, asin, Country):

    db = mssqlc.mssql(CONFIG3) if IS_MSSQL else mysqlc.mysql(CONFIG)

    cond = "P_ID={}".format(product_id)
    row = db.one("select ASIN, Country, Cjtime, reviews from ck_products where {}".format(cond))
    asin, Country, Cjtime, reviews = row

    platform = DIC['pf'][Country]

    HEADERS['User-Agent'] = random.choice(USER_AGENT_LIST)
    HEADERS['Accept-Language'] = random.choice(ACCEPT_LANGUAGE_LIST)
    HEADERS['Cookie'] = random.choice(COOKIE_LIST_CHROME_COM)
    HEADERS['referer'] = 'https://{}/dp/{}/ref=?_encoding=UTF8&pf_rd_i=desktop'.format(platform, asin)

    purl = 'https://{}/product-reviews/{}/ref=cm_cr_getr_d_paging_btm_1?ie=UTF8&reviewerType=all_reviews&filterByStar=positive&pageNumber=1&sortBy=recent'.format(platform,asin)

    req = requests.get(purl, timeout=10, headers=HEADERS)
    req.encoding = 'utf-8'

    tree = etree.HTML(req.text, parser=etree.HTMLParser(remove_comments=True))

    if robot_check(tree, platform, asin):           # 验证码
        db.close()
        return

    print("status_code {} {}\n".format(req.status_code, purl))

    if req.status_code == 404:              # 404，判断产品为下线
        db.update("ck_products", {"IsExists": 0}, "P_ID={}".format(product_id), 0)
        db.close()
        return

    if req.status_code != 200:
        db.close()
        return

    dd = {}
    t_reviews = tree.xpath(ppx['reviews'])
    t_stars = tree.xpath(ppx['stars'])

    dd['reviews'] = re.sub("\D", "", t_reviews[0]) if t_reviews else 0
    dd['star'] = get_stars(platform, t_stars[0]) if t_stars else 0
    dd['creviews'] = 0

    x_critical = '//a[@data-reftag="cm_cr_arp_d_viewpnt_rgt"]'
    nodes1 = tree.xpath(x_critical)

    if nodes1:
        creviews = re.sub("\D", "", nodes1[0].text)                 # 提取差评数
        dd['creviews'] = int(creviews) if creviews else 1          # 差评数为1的时候text提取不出来，所以手动设为1

    dd['previews'] = int(dd['reviews']) - int(dd['creviews'])       # 好评数
    print('star: {}, reviews: {}, previews: {}'.format(dd['star'], dd['reviews'], dd['previews']), purl, sep=", ")

    boxs = tree.xpath(rvx['box'])

    if not boxs:
        db.update('ck_products', {"Cjtime": now(), "reviews": dd['reviews']}, cond, 0)
        db.close()
        return

    cj_all = 1 if not Cjtime or DIC['days_brefore_reviews'] < 0 else 0  # 如果cjtime为空，就全部采集, 则部分采集

    get_critical_10(tree, product_id, platform, asin)           # 第一页的默认全采

    pages = math.ceil(dd['previews'] / 10)
    for i in range(2, pages + 1):                              # 从第二页开始采集
        sret = get_ajax_review_by_day(product_id, asin, platform, i, cj_all)
        if not sret: break

    db.update("ck_products", {"Cjtime": now(), "reviews": dd['reviews']}, cond, 0)   # 更新产品的采集时间

    # pagesize = 10                         # 每次爬取的页数，等于线程数
    # num = math.ceil(pages / pagesize)     # 循环多少次
    #
    # for i in range(num):                   # 第二页以后的差评
    #     spage = i * pagesize + 2;          # 开始页数
    #     args2 = [[product_id, asin, platform, i] for i in range(spage, min(spage + pagesize, pages + 1))]
    #     threads_run(get_ajax_review_by_day, args2)

# 获得ajax评论页中指定页的评论
def get_ajax_review_by_day(product_id, asin, platform, page, cj_all=1):

    referer = "https://" + platform + "/hz/reviews-render/ajax/reviews/get/ref=cm_cr_getr_d_paging_btm_1"

    HEADERS['User-Agent'] = random.choice(USER_AGENT_LIST)
    HEADERS['Cookie'] = random.choice(COOKIE_LIST_CHROME_COM)
    HEADERS['Accept-Language'] = random.choice(ACCEPT_LANGUAGE_LIST)
    HEADERS['Content-Type'] = "application/x-www-form-urlencoded;charset=UTF-8"
    HEADERS['X-Requested-With'] = "XMLHttpRequest"
    HEADERS['referer'] = referer

    rv_pdata['asin'] = asin
    rv_pdata['pageNumber'] = str(page)
    rv_pdata['reftag'] = "cm_cr_getr_d_paging_btm_" + str(page)
    rv_pdata['scope'] = 'reviewsAjax' + str(random.randint(1, 5))
    rv_pdata['filterByStar'] = "positive"

    posturl = "https://" + platform + "/hz/reviews-render/ajax/reviews/get/ref=" + rv_pdata["reftag"]
    req = requests.post(posturl, timeout=10, headers=HEADERS, data=rv_pdata)

    print( "{} {} {}".format(req.status_code, product_id, posturl))

    if req.status_code != 200:
        return

    req.encoding = 'utf-8'
    content = req.text.replace('\\"', '"')
    tree = etree.HTML(content)
    ret = get_critical_10(tree, product_id, platform, asin, cj_all)
    return ret

# 解析评论
def get_critical_10(tree, product_id, platform, asin, cj_all=1):
    db = mssqlc.mssql(CONFIG3) if IS_MSSQL else mysqlc.mysql(CONFIG)
    nodes = tree.xpath(rvx['box'])
    for node in nodes:
        dic = {}
        dic['P_ID'] = product_id
        dic['Country'] = DIC['countrys'][platform]
        r_date = node.findtext(rvx['date'])
        sdate = date2stamp(platform, r_date)

        n_asin2 = node.xpath(rvx['asin2'])
        dic['ASIN'] = n_asin2[0].split("/")[3] if n_asin2 else asin

        r_stars = node.findtext(rvx['stars'])

        dic['R_No'] = node.get("id").strip()
        dic["R_Date"] = sdate
        dic['R_CustomerID'] = node.xpath(rvx['cuid'])[0].split("/")[3]
        dic['R_Aname'] = node.xpath(rvx['customer'])[0].text.strip()[:270]
        dic["CreateTime"] = now()                                             # 每次爬取后，都更新爬取时间

        dic["R_Star"] = get_stars(platform, r_stars);
        dic['R_Title'] = node.findtext(rvx['title'])
        dic['R_Content'] = os.linesep.join(node.find(rvx['content']).itertext())

        print(dic)

        if not dic['R_Date'] or not dic['R_No']: continue

        cond2 = "R_CustomerID='{}'".format( dic['R_CustomerID'] )                          # 有重复客户长ID的不新增，只upate
        db.update_or_add('ck_reviews', dic, cond2, 0)                                       # 更新或添加差评

    days_ago = days_before(DIC['days_brefore_reviews'], 0)       # 几天前的时间戳
    if not cj_all:
        print("采集{}天前的, {} ....".format(DIC['days_brefore_reviews'], sdate))
        plstime = int(time.mktime(time.strptime(str(sdate).split(" ")[0], "%Y-%m-%d")))  # 评论日期的时间戳
        if plstime < days_ago:
            url3 = "stop {} days before {} {} https://{}/product-review/{}/ref=cm_cr_arp_d_viewopt_srt?sortBy=recent&filterByStar=positive ***"
            print(url3.format(DIC['days_brefore_reviews'], sdate, product_id, platform, asin))
            return

    db.close()
    return 1

# 检测产品是否在线
def check_product_online(product_id):

    db = mssqlc.mssql(CONFIG3) if IS_MSSQL else mysqlc.mysql(CONFIG)

    cond = "P_ID={}".format(product_id)
    row = db.one("select ASIN, Country, CreateTime from ck_products where {}".format(cond))
    asin, Country, CreateTime = row

    platform = DIC['pf'][Country]

    HEADERS['User-Agent'] = random.choice(USER_AGENT_LIST)
    HEADERS['Accept-Language'] = random.choice(ACCEPT_LANGUAGE_LIST)
    HEADERS['Cookie'] = random.choice(COOKIE_LIST_CHROME_COM)
    HEADERS['referer'] = 'https://{}/dp/{}/ref=?_encoding=UTF8&pf_rd_i=desktop'.format(platform, asin)

    purl = 'https://{}/dp/{}'.format(platform,asin)
    req = requests.get(purl, timeout=10, headers=HEADERS)
    req.encoding = 'utf-8'

    print("status_code {} {}\n".format(req.status_code, purl))

    IsExists = 1
    if req.status_code == 404:
        IsExists = 0

    db.update("ck_products", {"IsExists": IsExists}, "P_ID={}".format(product_id), 0)
    db.close()

# July 14, 2016
# 27 January 2017
def convert_date(stri):
    stri = stri.replace(',', '')
    ft = "%B %d %Y"
    if stri[0].isdigit():
        ft = "%d %B %Y"
    ret = datetime.datetime.strptime(stri, ft)
    return ret

"""
com on August 11, 2016
jp  2018年3月12日
de  am 4. November 2017
fr  le 2 février 2017
it  il 28 giugno 2017
es  el 13 de enero de 2018
mx  el 26 de septiembre de 2016
"""

def date2stamp(platform='www.amazon.com', sdate=0):
    if sdate is None:
        return

    sdate = sdate.strip().lower()

    if platform in ['www.amazon.com', 'www.amazon.co.uk', 'www.amazon.ca']:
        sdate = sdate.replace("on ", "")
        fdate = convert_date(sdate)
        return fdate

    if platform == 'www.amazon.co.jp':
        fdate = re.sub("\D", "-", sdate.replace("日",''))
        return fdate

    elif platform in ['www.amazon.es', 'www.amazon.com.mx']:
        sdate = sdate.replace("el ", '').replace(" de ", '-')
        sdate = replace_dict(sdate, es_months)

    elif platform == 'www.amazon.de':
        sdate = sdate.replace("am ", '').replace(" ", '-').replace(".", '')
        sdate = replace_dict(sdate, de_months)

    elif platform == 'www.amazon.fr':
        sdate = sdate.replace("le ", '').replace(" ", '-')
        sdate = replace_dict(sdate, fr_months)

    elif platform == 'www.amazon.it':
        sdate = sdate.replace("il ", '').replace(" ", '-')
        sdate = replace_dict(sdate, it_months)

    fdate = time.strftime("%Y-%m-%d", time.strptime(sdate, "%d-%m-%Y"))

    return fdate

"""
com 1.0 out of 5 stars
fr  3,0 sur 5 étoiles
de  1,0 von 5 Sternen
jp  5つ星のうち1.0
it  4,0 su 5 stelle
es  2,0 de 5 estrellas
mx  4.0 de 5 estrellas
"""

def get_stars(platform, r_rank):
    if r_rank is None: return 0

    r_rank = r_rank.strip()

    if platform in ['www.amazon.com', 'www.amazon.co.uk', 'www.amazon.ca']:
        ret = r_rank.replace(" out of 5 stars", '')

    elif platform == 'www.amazon.co.jp':
        ret = r_rank.replace("5つ星のうち", '')

    elif platform == 'www.amazon.de':
        ret = r_rank.replace(" von 5 Sternen", '').replace(",", ".")

    elif platform == 'www.amazon.fr':
        ret = r_rank.replace(" sur 5 étoiles", '').replace(",", ".").replace(" sur 5\xa0étoiles", '')

    elif platform in ['www.amazon.es', 'www.amazon.com.mx']:
        ret = r_rank.replace(" de 5 estrellas", '').replace(",", ".")

    elif platform == 'www.amazon.it':
        ret = r_rank.replace(" su 5 stelle", '').replace(",", ".")

    else:
        ret = r_rank

    return float(ret)

# 店铺的产品数
def get_pronum(txt):
    print(txt)
    S_PVolume = txt.split(" of ")[-1]  # en
    S_PVolume = S_PVolume.split(" von ")[-1]  # de
    S_PVolume = S_PVolume.split(" sur ")[-1]  # fr
    S_PVolume = S_PVolume.split(" su ")[-1]  # it
    S_PVolume = S_PVolume.split(" de ")[-1]  # es
    S_PVolume = S_PVolume.split("の")[0]  # jp
    S_PVolume = re.sub('\D', '', S_PVolume)  # es
    return S_PVolume