# Authour: Samantha Preisig
# File: main.py (driver)
# Brief: creates DynamoDB tables and runs CLI

import configparser
import os
import sys
import boto3
import readline
from botocore.exceptions import ClientError

# Import custom files/modules
import global_vars
from create_table import build_json, create_table
from cli_commands import *

# Purpose: initializing global variables declared in global_vars.py. These
# variables are made global to all modules in the current directory
def set_globals():
    global_vars.init() # Declaring global variables

    # Initialization
    global_vars.dict_tables = {
        "shortlist_area.csv": {"table_name": "spreisig_shortlist_area", "key_columns": ["ISO3"], "columns": []},
        "shortlist_capitals.csv": {"table_name": "spreisig_shortlist_capitals", "key_columns": ["ISO3"], "columns": []},
        "shortlist_curpop.csv": {"table_name": "spreisig_shortlist_curpop", "key_columns": ["Country Name"], "columns": []},
        "shortlist_gdppc.csv": {"table_name": "spreisig_shortlist_gdppc", "key_columns": ["Country Name"], "columns": []},
        "shortlist_languages.csv": {"table_name": "spreisig_shortlist_languages", "key_columns": ["ISO3"], "columns": []},
        "un_shortlist.csv": {"table_name": "spreisig_un_shortlist", "key_columns": ["ISO3"], "columns": []},
        "shortlist_economic": {"table_name": "spreisig_economic", "key_columns": ["Country Name"], "columns": []},
        "shortlist_non_economic": {"table_name": "spreisig_non_economic", "key_columns": ["ISO3"], "columns": []}
    }
    global_vars.data_dir = "data/"
    global_vars.json_dir = global_vars.data_dir+"json/"
    global_vars.help_dir = "help/"
    global_vars.add_records_file = global_vars.data_dir+"add_records.txt"
    global_vars.delete_records_file = global_vars.data_dir+"delete_records.txt"
    global_vars.missing_info_file = global_vars.data_dir+"missing_info.txt"

# Purpose: establishes an AWS session by parsing config file (S5-S3.conf) and setting
# up client and resources
def config_and_setup():
    # AWS access key id and secret access key information found in configuration file (S5-S3.conf)
    config = configparser.ConfigParser()
    config.read("S5-S3.conf")
    aws_access_key_id = config['default']['aws_access_key_id']
    aws_secret_access_key = config['default']['aws_secret_access_key']

    try:
        # Establish an AWS session
        session = boto3.Session(
            aws_access_key_id=aws_access_key_id,
            aws_secret_access_key=aws_secret_access_key
        )
        # Set up client and resources
        dynamodb_res = session.resource('dynamodb', region_name='ca-central-1')
        dynamodb_client = session.client('dynamodb', region_name='ca-central-1')
        return dynamodb_res, dynamodb_client

    except ClientError as e:
        if e.response['Error']['Code'] == 'EntityAlreadyExists':
            print("User already exists")
        else:
            print("Unexpected error: %s" % e)

# Purpose: iterates through data/ directory and converts each csv files to
# json, placing each converted json file into data/json/ directory. After
# all csv files have been converted to json files, create_tables() is called
# to create spreisig_economic and spreisig_non_economic tables containing organized
# information using the converted json files
# Params:
#   - dynamodb_res: high-level abstraction for AWS services requests
#   - dynamodb_client: low-level interface for AWS services requests
def build_tables(dynamodb_res, dynamodb_client):
    filenames = os.listdir(global_vars.data_dir)

    # Removing filenames within the data directory that are not csv files
    filenames.remove(global_vars.add_records_file.replace(global_vars.data_dir, ''))
    filenames.remove(global_vars.delete_records_file.replace(global_vars.data_dir, ''))
    filenames.remove(global_vars.missing_info_file.replace(global_vars.data_dir, ''))
    filenames.remove("json")
    filenames.remove("README.md")

    # Looping through each csv file within the data directory and calling build_json to
    # convert the csv file into a json file
    for filename in filenames:
        table_name = ("spreisig_"+filename).replace('.csv', '')
        build_json(table_name, global_vars.data_dir+filename)
    # Creating economic and non-economic tables
    create_table(dynamodb_res, dynamodb_client, "spreisig_economic")
    create_table(dynamodb_res, dynamodb_client, "spreisig_non_economic")

# Purpose: DRIVER
# Initializes global variables, establishes AWS session, builds economic and non-economic
# tables, and launches CLI for table manipulation and report production
def main():
    # Setting global variables, AWS configuration, and initial bulk creation of tables
    set_globals()
    dynamodb_res, dynamodb_client = config_and_setup()
    build_tables(dynamodb_res, dynamodb_client)

    # CLI
    print("\nWelcome to Sam's custom AWS CLI\nFor help command, type `help`\nTo stop CLI, type `quit`\n")
    while True:
        cli = input("> ").split()
        command = cli[0]
        args = cli[1:]

        if(command == "help"):
            cmd_help(args)

        elif(command == "create_table"):
            cmd_create_table(dynamodb_res, dynamodb_client, args)

        elif(command == "delete_table"):
            cmd_delete_table(dynamodb_client, args)

        elif(command == "add_data"):
            cmd_add_data()
            build_tables(dynamodb_res, dynamodb_client) # Rebuilding tables with updated csv files

        elif(command == "add_records"):
            cmd_add_record(dynamodb_res)

        elif(command == "delete_records"):
            cmd_delete_record(dynamodb_res)

        elif(command == "dump"):
            cmd_dump(dynamodb_res, dynamodb_client, args)

        elif(command == "build_report"):
            cmd_build_report(dynamodb_res, args)

        elif(command == "quit"):
            break

        else:
            print("Not a valid command. Enter `help` for a list of valid commands")

if __name__ == "__main__":
    main()


import os
import re
import sys
import tarfile

import tensorflow as tf

import model_parts as parts
from model_parts import variable

FLAGS = tf.app.flags.FLAGS

def layer(inputs, kernel_size, channel, stride):
    """
    unit layer of this model.

    :parma Tensor inputs: input tensor, which is batch Tensor.
    :param int kernel_size: convolution kernel size
    :param int channel: output channels
    :parma int stride: convolution stride
    :return: output of layer
    :rtype: Tensor
    """
    wd = 1e-4
    input_depth = inputs.get_shape()[-1]

    kernel = variable('weights', shape=[kernel_size, kernel_size, input_depth, channel],
                      init_type="xavier", wd=wd)

    conv = tf.nn.conv2d(inputs, kernel, [1, stride, stride, 1], padding='SAME')
    normalized = parts.batch_norm(conv)

    # pool1
    pool = tf.nn.max_pool(normalized, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1],
                           padding='SAME', name='pool')

    relu = tf.nn.relu(pool, name="relu")
    parts.activation_summary(relu)

    return relu

def inference(images):
    """
    builds the colorization model.

    :param Tenor images: batch tesnor of grayscale images. shape is [image_height, image_width, 1]
    :return: inferenced color image, which has shape [image_height, image_width, 3]
    :rtype: Tensor
    """
    features = [images]
    inputs = images

    # 1/4
    with tf.variable_scope('layer1') as scope:
        outputs = layer(inputs, kernel_size=3, channel=32, stride=2)
        layer_features = tf.image.resize_images(outputs, FLAGS.image_height, FLAGS.image_width)
        features.append(layer_features)

        inputs = outputs

    # 1/2 ** 3
    for idx_layer, channel in zip([2, 3, 4], [64, 64, 64]):
    #for idx_layer, channel in zip([2, 3], [64, 64]):
        layer_name = "layer{}".format(idx_layer)

        with tf.variable_scope(layer_name) as scope:
            outputs = layer(inputs, kernel_size=3, channel=channel, stride=1)
            #outputs = layer(inputs, kernel_size=3, channel=channel, stride=2)
            layer_features = tf.image.resize_images(outputs, FLAGS.image_height, FLAGS.image_width)
            features.append(layer_features)

            inputs = outputs

    # concate nate
    all_features = tf.concat(3, features, "feature_concat")

    with tf.variable_scope("generator") as scope:
        input_depth = all_features.get_shape()[-1]
        kernel = variable('weights', shape=[5, 5, input_depth, 3],
                          init_type="xavier", wd=1e-05)

        conv = tf.nn.conv2d(all_features, kernel, [1, 1, 1, 1], padding='SAME')
        bias = variable("bias", shape=[3], init_type="const", wd=None)
        color_map = tf.nn.bias_add(conv, bias)

    return color_map

def loss(inferenced, original):
    """
    calculates loss value.
    The loss value contains difference between colors and regularization terms.

    :param Tensor inferenced: inferenced colors
    :param Tensor original: original colors (pixel range [0,1])
    :return: the loss value.
    :rtype: Tensor
    """
    loss = tf.reduce_mean(tf.square(original - inferenced), name="raw_loss")
    #loss = tf.nn.l2_loss(original - inferenced) / (FLAGS.image_height*FLAGS.image_width*3)

    tf.add_to_collection('losses', loss)

    total_loss = tf.add_n(tf.get_collection('losses'), name='total_loss')

    return loss, total_loss

def add_loss_summaries(raw_loss, total_loss):
    """
    Add summaries for losses

    Generates moving average for all losses and associated summariefs for
    visualizing the performance of the network.

    :param Tensor raw_loss: tensor of loss value without regularization terms.
    :param Tensor total_loss: tensor of loss value with regularization terms.
    :return: op for generating moving averages of losses.
    """

    loss_averages = tf.train.ExponentialMovingAverage(0.95, name='avg')
    losses = tf.get_collection('losses')
    loss_averages_op = loss_averages.apply([raw_loss, total_loss])

    for l in [raw_loss, total_loss]:
        tf.scalar_summary(l.op.name +' (raw)', l)
        tf.scalar_summary(l.op.name, loss_averages.average(l))

    return loss_averages_op


import math
import re
import sys
from typing import List, Optional  # pylint: disable=unused-import

from gcp_variant_transforms.beam_io import vcfio

# Prefix to use when the first character of the field name is not [a-zA-Z]
# as required by BigQuery.
_FALLBACK_FIELD_NAME_PREFIX = 'field_'

# A big number to represent infinite float values. The division by 10 is to
# prevent unintentional overflows when doing subsequent operations.
_INF_FLOAT_VALUE = sys.float_info.max / 10
_DEFAULT_NULL_NUMERIC_VALUE_REPLACEMENT = -2 ^ 31

class SchemaSanitizer():
  """Class to sanitize BigQuery schema according to BigQuery restrictions."""

  @staticmethod
  def get_sanitized_string(input_str):
    # type: (str) -> unicode
    """Returns a unicode as BigQuery API does not support UTF-8 strings."""
    return _decode_utf8_string(input_str)

  @staticmethod
  def get_sanitized_field_name(field_name):
    # type: (str) -> str
    """Returns the sanitized field name according to BigQuery restrictions.

    BigQuery field names must follow `[a-zA-Z][a-zA-Z0-9_]*`. This method
    converts any unsupported characters to an underscore. Also, if the first
    character does not match `[a-zA-Z]`, it prepends
    `_FALLBACK_FIELD_NAME_PREFIX` to the name.

    Args:
      field_name: Name of the field to sanitize.
    Returns:
      Sanitized field name with unsupported characters replaced with an
        underscore. It also prepends the name with `_FALLBACK_FIELD_NAME_PREFIX`
        if the first character does not match `[a-zA-Z]`.
    """
    assert field_name  # field_name must not be empty by this stage.
    if not re.match('[a-zA-Z]', field_name[0]):
      field_name = _FALLBACK_FIELD_NAME_PREFIX + field_name
    return re.sub('[^a-zA-Z0-9_]', '_', field_name)

class FieldSanitizer():
  """Class to sanitize field values according to BigQuery restrictions."""

  def __init__(self, null_numeric_value_replacement):
    # type: (Optional[int]) -> None
    """Initializes a `BigQueryFieldSanitizer`.

    Args:
      null_numeric_value_replacement: Value to use instead of null for
        numeric (float/int/long) lists. For instance, [0, None, 1] will become
        [0, `null_numeric_value_replacement`, 1].
    """
    self._null_numeric_value_replacement = (
        null_numeric_value_replacement or
        _DEFAULT_NULL_NUMERIC_VALUE_REPLACEMENT)

  def get_sanitized_field(self, field):
    # type: (Any) ->  Any
    """Returns sanitized field according to BigQuery restrictions.

    This method only sanitizes lists and strings. It returns the same `field`
    for all other types (including None).

    For lists, null values are replaced with reasonable defaults since the
    BigQuery API does not allow null values in lists (note that the entire
    list is allowed to be null). For instance, [0, None, 1] becomes
    [0, `null_numeric_value_replacement`, 1].
    Null value replacements are:
      - `False` for bool.
      - `.` for string.
      - `null_numeric_value_replacement` for float/int/long.

    For strings, it returns its unicode representation. The BigQuery API does
    not support strings that are UTF-8 encoded.

    Args:
      field: Field to sanitize. It can be of any type.

    Raises:
      ValueError: If the field could not be sanitized (e.g. unsupported types in
        lists).
    """
    if not field:
      return field
    if isinstance(field, (str, bytes)):
      return self._get_sanitized_string(field)
    elif isinstance(field, float):
      return self._get_sanitized_float(field)
    elif isinstance(field, list):
      return self._get_sanitized_list(field)
    else:
      return field

  def _get_sanitized_list(self, input_list):
    # type: (List) -> List
    """Returns sanitized list according to BigQuery restrictions.

    Null values are replaced with reasonable defaults since the
    BigQuery API does not allow null values in lists (note that the entire
    list is allowed to be null). For instance, [0, None, 1] becomes
    [0, `null_numeric_value_replacement`, 1].
    Null value replacements are:
      - `False` for bool.
      - `.` for string.
      - `null_numeric_value_replacement` for float/int/long.
    Lists that contain strings are also sanitized according to the
    `_get_sanitized_string` method.

    Args:
      input_list: List to sanitize.

    Raises:
      ValueError: If a list contains unsupported values. Supported types are
        basestring, bool, int, long, and float.
    """
    null_replacement_value = None
    for i in input_list:
      if i is None:
        continue
      if isinstance(i, str):
        null_replacement_value = vcfio.MISSING_FIELD_VALUE
      elif isinstance(i, bool):
        null_replacement_value = False
      elif isinstance(i, (int, float)):
        null_replacement_value = self._null_numeric_value_replacement
      else:
        raise ValueError('Unsupported value for input: %s' % str(i))
      break  # Assumption is that all fields have the same type.
    if null_replacement_value is None:  # Implies everything was None.
      return []
    sanitized_list = []
    for i in input_list:
      if i is None:
        i = null_replacement_value
      elif isinstance(i, (str, bytes)):
        i = self._get_sanitized_string(i)
      elif isinstance(i, float):
        sanitized_float = self._get_sanitized_float(i)
        i = (sanitized_float if sanitized_float is not None
             else null_replacement_value)
      sanitized_list.append(i)
    return sanitized_list

  def _get_sanitized_float(self, input_float):
    """Returns a sanitized float for BigQuery.

    This method replaces INF and -INF with positive and negative numbers with
    huge absolute values, and replaces NaN with None. It returns the same value
    for all other values.
    """
    if input_float == float('inf'):
      return _INF_FLOAT_VALUE
    elif input_float == float('-inf'):
      return -_INF_FLOAT_VALUE
    elif math.isnan(input_float):
      return None
    else:
      return input_float

  def _get_sanitized_string(self, input_str):
    # type: (Any) -> str
    """Returns a unicode as BigQuery API does not support UTF-8 strings."""
    return _decode_utf8_string(input_str)

def _decode_utf8_string(input_str):
  # type: (Any) -> str
  try:
    return (input_str if isinstance(input_str, str)
            else input_str.decode('utf-8'))
  except UnicodeDecodeError as e:
    raise ValueError('input_str is not UTF-8: %s ' % (input_str)) from e


from keras.models import Model
from keras.layers import Input
from entertrain import backend as E

class ExtremeLearningMachine:

    def __init__(self,
                 feature_extractor: Model,
                 predictor: Model,
                 solver="pseudoinverse"):
        self.feature_extractor = feature_extractor
        self.predictor = predictor
        self.full_model = None  # type: Model
        self._predictor_bias = self.predictor.get_weights()[-1]
        self.solver = {"pseudoinverse": self._solve_pseudoinverse,
                       "covariance": self._solve_covariance}[solver]
        self._build_full_model()

    def _build_full_model(self):
        model_input = Input(batch_shape=self.feature_extractor.input_shape)
        model_output = self.predictor(self.feature_extractor(model_input))
        self.full_model = Model(inputs=model_input, outputs=model_output)

    @classmethod
    def from_single_model(cls, model: Model, solver="pseudoinverse"):
        fe_input = Input(batch_shape=model.input_shape)
        fe_out = model.layers[-2](fe_input)
        feature_extractor = Model(inputs=fe_input, outputs=fe_out)
        pr_in = Input(batch_shape=model.layers[-2].output_shape)
        pr_out = model(pr_in)
        predictor = Model(inputs=pr_in, outputs=pr_out)
        return cls(feature_extractor, predictor, solver)

    def _solve_pseudoinverse(self, Z, Y):
        W = E.dot(E.pinv(Z), Y)
        self.predictor.set_weights([W, self._predictor_bias])

    def _solve_covariance(self, Z, Y):
        A = E.cov(Z.T)
        B = E.cov(Z.T, Y.T)
        W = E.dot(E.inv(A), B)
        self.predictor.set_weights([W, self._predictor_bias])

    def train_on_batch(self, x, y):
        z = self.feature_extractor.predict(x)
        self.solver(z, y)

    def predict(self, x):
        z = self.feature_extractor.predict(x)
        return self.predictor.predict(z)

    def evaluate(self, x=None, y=None, batch_size=None, verbose=1,
                 sample_weight=None, steps=None, loss=None, **kwargs):
        if not self.full_model._is_compiled:
            if loss is None:
                raise RuntimeError("Model needs to be built for evaluation, please supply a loss!")
            self.full_model.compile(optimizer="sgd", loss=loss, **kwargs)
        return self.full_model.evaluate(x, y, batch_size, verbose, sample_weight, steps)


from .settings import *

TEST_DISCOVER_PATTERN = "test_*"
TEST_RUNNER = 'django_test_exclude.runners.ExcludeTestSuiteRunner'
TEST_EXCLUDE = (
    'smart_selects',
    'django.contrib',
)

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": ":memory:",
        "USER": "",
        "PASSWORD": "",
        "HOST": "",
        "PORT": "",
    },
}

TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    './templates',
)


'''
****************************************************
File: discretePolicyTranslator.py
Version: 1.0
Written By: Luke Burks
May 2016

Input: File name, current pose
Output: Goal pose

The discretePolicyTranslator class is designed to
process a robot position and use a pre-generated
pomdp policy file to output the desired goal pose.
The current version creates a fake belief vector
from the currnet pose. Future implementations will
allow for the input of a true belief.

Use:
Initialize with the file name containing the policy,
represented by alpha vectors with the desired
cardinal action as the last element.
The desired pose is generated by the getNextPose()
function with the current pose as an argument.

Version History:
1.0.0: initial release
1.0.1: allowed fake belief creation with floats as
well as ints
1.0.2: getNextPose() now returns [x,y,z,theta]

****************************************************
'''

__author__ = "Luke Burks"
__copyright__ = "Copyright 2016, Cohrint"
__license__ = "GPL"
__version__ = "1.0.2"
__maintainer__ = "Luke Burks"
__email__ = "clburks9@gmail.com"
__status__ = "Development"

import random
import numpy as np

class discretePolicyTranslator():

	def __init__(self,fileName=None):
		if(fileName == None):
			self.alphas = self.readAlphas("fakealphas1.txt");
		else:
			self.alphas = self.readAlphas(fileName);

	def fakeBelief(self,x,y):
		arr = [0]*16;
		arr[int(round(y))*4+int(round(x))] = 1;
		return arr;

	def readAlphas(self,fileName):
		file = open(fileName,"r");
		lines = np.loadtxt(fileName,delimiter = " ");
		return lines;

	def getAction(self,alphas,belief):
		bestValue = 0;
		bestAction = 0;

		for i in range(0,len(alphas)):
			total = 0;
			for j in range(0,len(belief)):
				total = total + belief[j]*alphas[i][j];
			if(total>bestValue):
				bestValue = total;
				bestAction = alphas[i][len(belief)]
		return bestAction;

	def printMap(self,x,y):
		map1 = "";
		for i in range(3,-1,-1):
			for j in range(0,4):
				if(j == x and i == y):
					map1 = map1+'X';
				else:
					map1 = map1+"-";
			map1 = map1+"\n";
		print(map1);

	def getCurrentPose(self):
		x = 0;
		y = 0;
		z = 0;
		return [x,y];

	def getNextPose(self,pose):
		x = int(pose[0]);
		y = int(pose[1]);
		belief = self.fakeBelief(x,y);
		action = self.getAction(self.alphas,belief);
		orient = 0;

		if(action == 0):
			destX = x-1;
			destY = y;
			actVerb = "Left";
			orient = 180;
		elif(action == 1):
			destX = x+1;
			destY = y;
			actVerb = "Right";
			orient = 0;
		elif(action == 2):
			destX = x;
			destY = y+1;
			actVerb = "Up";
			orient = 90;
		elif(action == 3):
			destX = x;
			destY = y-1;
			actVerb = "Down";
			orient = -90;
		else:
			destX = x;
			destY = y;
			actVerb = "Wait";

		return [destX,destY,0,orient];

	def simulate(self,T):
		#grab robots position
		#x = random.randrange(0,4);
		#y = random.randrange(0,4);
		if(T == 0):
			x = 0;
			y = 0;
			alphas = self.readAlphas("fakealphas1.txt");
		if(T == 1):
			x = 1;
			y = 2;
			alphas = self.readAlphas("fakealphas2.txt");

		action = 0;

		print("Origin: [" + str(x) + "," + str(y) + "]");
		self.printMap(x,y);

		while(action != 4):
			belief = self.fakeBelief(x,y);
			action = self.getAction(alphas,belief);
			destX = 0;
			destY = 0;
			actVerb = "";

			if(action == 0):
				destX = x-1;
				destY = y;
				actVerb = "Left";
			elif(action == 1):
				destX = x+1;
				destY = y;
				actVerb = "Right";
			elif(action == 2):
				destX = x;
				destY = y+1;
				actVerb = "Up";
			elif(action == 3):
				destX = x;
				destY = y-1;
				actVerb = "Down";
			else:
				destX = x;
				destY = y;
				actVerb = "Wait";

			print("Action: " + actVerb);
			print("Destination: [" + str(destX) + "," + str(destY) + "]");
			self.printMap(destX,destY);
			x = destX;
			y = destY;

	def runOnce(self):
		x = random.randrange(0,4);
		y = random.randrange(0,4);
		belief = self.fakeBelief(x,y);
		alphas = self.readAlphas("fakealphas1.txt");
		action = self.getAction(alphas,belief);

		if(action == 0):
			destX = x-1;
			destY = y;
			actVerb = "Left";
		elif(action == 1):
			destX = x+1;
			destY = y;
			actVerb = "Right";
		elif(action == 2):
			destX = x;
			destY = y+1;
			actVerb = "Up";
		elif(action == 3):
			destX = x;
			destY = y-1;
			actVerb = "Down";
		else:
			destX = x;
			destY = y;
			actVerb = "Wait";
		print("Origin: [" + str(x) + "," + str(y) + "]");
		print("Action: " + actVerb);
		print("Destination: [" + str(destX) + "," + str(destY) + "]");

if __name__ == "__main__":

	fileName = "fakealphas1.txt";
	pol = discretePolicyTranslator(fileName);
	#pol.simulate(1);

	post = pol.getNextPose([2.5,2.1,2]);
	print(post);


from subprocess import *
import yaml
import io
import logging
import os
import os.path

CONFIG_FILE='/opt/config.yaml'
SYSLOG_FIFO='/var/log/syslog-fifo'

def main():
  global config

  logging.getLogger().setLevel(logging.INFO)
  logging.info('Reading config: %s' % CONFIG_FILE)
  with open(CONFIG_FILE, 'r') as f:
    config = yaml.load(f)

  spawn_rsyslogd()
  base_postfix_config()
  configure_postscreen()
  configure_sasl()
  configure_virtual_domains()
  spawn_postsrsd()
  spawn_postfix()

  # Wait for something to exit.  As soon as some child process exits we exit
  os.wait()

def spawn_rsyslogd():
  logging.info('Starting rsyslogd')
  if os.path.exists(SYSLOG_FIFO):
    call(['rm', SYSLOG_FIFO])
  if os.path.exists('/var/run/rsyslogd.pid'):
    call(['rm', '/var/run/rsyslogd.pid'])
  check_call(['mkfifo', SYSLOG_FIFO])
  with open('/etc/rsyslog.conf', 'w') as f:
    f.write(r"""
$ModLoad imuxsock
$template TraditionalFormatWithPRI,"%timegenerated:::date-rfc3339% %pri-text% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n"
$WorkDirectory /var/spool/rsyslog
*.* |/var/log/syslog-fifo;TraditionalFormatWithPRI
""".strip())
  Popen(['cat', SYSLOG_FIFO])
  Popen(['rsyslogd', '-n'])

def base_postfix_config():
  # Set up the spool directory so it hass all of the right sub-dirs.
  check_call(['postfix', 'post-install', 'create-missing'])

  # Turn off all the chrooting in postfix. This only works for postfix v2.11+.
  # We grab that from wheezy-backports.
  check_call(['postconf', '-F', '*/*/chroot = n'])

  # Set up a virtual map (placeholder for now)
  check_call(['postconf', '-e', 'myhostname=%s' % config['ptr_hostname']])
  check_call(['postconf', '-e', 'local_recipient_maps='])
  check_call(['postconf', '-e', 'mydomain=localdomain'])
  check_call(['postconf', '-e', 'mydestination='])
  check_call(['postconf', '-e', ('message_size_limit = %d' % (50*1024*1024,))])

  # Enable TLS for smtpd
  check_call(['postconf', '-e', 'smtpd_tls_security_level=may'])
  check_call(['postconf', '-e', 'smtpd_tls_auth_only=yes'])

  # Configure the submission service (587)
  check_call(['postconf', '-Me', 'submission/inet = submission inet n - n - - smtpd'])
  check_call(['postconf', '-Pe', 'submission/inet/syslog_name=postfix/submission'])
  check_call(['postconf', '-Pe', 'submission/inet/smtpd_tls_security_level=encrypt'])
  check_call(['postconf', '-Pe', 'submission/inet/smtpd_sasl_auth_enable=yes'])
  check_call(['postconf', '-Pe', 'submission/inet/smtpd_reject_unlisted_recipient=no'])
  check_call(['postconf', '-Pe', 'submission/inet/smtpd_recipient_restrictions='])
  check_call(['postconf', '-Pe', 'submission/inet/smtpd_relay_restrictions=permit_sasl_authenticated,reject'])
  check_call(['postconf', '-Pe', 'submission/inet/milter_macro_daemon_name=ORIGINATING'])

def configure_postscreen():
  if not config['postscreen']['enable']:
    return

  check_call(['postconf', '-MX', 'smtp/inet'])
  check_call(['postconf', '-Me', 'smtpd/pass = smtpd pass - - n - - smtpd'])
  check_call(['postconf', '-Me', 'smtp/inet = smtp inet n - n - 1 postscreen'])
  check_call(['postconf', '-Me', 'tlsproxy/unix = tlsproxy unix - - n - 0 tlsproxy'])
  check_call(['postconf', '-Me', 'dnsblog/unix = dnsblog unix - - n - 0 dnsblog'])

  # Before-220 tests
  check_call(['postconf', '-e', 'postscreen_dnsbl_action = enforce'])
  check_call(['postconf', '-e', 'postscreen_dnsbl_threshold = 2'])
  check_call(['postconf', '-e', 'postscreen_dnsbl_sites = zen.spamhaus.org*2 bl.spamcop.net*1 b.barracudacentral.org*1 swl.spamhaus.org*-3'])

  check_call(['postconf', '-e', 'postscreen_greet_action = enforce'])

  if config['postscreen']['enable_slow_checks']:
    # After-220 tests -- these can cause significant delays so are disabled for now.
    check_call(['postconf', '-e', 'postscreen_bare_newline_action = enforce'])
    check_call(['postconf', '-e', 'postscreen_bare_newline_enable = yes'])
    check_call(['postconf', '-e', 'postscreen_non_smtp_command_enable = yes'])
    check_call(['postconf', '-e', 'postscreen_pipelining_enable = yes'])

def configure_sasl():
  check_call(['postconf', '-e', 'smtpd_sasl_type = cyrus'])
  check_call(['postconf', '-e', 'smtpd_sasl_auth_enable = yes'])
  check_call(['postconf', '-e', 'broken_sasl_auth_clients = yes'])
  check_call(['adduser', 'postfix', 'sasl'])
  with open('/etc/postfix/sasl/smtpd.conf', 'w') as f:
    f.write("""
pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: PLAIN
""".strip())

  for (domain, domain_info) in config['virtual_domains'].items():
    for account in domain_info['accounts']:
      logging.info("Creating SASL account for %s@%s" % (account['name'], domain))
      cmd = ['saslpasswd2', '-p', '-c', '-u', domain, account['name']]
      p = Popen(cmd, stdin=PIPE)
      p.communicate(input=account['password'])
      retcode = p.poll()
      if retcode:
        raise CalledProcessError(retcode, cmd)

def get_forward_list(account):
  forward = account['forward']
  if isinstance(forward, basestring):
    forward = [forward]
  return forward

def configure_virtual_domains():
  domains = config['virtual_domains'].keys()
  check_call(['postconf', '-e', 'virtual_alias_domains=%s' % ' '.join(domains)])
  check_call(['postconf', '-e', 'virtual_alias_maps=hash:/etc/postfix/virtual regexp:/etc/postfix/virtual.regexp'])
  with open('/etc/postfix/virtual', 'w') as f:
    for (domain, domain_info) in config['virtual_domains'].items():
      for account in domain_info['accounts']:
        def forward(alias):
          forward = ' '.join(get_forward_list(account))
          logging.info("Forwarding %s@%s to %s" % (alias, domain, forward))
          f.write('%s@%s %s\n' % (alias, domain, account['forward']))
        forward(account['name'])
        for alias in account.get('aliases', []):
          forward(alias)
      f.write('\n')
  check_call(['postmap', '/etc/postfix/virtual'])

  with open('/etc/postfix/virtual.regexp', 'w') as f:
    for (domain, domain_info) in config['virtual_domains'].items():
      for account in domain_info['accounts']:
        if account.get('dot_plus_rewrite', True):
          name = account['name']
          forwards = ' '.join(["%s+$3@%s" % tuple(forward.split('@')) for forward in get_forward_list(account)])
          logging.info("Forwarding %s.*@%s to %s" % (name, domain, forwards))
          f.write('/^%s((\\+|\\.)([-a-zA-Z0-9_]+))?@%s$/ %s\n' % (name, domain, forwards))

  ai_fn = '/etc/postfix/access_inbound'
  check_call(['postconf', '-e', 'smtpd_sender_restrictions=check_recipient_access hash:%s' % ai_fn])
  with open(ai_fn, 'w') as f:
    for (domain, domain_info) in config['virtual_domains'].items():
      for blackhole in domain_info.get('blackholes', []):
        bh_email = "%s@%s" % (blackhole, domain)
        logging.info("Blackholeing %s" % bh_email)
        f.write('%s REJECT\n' % bh_email)
  check_call(['postmap', ai_fn])

def spawn_postsrsd():
  if not config['srs']['enable']:
    return

  check_call(['postconf', '-e', 'sender_canonical_maps = tcp:127.0.0.1:10001'])
  check_call(['postconf', '-e', 'sender_canonical_classes = envelope_sender'])
  check_call(['postconf', '-e', 'recipient_canonical_maps = tcp:127.0.0.1:10002'])
  check_call(['postconf', '-e', 'recipient_canonical_classes = envelope_recipient,header_recipient'])

  with open('/opt/srs.secret', 'w') as f:
    f.write(config['srs']['srs_secret'])

  exclude_domains=",".join(config['virtual_domains'].keys())

  cmd = ['postsrsd-1.2/build/postsrsd', '-s/opt/srs.secret', '-upostfix',
         '-d%s' % config['srs']['srs_domain'],
         '-X%s' % exclude_domains]
  logging.info("Running postsrsd: %s", repr(cmd))
  Popen(cmd)

def spawn_postfix():
  # Start up the postfix master in the foreground.  Normally this happens with:
  #   /etc/init.d/postfix start ->
  #   /usr/sbin/postfix ->
  #   /usr/lib/postfix/postfix-script ->
  #   /usr/lib/postfix/master
  #
  # The only thing I can figure that *really* matters here is that we change the
  # working directory to the spool directory.  I might be missing some env
  # variables :/
  os.chdir('/var/spool/postfix')
  cmd = ['/usr/lib/postfix/master', '-d']
  logging.info("Running postfix master: %s", repr(cmd))
  Popen(cmd)

if __name__ == "__main__":
  main()


from musixmatch import Musixmatch

class MusiXMatchAPI:

    def __init__(self, key):
        self.MM = Musixmatch(key)
        self.track_not_found = 0
        self.total_count = 0
        self.error_codes = []

    def get_song_data(self, artist_name: str, track_title: str) -> dict:
        """
        Gets song data from musixmatch api. Using the free API means
        access to only 30% of the lyrics body, so that's a no go. We
        can still use the API to augment our datasets with the
        album name, release date, and genres.

        :param artist_name: name of track artist (str)
        :param track_title: name of track title (str)
        :return: dict of form {
            "Album_Name": str,
            "Release_date": "yyyy-MM-dd,
            "Genres": list of strs
        }
        """
        self.total_count += 1
        result = self.MM.matcher_track_get(q_artist=artist_name,
                                           q_track=track_title)

        result = result["message"]
        if result["header"]["status_code"] != 200 or \
                        result["body"]["track"]["has_lyrics"] != 1:
            self.track_not_found += 1
            self.error_codes.append(result["header"]["status_code"])
            return {}

        result = result["body"]["track"]
        return {
            "Album_Name": result["album_name"],
            "Release_Date": result["first_release_date"].split("T")[0],
            "Genres": {
                "Names": [x["music_genre"]["music_genre_name"] for x
                       in result["primary_genres"]["music_genre_list"]],
                "Source": "MusixMatch"
            }
        }

    def get_usage_report(self) -> dict:
        """
        Returns usage report of the spotify scraperr

        :return: dict of form {
            "Musixmatch_Usage_Reports": {
                "Missed_Searches": int,
                "Total_Attempts": int
            }
        }
        """
        usage = {
            "Musixmatch_Usage_Reports": {
                "Missed_Searches": self.track_not_found,
                "Total_Attempts": self.total_count
            }
        }
        return usage

    def clear_usage_stats(self):
        self.track_not_found = 0
        self.total_count = 0

if __name__ == "__main__":

    import json
    import time
    from scraping import keys
    k = keys.Keys()

    MM = MusiXMatchAPI(k.musixmatch_key)

    songs = {
        "AC/DC": "Thunderstruck",
        "Twenty One Pilots": "Bandito",
        "BROCKHAMPTON": "BERLIN",
        "Eric Church": "The Snake",
        "D'Angelo": "Sugah Daddy",
        "Bad Artist Name": "Bad Song Name"
    }

    for key, val in songs.items():
        print("Artist:", key, " : ", "Track:", val)
        info = MM.get_song_data(key, val,)
        json_dump = json.dumps(info, indent=4)
        print(json_dump)
        print()
        time.sleep(2)

    report = MM.get_usage_report()
    json_dump = json.dumps(report, indent=4)
    print(json_dump)
    print()


import functools
from typing import Any, Callable
import numpy as np

from flax import linen as nn
import jax
from jax import lax
from jax import random
import jax.numpy as jnp

class NerfMLP(nn.Module):
  """A Nerf MLP."""
  net_depth: int = 8  # The depth of the first part of MLP.
  net_width: int = 256  # The width of the first part of MLP.
  net_depth_condition: int = 1  # The depth of the second part of MLP.
  net_width_condition: int = 128  # The width of the second part of MLP.
  net_activation: Callable[..., Any] = nn.relu  # The activation function.
  skip_layer: int = 4  # The layer to add skip layers to.
  num_rgb_channels: int = 3  # The number of RGB channels.
  num_sigma_channels: int = 1  # The number of sigma channels.

  @nn.compact
  def __call__(self, x, condition=None):
    """Evaluate the MLP.

    Args:
      x: jnp.ndarray(float32), [batch, num_samples, feature], points.
      condition: jnp.ndarray(float32), [batch, feature], if not None, this
        variable will be part of the input to the second part of the MLP
        concatenated with the output vector of the first part of the MLP. If
        None, only the first part of the MLP will be used with input x. In the
        original paper, this variable is the view direction.

    Returns:
      raw_rgb: jnp.ndarray(float32), with a shape of
           [batch, num_samples, num_rgb_channels].
      raw_sigma: jnp.ndarray(float32), with a shape of
           [batch, num_samples, num_sigma_channels].
    """
    feature_dim = x.shape[-1]
    num_samples = x.shape[1]
    x = x.reshape([-1, feature_dim])
    dense_layer = functools.partial(
        nn.Dense, kernel_init=jax.nn.initializers.glorot_uniform())
    inputs = x
    for i in range(self.net_depth):
      x = dense_layer(self.net_width)(x)
      x = self.net_activation(x)
      if i % self.skip_layer == 0 and i > 0:
        x = jnp.concatenate([x, inputs], axis=-1)
    raw_sigma = dense_layer(self.num_sigma_channels)(x).reshape(
        [-1, num_samples, self.num_sigma_channels])

    if condition is not None:
      # Output of the first part of MLP.
      bottleneck = dense_layer(self.net_width)(x)
      # Broadcast condition from [batch, feature] to
      # [batch, num_samples, feature] since all the samples along the same ray
      # have the same viewdir.

      # Collapse the [batch, num_samples, feature] tensor to
      # [batch * num_samples, feature] so that it can be fed into nn.Dense.
      condition = condition.reshape([-1, condition.shape[-1]])
      x = jnp.concatenate([bottleneck, condition], axis=-1)
      # Here use 1 extra layer to align with the original nerf model.
      for i in range(self.net_depth_condition):
        x = dense_layer(self.net_width_condition)(x)
        x = self.net_activation(x)
    raw_rgb = dense_layer(self.num_rgb_channels)(x).reshape(
        [-1, num_samples, self.num_rgb_channels])
    return raw_rgb, raw_sigma

class MLP(nn.Module):
  """A simple MLP."""
  net_depth: int = 8  # The depth of the first part of MLP.
  net_width: int = 256  # The width of the first part of MLP.
  net_depth_condition: int = 1  # The depth of the second part of MLP.
  net_width_condition: int = 128  # The width of the second part of MLP.
  net_activation: Callable[..., Any] = nn.relu  # The activation function.
  skip_layer: int = 4  # The layer to add skip layers to.
  num_out_channels: int = 1  # The number of sigma channels.
  output_init: Callable = jax.nn.initializers.xavier_uniform()

  @nn.compact
  def __call__(self, x, condition=None):
    """Evaluate the MLP.

    Args:
      x: jnp.ndarray(float32), [batch, num_samples, feature], points.
      condition: jnp.ndarray(float32), [batch, feature], if not None, this
        variable will be part of the input to the second part of the MLP
        concatenated with the output vector of the first part of the MLP. If
        None, only the first part of the MLP will be used with input x. In the
        original paper, this variable is the view direction.

    Returns:
      raw_out: jnp.ndarray(float32), with a shape of
           [batch, num_samples, num_out_channels].
    """
    feature_dim = x.shape[-1]
    num_samples = x.shape[1]
    x = x.reshape([-1, feature_dim])
    dense_layer = functools.partial(
        nn.Dense, kernel_init=jax.nn.initializers.xavier_uniform())
    inputs = x
    for i in range(self.net_depth):
      x = dense_layer(self.net_width)(x)
      x = self.net_activation(x)
      if i % self.skip_layer == 0 and i > 0:
        x = jnp.concatenate([x, inputs], axis=-1)
    if condition is not None:
      condition = condition.reshape([-1, condition.shape[-1]])
      x = jnp.concatenate([x, condition], axis=-1)
      for i in range(self.net_depth_condition):
        x = dense_layer(self.net_width_condition)(x)
        x = self.net_activation(x)
    raw_out = nn.Dense(self.num_out_channels, kernel_init=self.output_init)(x).reshape(
        [-1, num_samples, self.num_out_channels])

    return raw_out

def cast_rays(z_vals, origins, directions):
  return origins[..., None, :] + z_vals[..., None] * directions[..., None, :]

# def sample_along_rays(key, origins, directions, num_samples, near, far,
#                       randomized, lindisp):
#   """Stratified sampling along the rays.

#   Args:
#     key: jnp.ndarray, random generator key.
#     origins: jnp.ndarray(float32), [batch_size, 3], ray origins.
#     directions: jnp.ndarray(float32), [batch_size, 3], ray directions.
#     num_samples: int.
#     near: float, near clip.
#     far: float, far clip.
#     randomized: bool, use randomized stratified sampling.
#     lindisp: bool, sampling linearly in disparity rather than depth.

#   Returns:
#     z_vals: jnp.ndarray, [batch_size, num_samples], sampled z values.
#     points: jnp.ndarray, [batch_size, num_samples, 3], sampled points.
#   """
#   batch_size = origins.shape[0]

#   t_vals = jnp.linspace(0., 1., num_samples)
#   if lindisp:
#     t_vals = 1. / (1. / near * (1. - t_vals) + 1. / far * t_vals)
#   else:
#     t_vals = near * (1. - t_vals) + far * t_vals

#   if randomized:
#     mids = 0.5 * (t_vals[..., 1:] + t_vals[..., :-1])
#     upper = jnp.concatenate([mids, t_vals[..., -1:]], -1)
#     lower = jnp.concatenate([t_vals[..., :1], mids], -1)
#     t_rand = random.uniform(key, [batch_size, num_samples])
#     t_vals = lower + (upper - lower) * t_rand
#   else:
#     # Broadcast t_vals to make the returned shape consistent.
#     t_vals = jnp.broadcast_to(t_vals[None, ...], [batch_size, num_samples])

#   coords = cast_rays(t_vals, origins, directions)
#   return t_vals, coords

def pos_enc(x, min_deg, max_deg, legacy_posenc_order=False, amp=1.0):
  """Cat x with a positional encoding of x with scales 2^[min_deg, max_deg-1].

  Instead of computing [sin(x), cos(x)], we use the trig identity
  cos(x) = sin(x + pi/2) and do one vectorized call to sin([x, x+pi/2]).

  Args:
    x: jnp.ndarray, variables to be encoded. Note that x should be in [-pi, pi].
    min_deg: int, the minimum (inclusive) degree of the encoding.
    max_deg: int, the maximum (exclusive) degree of the encoding.
    legacy_posenc_order: bool, keep the same ordering as the original tf code.

  Returns:
    encoded: jnp.ndarray, encoded variables.
  """
  if min_deg == max_deg:
    return x
  scales = jnp.array([2**i for i in range(min_deg, max_deg)])
  if legacy_posenc_order:
    xb = x[..., None, :] * scales[:, None]
    four_feat = jnp.reshape(
        jnp.sin(jnp.stack([xb, xb + 0.5 * jnp.pi], -2)),
        list(x.shape[:-1]) + [-1])
  else:
    xb = jnp.reshape((x[..., None, :] * scales[:, None]),
                     list(x.shape[:-1]) + [-1])
    four_feat = jnp.sin(jnp.concatenate([xb, xb + 0.5 * jnp.pi], axis=-1))
  return jnp.concatenate([x] + [amp * four_feat], axis=-1)

# Reference: https://github.com/google/nerfies/blob/1a38512214cfa14286ef0561992cca9398265e13/nerfies/modules.py#L231
def cosine_easing_window(min_freq_log2, max_freq_log2, num_bands, alpha):
  """Eases in each frequency one by one with a cosine.
  This is equivalent to taking a Tukey window and sliding it to the right
  along the frequency spectrum.
  Args:
    min_freq_log2: the lower frequency band.
    max_freq_log2: the upper frequency band.
    num_bands: the number of frequencies.
    alpha: will ease in each frequency as alpha goes from 0.0 to num_freqs.
  Returns:
    A 1-d numpy array with num_sample elements containing the window.
  """
  if max_freq_log2 is None:
    max_freq_log2 = num_bands - 1.0
  bands = jnp.linspace(min_freq_log2, max_freq_log2, num_bands)
  x = jnp.clip(alpha - bands, 0.0, 1.0)
  return 0.5 * (1 + jnp.cos(jnp.pi * x + jnp.pi))

def annealed_pos_enc(x, min_deg, max_deg, alpha, amp=1.0):
  if min_deg == max_deg:
    return x
  scales = jnp.array([2**i for i in range(min_deg, max_deg)])

  xb = x[..., None, :] * scales[:, None]  # [batch, sample, num_deg, channel]
  window = cosine_easing_window(min_deg, max_deg - 1, len(scales), alpha)[:, None]  # [num_deg, 1]
  four_feat = jnp.reshape(jnp.concatenate([jnp.sin(xb) * window, jnp.sin(xb + 0.5 * jnp.pi) * window], axis=-1),
                          list(x.shape[:-1]) + [-1])  # [batch, sample, channel]
  return amp * four_feat

def volumetric_rendering(rgb, density, t_vals, dirs, white_bkgd, rgb_bkgd, mask_bbox=None):
  """Volumetric Rendering Function.

  Args:
    rgb: jnp.ndarray(float32), color, [batch_size, num_samples, 3]
    density: jnp.ndarray(float32), sigma, [batch_size, num_samples, 1].
    t_vals: jnp.ndarray(float32), [batch_size, num_samples].
    dirs: jnp.ndarray(float32), [batch_size, 3].
    white_bkgd: bool.

  Returns:
    comp_rgb: jnp.ndarray(float32), [batch_size, 3].
    disp: jnp.ndarray(float32), [batch_size].
    acc: jnp.ndarray(float32), [batch_size].
    weights: jnp.ndarray(float32), [batch_size, num_samples]
  """
  eps = 1e-10
  # NOTE(bkgd): To account for boundary term, narrow down the last delta
  t_dists = jnp.concatenate([
      t_vals[..., 1:] - t_vals[..., :-1],
      jnp.broadcast_to([1e-3], t_vals[..., :1].shape)
  ], -1)
  # NOTE(eikonal)
  delta = t_dists * jnp.linalg.norm(dirs, axis=-1)
  # Note that we're quietly turning density from [..., 0] to [...].
  density_delta = density[..., 0] * delta

  # NOTE(voxelize)
  if mask_bbox is not None:
    density_delta *= mask_bbox

  # Check beta/sparsity
  # if mask is not None:
  #   mask = mask * ((1 - jnp.exp(-density_delta)) > 0.5)
  # mask = (1 - jnp.exp(-density_delta)) > 0.1
  # density_delta = density_delta * mask

  # Exponential transmittance model
  alpha = 1 - jnp.exp(-density_delta)
  trans = jnp.exp(-jnp.concatenate([
      jnp.zeros_like(density_delta[..., :1]),
      jnp.cumsum(density_delta[..., :], axis=-1)
  ], axis=-1))
  # # Linear transmittance model
  # alpha = 1 - nn.relu(1 - density_delta)
  # trans = jnp.concatenate([
  #     jnp.ones_like(alpha[..., :1], alpha.dtype),
  #     jnp.cumprod(nn.relu(1 - density_delta[..., :]) + eps, axis=-1)
  # ], axis=-1)
  weights = alpha * trans[..., :-1]

  if rgb_bkgd is not None:
    comp_rgb = (weights[..., None] * rgb).sum(axis=-2) + trans[..., -1:] * rgb_bkgd
  else:
    comp_rgb = (weights[..., None] * rgb).sum(axis=-2)
    rgb_bkgd = jnp.ones(list(trans[..., -1:].shape[:-1]) + [3])
  acc = weights.sum(axis=-1)
  distance = (weights * t_vals).sum(axis=-1) / acc
  distance = jnp.clip(jnp.nan_to_num(distance, jnp.inf), t_vals[:, 0], t_vals[:, -1])

  if white_bkgd:
    comp_rgb = comp_rgb + (1. - acc[..., None])
  return comp_rgb, distance, acc, weights, alpha, trans[..., -1:], trans[..., -1:] * lax.stop_gradient(rgb_bkgd)

def sorted_piecewise_constant_pdf(key, bins, weights, num_samples, randomized):
  """Piecewise-Constant PDF sampling from sorted bins.

  Args:
    key: jnp.ndarray(float32), [2,], random number generator.
    bins: jnp.ndarray(float32), [batch_size, num_bins + 1].
    weights: jnp.ndarray(float32), [batch_size, num_bins].
    num_samples: int, the number of samples.
    randomized: bool, use randomized samples.

  Returns:
    t_samples: jnp.ndarray(float32), [batch_size, num_samples].
  """
  # Pad each weight vector (only if necessary) to bring its sum to `eps`. This
  # avoids NaNs when the input is zeros or small, but has no effect otherwise.
  eps = 1e-5
  weight_sum = jnp.sum(weights, axis=-1, keepdims=True)
  padding = jnp.maximum(0, eps - weight_sum)
  weights += padding / weights.shape[-1]
  weight_sum += padding

  # Compute the PDF and CDF for each weight vector, while ensuring that the CDF
  # starts with exactly 0 and ends with exactly 1.
  pdf = weights / weight_sum
  cdf = jnp.minimum(1, jnp.cumsum(pdf[..., :-1], axis=-1))
  cdf = jnp.concatenate([
      jnp.zeros(list(cdf.shape[:-1]) + [1]), cdf,
      jnp.ones(list(cdf.shape[:-1]) + [1])
  ], axis=-1)

  # Draw uniform samples.
  if randomized:
    # mipnerf
    s = 1 / num_samples
    u = jnp.arange(num_samples) * s
    u += jax.random.uniform(
        key,
        list(cdf.shape[:-1]) + [num_samples],
        maxval=s - jnp.finfo('float32').eps)
    # `u` is in [0, 1) --- it can be zero, but it can never be 1.
    u = jnp.minimum(u, 1. - jnp.finfo('float32').eps)
  else:
    # Match the behavior of jax.random.uniform() by spanning [0, 1-eps].
    u = jnp.linspace(0., 1. - jnp.finfo('float32').eps, num_samples)
    u = jnp.broadcast_to(u, list(cdf.shape[:-1]) + [num_samples])

  # Identify the location in `cdf` that corresponds to a random sample.
  # The final `True` index in `mask` will be the start of the sampled interval.
  mask = u[..., None, :] >= cdf[..., :, None]

  def find_interval(x):
    # Grab the value where `mask` switches from True to False, and vice versa.
    # This approach takes advantage of the fact that `x` is sorted.
    x0 = jnp.max(jnp.where(mask, x[..., None], x[..., :1, None]), -2)
    x1 = jnp.min(jnp.where(~mask, x[..., None], x[..., -1:, None]), -2)
    return x0, x1

  bins_g0, bins_g1 = find_interval(bins)
  cdf_g0, cdf_g1 = find_interval(cdf)

  t = jnp.clip(jnp.nan_to_num((u - cdf_g0) / (cdf_g1 - cdf_g0), 0), 0, 1)
  samples = bins_g0 + t * (bins_g1 - bins_g0)
  return samples

def sample_pdf(key, bins, weights, origins, directions, z_vals, idx_grads, num_samples,
               randomized, jitter, near, stop_grad=True, resample_padding=0.01):
  """Hierarchical sampling.

  Args:
    key: jnp.ndarray(float32), [2,], random number generator.
    bins: jnp.ndarray(float32), [batch_size, num_bins + 1].
    weights: jnp.ndarray(float32), [batch_size, num_bins].
    origins: jnp.ndarray(float32), [batch_size, 3], ray origins.
    directions: jnp.ndarray(float32), [batch_size, 3], ray directions.
    z_vals: jnp.ndarray(float32), [batch_size, num_coarse_samples].
    num_samples: int, the number of samples.
    randomized: bool, use randomized samples.
    stop_grad: bool, whether or not to backprop through sampling.
    resample_padding: float, added to the weights before normalizing.

  Returns:
    z_vals: jnp.ndarray(float32),
      [batch_size, num_coarse_samples + num_fine_samples].
    points: jnp.ndarray(float32),
      [batch_size, num_coarse_samples + num_fine_samples, 3].
  """
  # Do a blurpool.

  z_samples = sorted_piecewise_constant_pdf(key, bins, weights, num_samples, randomized)

  # Compute united z_vals and sample points
  # NOTE(debug): visualize coarse and fine samples
  z_samples = jnp.sort(jnp.concatenate([z_vals[:, jitter], z_samples], axis=-1), axis=-1)  # coarse + fine samples
  if stop_grad:
    origins = lax.stop_gradient(origins)
    directions = lax.stop_gradient(directions)
    z_samples = lax.stop_gradient(z_samples)
    z_vals = lax.stop_gradient(z_vals)
    idx_grads = lax.stop_gradient(idx_grads)

  ret = jnp.ones(list(z_samples.shape) + [3 + 3 + 3])
  # Assume that z_vals is monotonically increasing / sorted
  def sorted_find_nearest(xi, x, y):
    # # Shift x points to centers for rounding
    # spacing = jnp.diff(x) / 2
    # x = x + jnp.hstack([spacing, spacing[-1]])
    # Append head, tail for indexing
    y = jnp.hstack([y[0], y, y[-1]])
    return y[jnp.searchsorted(x, xi, side="left")]
  def loop_body(i, val):
    idx = sorted_find_nearest(z_samples[i], z_vals[i], jnp.arange(z_vals.shape[1]))
    rd = directions[i, idx]
    val = val.at[i, :, :3].set(origins[i, idx] + rd * (z_samples[i] - z_vals[i, idx])[..., None])
    val = val.at[i, :, 3:6].set(rd)
    val = val.at[i, :, 6:9].set(idx_grads[i, idx])
    return val
  ret = jax.lax.fori_loop(0, ret.shape[0], loop_body, ret)
  # for i in range(z_vals.shape[0]):
  #   ret = ret.at[i].set(directions[i, sorted_find_nearest(z_samples[i], z_vals[i], jnp.arange(z_vals.shape[1]))])

  # t = jnp.concatenate([z_samples[:, 0:1] - near, z_samples[:, 1:] - z_samples[:, :-1]], axis=-1)[..., None]
  # coords = jnp.cumsum(ret[..., :3] * t, axis=1) + origins[:, 0:1]
  return z_samples, ret[..., :3], ret[..., 3:6], ret[..., 6:9]

def add_gaussian_noise(key, raw, noise_std, randomized):
  """Adds gaussian noise to `raw`, which can used to regularize it.

  Args:
    key: jnp.ndarray(float32), [2,], random number generator.
    raw: jnp.ndarray(float32), arbitrary shape.
    noise_std: float, The standard deviation of the noise to be added.
    randomized: bool, add noise if randomized is True.

  Returns:
    raw + noise: jnp.ndarray(float32), with the same shape as `raw`.
  """
  if (noise_std is not None) and randomized:
    return raw + random.normal(key, raw.shape, dtype=raw.dtype) * noise_std
  else:
    return raw


#//MAXIME
from microbit import *
import radio

def getFromTel():
    recep = uart.read()
    if recep:
        return str(recep,'utf-8')
    #Man pr debug.
    if button_a.was_pressed():
        return "t"
    if button_b.was_pressed():
        return "l"
    return 0

def ask(fonction:str):
    """
    fonction:
        sendMeTemp
    """
    ProtocoleRadio().send_message("2",fonction)
    #Demande latemperature a l'autre microbit
    tentative = 0
    while True:
        tentative += 1
        source,message = ProtocoleRadio().get_message()
        if source and message:
            if source == "2":
                return message
        if tentative > 200:
            ProtocoleRadio().send_message("2",fonction)
            tentative = 0

class Secu:
    """
    Securité. vraiment très sur!
    Algo de césar remodifié car on est vraiement très chaud  !
    """
    def crypt(self,message:str,key:int=10):
        cryptedMessage = ""
        for lettre in message:
            key+=1
            cryptedMessage += chr(ord(lettre)+key)
        return cryptedMessage

    def decrypt(self,cryptedMessage:str,key:int=10):
        clearMessage = ""
        for lettre in cryptedMessage:
            key+=1
            clearMessage += chr(ord(lettre)-key)
        return clearMessage

    def hash(self,message:str):
        """
        hash de remplacement. #nul
        """
        checksum = 0
        for letter in message:
            checksum += ord(letter)
        return str(checksum)
    """
    import hashlib ne fonctionne pas :/
    def hash(self,message):
        return hashlib.md5(message.encode()).hexdigest()"""

class ProtocoleRadio:
    """
    protocole codé avec le cul.
    """
    def __init__(self):
        self.moi = "1"

    def get_message(self):
        recep = radio.receive()
        if recep:
            message_recup = Secu().decrypt(recep).split("|")
            if message_recup[0] == self.moi:
                if Secu().hash(message_recup[0]+"|"+message_recup[1]+"|"+message_recup[2]) == message_recup[3]:
                    #le message s'addresse a moi.
                    return message_recup[1],message_recup[2]
        return 0,0

    def send_message(self,dest,msg):
        to_send_informations = dest+"|"+self.moi+"|"+msg
        to_send = to_send_informations+"|"+Secu().hash(to_send_informations)
        radio.send(Secu().crypt(to_send))
        #return 1 pour send.
        return 1

if __name__ == "__main__":
    radio.config(channel=24)
    radio.on()
    uart.init(115200)
    while True:
        """
        Main Boucle
        """
        demande = getFromTel()
        if demande:
            message = ask(demande)
            sleep(500)
            uart.write(bytes(message,'utf-8'))


N = int(input())

from collections import Counter

C = Counter()
for i in range(N):
    a,b = map(int,input().split())
    C[a]+=1
    C[a+b]-=1

days = sorted(C.keys())
# ans[i] i人ログインしている日数
ans= [0] *(N+1)
prev_day = 0
cnt = 0
for curr_day in days:
    ans[cnt] += curr_day-prev_day
    cnt += C[curr_day]
    prev_day = curr_day
print(*ans[1:])


from colaPrioridad import Cola
from arbolBinario import nodoArbol
setattr(nodoArbol, 'peso', None)

def crearDecodificador(listaLetras, listaPeso):
    cola = Cola()
    for i in range(len(listaLetras)):
        nodo = nodoArbol(listaLetras[i])
        nodo.peso = listaPeso[i]
        cola.añadir(nodo, listaPeso[i])
    while(cola.tamanio > 1):
        nodo1 = cola.atender()
        nodo2 = cola.atender()
        nodo = nodoArbol(None)
        nodo.izq = nodo1[0]
        nodo.der = nodo2[0]
        peso = nodo1[1] + nodo2[1]
        #nodo.peso = peso
        cola.añadir(nodo, peso)
    return cola.primero.info[0]

def decodificar(decodificador, texto):
    buscador = decodificador
    cadena = ""
    for i in texto:
        if i == "0":
            if buscador.izq is not None:
                buscador = buscador.izq
            else:
                cadena += buscador.info
                buscador = decodificador.izq
        else:
            if buscador.der is not None:
                buscador = buscador.der
            else:
                cadena += buscador.info
                buscador = decodificador.der
    cadena += buscador.info
    return cadena

def generar(decodificador, lista, texto=''):
    if decodificador.info is None:
        generar(decodificador.izq, lista, texto + '0')
        generar(decodificador.der, lista, texto + '1')
    else:
        lista.append((decodificador.info, texto))

def codificar(decodificador, texto):
    tabla = []
    generar(decodificador, tabla)
    resultado = ""
    for i in texto:
        for j in tabla:
            if i == j[0]:
                resultado += j[1]
    return resultado


from nltk.corpus import stopwords
from nltk.tokenize import sent_tokenize, word_tokenize
from nltk import pos_tag
from nltk.util import ngrams

class FeatureExtractModule():
	# 你可以將你想要的特徵擷取函式寫在FeatureExtractModule
	# 因此，該模組只適合將建立FeatureExtraction_Func在這
	def __init__(self):
		self.stopword_set = stopwords.words('english')

	def Unigram_FEF(self, tweet):
		# 採用詞性
		pos_candidates = ['NN', 'JJ', 'VB', 'RB']

		# 將Tweet做sentence tokenize
		tweet_sents = sent_tokenize(tweet)

		# 進行word tokenize 以及標註詞性
		word_pos_set = [word_pos for sentence in tweet_sents for word_pos in pos_tag(word_tokenize(sentence))]

		# 將適合的字加入到feature
		feature = [word_pos[0].lower() for word_pos in word_pos_set
									   if word_pos[0].lower() not in self.stopword_set
									   and word_pos[1][0:2] in pos_candidates]

		# 回傳特徵
		return feature


import re
import os
import errno

try:
    from urllib.parse import urlparse
except ImportError:
    from urlparse import urlparse

from django.conf import settings
from django.core.urlresolvers import resolve

IS_FILE_RE = re.compile(r'\.([a-z]{2,4})$')
YOLODEX_MEDIA_PATH = u'yolodex/sources/{}/{}'

def get_current_app(request):
    return resolve(request.path).namespace

def get_media_path(realm, path):
    return YOLODEX_MEDIA_PATH.format(realm.pk, path)

def get_absolute_media_path(realm, path):
    return os.path.join(settings.MEDIA_ROOT, get_media_path(realm, path))

def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc:
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise

def get_domain(url):
    o = urlparse(url)
    return o.netloc

def get_sources(realm, sources):
    for kind, source, extra in get_raw_sources(realm, sources):
        if kind == 'file':
            source = get_media_path(realm, source)
        yield kind, source, extra

def get_raw_sources(realm, sources):
    for line in sources.splitlines():
        if not line.strip():
            continue
        match = IS_FILE_RE.search(line)
        if line.startswith(('http://', 'https://')):
            extra = get_domain(line)
            if match is not None:
                extra = u'%s (%s)' % (extra, match.group(1).upper())
            yield ('url', line, extra)
        elif match is not None:
            ext = match.group(1).upper()
            yield ('file', line, ext)
        else:
            yield ('text', line, '')


import random
from typing import Dict, List, Tuple

from netaddr import IPNetwork

from maasserver.models import Fabric, Subnet, VLAN
from maasserver.testing.commissioning import (
    FakeCommissioningData,
    LXDAddress,
    LXDNetwork,
)
from maastesting.factory import factory

from .defs import MACHINES_PER_FABRIC

def make_networks(
    count_per_fabric: int, fabrics_count
) -> Tuple[Dict[Fabric, List[VLAN]], Dict[VLAN, IPNetwork]]:
    fabrics = [Fabric.objects.create() for _ in range(fabrics_count)]
    vlans = {}
    ip_networks = {}
    created_cidrs = set()

    for fabric in fabrics:
        vlans[fabric] = [
            VLAN.objects.create(vid=vid, fabric=fabric)
            for vid in random.sample(range(10, 4095), count_per_fabric)
        ]
        for vlan in vlans[fabric]:
            cidr = factory.make_ipv4_network(slash=24, but_not=created_cidrs)
            created_cidrs.add(cidr)
            Subnet.objects.create(
                vlan=vlan,
                cidr=cidr,
            )
            ip_networks[vlan] = IPNetwork(cidr)

    return vlans, ip_networks

def make_network_interfaces(
    machine_infos: List[FakeCommissioningData],
    vlans: Dict[Fabric, List[VLAN]],
    ip_networks: Dict[VLAN, IPNetwork],
):
    machine_infos = list(machine_infos)

    def make_network_ip(vlan: VLAN, network: LXDNetwork):
        ip_network = ip_networks[vlan]
        ip = factory.pick_ip_in_network(ip_network)
        network.addresses = [LXDAddress(str(ip), ip_network.prefixlen)]
        return ip

    for fabric_vlans in vlans.values():
        if not machine_infos:
            return
        fabric_machine_infos, machine_infos = (
            machine_infos[:MACHINES_PER_FABRIC],
            machine_infos[MACHINES_PER_FABRIC:],
        )
        for machine_info in fabric_machine_infos:
            for idx, vlan in enumerate(fabric_vlans):
                network = machine_info.create_physical_network()
                if idx == 0:
                    bridge = machine_info.create_bridge_network(
                        mac_address=network.hwaddr, parents=[network]
                    )
                    make_network_ip(vlan, bridge)
                elif idx == 1:
                    vlan_iface = machine_info.create_vlan_network(
                        vid=vlan.vid, parent=network
                    )
                    make_network_ip(vlan, vlan_iface)
                elif idx == 2:
                    network2 = machine_info.create_physical_network()
                    bond = machine_info.create_bond_network(
                        parents=[network, network2]
                    )
                    make_network_ip(vlan, bond)
                else:
                    make_network_ip(vlan, network)


from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

# from selenium.webdriver.chrome.service import Service
# browser = webdriver.Firefox(service=path_chrome)
# browser = webdriver.Chrome(service=path_chrome)
browser = webdriver.Chrome()
browser.get("https://www.amazon.com.br")
xpath_search = '//*[@id="twotabsearchtextbox"]'
browser.find_element(By.XPATH, xpath_search).send_keys("iphone" + Keys.RETURN)

iphone_names = browser.find_elements(By.XPATH, '//span[@class="a-size-base-plus a-color-base a-text-normal"]')
prices = browser.find_elements(By.XPATH, '//*[@class="a-price"]')

name = []
price = []

# for n in iphone_names:
#     name.append(n.text)
# print(name)
#
# for p in prices:
#     price.append(p.text.replace("\n", ","))
# print(price)

cont = 1
for name, price in zip(iphone_names, prices):
    print(cont, name.text, price.text.replace("\n", ","))
    cont += 1
browser.close()


class Solution:
    def isPathCrossing(self, path: str) -> bool:
        visited = {}
        curr = (0,0)
        visited[curr] = True

        for p in path:
            if p == 'N':    curr = (curr[0], curr[1]+1)
            elif p == 'S':  curr = (curr[0], curr[1]-1)
            elif p == 'W':  curr = (curr[0]-1, curr[1])
            elif p == 'E':  curr = (curr[0]+1, curr[1])
            else:           raise Exception('Solution', 'wrong path code')

            if curr in visited: return True
            visited[curr] = True;

        return False


from urllib import request #different way to import

drive_url = 'http://www.sample-videos.com/csv/Sample-Spreadsheet-1000-rows.csv'

def download_pdf_file(file_url):
    #Connect
    response = request.urlopen(file_url)
    file = response.read()
    #Save as a string
    file_str = str(file)
    lines = file_str.split("\\n")
    #Make a file
    dest_url = r'goog.csv'
    fx = open(dest_url,"w")
    for line in lines:
        fx.write(line + "\n")

download_pdf_file(drive_url)


# E - 「く」
# https://atcoder.jp/contests/iroha2019-day3/tasks/iroha2019_day3_e

N = int(input())
C = [input() for _ in range(N)]

ans = 0

nums = []
tmpc = '/'
tmpn = 0
for c in C:
    if c == tmpc:
        tmpn += 1
    else:
        nums.append(tmpn)
        tmpn = 1
    tmpc = c
nums.append(tmpn)

ans = 0
for i in range(0, len(nums)//2 * 2, 2):
    if nums[i] == nums[i+1]:
        ans += 1

print(ans)


#! /usr/bin/env python
# -*- coding: utf-8 -*-
# author: Crise
# date: 25/07/20

"""
题目描述：
给定一个数组和滑动窗口的大小，找出所有滑动窗口里数值的最大值。例如，如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3，
那么一共存在6个滑动窗口，他们的最大值分别为{4,4,6,6,6,5}； 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个：
{[2,3,4],2,6,2,5,1}， {2,[3,4,2],6,2,5,1}， {2,3,[4,2,6],2,5,1}， {2,3,4,[2,6,2],5,1}，
{2,3,4,2,[6,2,5],1}， {2,3,4,2,6,[2,5,1]}。

"""

class Solution:
    def maxInWindows(self, num, size):
        # write code here
        if num is None or size <= 0:
            return []

        max_list = []
        for i in range(len(num) - size + 1):
            range_ = num[i: i+size]
            max_list.append(max(range_))
        return max_list

if __name__ == "__main__":
    print(Solution().maxInWindows([2, 3, 4, 2, 6, 2, 5, 1], 2))

JZ64 滑动窗口的最大值.py


# -*- coding: utf-8 -*-
"""
Created on Mon Nov 20 11:18:45 2017

@author: s161488
"""

import tensorflow as tf
import numpy as np

def unpool_with_argmax(pool, ind, shape_ori, name = None, ksize=[1, 2, 2, 1]):

    """
       Unpooling layer after max_pool_with_argmax.
       Args:
           pool:   max pooled output tensor
           ind:      argmax indices
           ksize:     ksize is the same as for the pool
       Return:
           unpool:    unpooling tensor
    """
    with tf.variable_scope(name):
        input_shape = pool.get_shape().as_list()
        output_shape = shape_ori
        flat_input_size = np.prod(input_shape)
        flat_output_shape = [output_shape[0], output_shape[1] * output_shape[2] * output_shape[3]]

        pool_ = tf.reshape(pool, [flat_input_size])
        batch_range = tf.reshape(tf.range(output_shape[0], dtype=ind.dtype), shape=[input_shape[0], 1, 1, 1])
        b = tf.ones_like(ind) * batch_range
        #first let's create batch matrix, the batch_range determine the batch index for each element in the matrix(0,to,batch_size-1),
        #the size will be as same as the size of output from maxpooling! And also when we reshape the output(if the batch size is not 1), then the order of
        #output  is first read from the first batch, after finished we start to read the second batch, so this way is exactly does the same thing, the
        #concat index for the first batch are all zero, then the concat index for the second batch are all one, so this upsampling way is really correct!!
        #actually the flattened pooling index represent the index for the pooling value, which is in the range of (0-totalnumber of pixels)!!
        b = tf.reshape(b, [flat_input_size, 1])
        ind_ = tf.reshape(ind, [flat_input_size, 1])
        ind_ = tf.concat([b, ind_], 1)
        ret = tf.scatter_nd(ind_, pool_, shape=flat_output_shape)
        ret = tf.reshape(ret, output_shape)
        return ret

def max_pool(inputs,name):
    value,index = tf.nn.max_pool_with_argmax(tf.to_double(inputs),ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME',name=name)
    print('value shape',value.shape)
    print('index shape',index.shape)
    return tf.to_float(value),index,inputs.get_shape().as_list()

def Test_Upsampling():
    gen_array = np.array([[[[0,1,3],
                           [1,3,6],
                           [2,6,7],
                           [3,7,2],
                           [5,5,5]],

                           [[7,4,1],
                            [8,9,9],
                            [5,8,2],
                            [3,5,8],
                            [6,3,9]],

                           [[2,6,2],
                            [4,3,7],
                            [3,2,3],
                            [9,5,5],
                            [9,4,4]],

                           [[7,3,1],
                            [4,7,4],
                            [6,5,6],
                            [7,8,9],
                            [2,9,2]]]])

    xplaceholder = tf.placeholder(tf.float32,np.shape(gen_array))
    value,index,oridex = max_pool(xplaceholder,'test')
    sp_dense = unpool_with_argmax(value,index,np.shape(gen_array),name='test',ksize=[1,2,2,1])
    print(np.shape(gen_array))
    print(sp_dense)
    with tf.Session() as sess:
        feed_dict = {
        xplaceholder:gen_array}
        fetches = [value,index,sp_dense]
        maxv,maxi,spdense = sess.run(fetches,feed_dict)
    return maxv,maxi,spdense

def Test_Gradient():
    indices = tf.placeholder(tf.int64,(None,2))
    values = tf.placeholder(tf.float32,(None,))
    sparse_tensor = tf.SparseTensor(indices,values,(5,7))
    dense_tensor1 = tf.sparse_tensor_to_dense(sparse_tensor)
    dense_tensor2 = tf.scatter_nd(indices,values,shape=[5,7])
    dense_tensor3 = tf.sparse_add(tf.zeros((5,7)),sparse_tensor)
    sum1 = tf.reduce_sum(dense_tensor1)
    sum2 = tf.reduce_sum(dense_tensor2)
    sum3 = tf.reduce_sum(dense_tensor3)

    print('dense_tensor1',tf.gradients(sum1,values)) #None
    print('dense_tensor2',tf.gradients(sum2,values)) #tf.Tensor 'gradients_1/ScatterNd_grad/GatherNd:0'
    print('dense_tensor3',tf.gradients(sum3,values)) #tf.Tensor 'gradients_2/SparseTensorDenseAdd_grad/GatherNd:0'

#gen_array = np.array([[[[0,1,3],
#                           [1,3,6],
#                           [2,6,7],
#                           [3,7,2],
#                           [5,5,5],
#                           [4,2,4]],
#
#                           [[7,4,1],
#                            [8,9,9],
#                            [5,8,2],
#                            [3,5,8],
#                            [6,3,9],
#                            [7,7,9]],
#
#                           [[2,6,2],
#                            [4,3,7],
#                            [3,2,3],
#                            [9,5,5],
#                            [9,4,4],
#                            [8,2,6]],
#
#                           [[7,3,1],
#                            [4,7,4],
#                            [6,5,6],
#                            [7,8,9],
#                            [2,9,2],
#                            [5,1,5]]]])
#


# -*- coding: utf-8 -*-
"""
Created on Wed Jun 17 00:29:53 2020

@author: gao
"""

import numpy as np
import numpy_financial as npf

#%%
def cal_interets(principal, rate, n, interest_type='simple'):
    '''
    计算本息和
    ---------
    Params:
    ------
    principal: -> float 本金
    rate: -> float 利率
    n: -> float 年份
    interest_type: -> str 单利(simple)|复利(compound)|连续复利(continuous)

    Returns:
    -------
    future value : -> float 终值
    '''
    if interest_type == 'simple':
        final = principal * (1 + rate * n)
    elif interest_type == 'compound':
        final = principal * (1 + rate) ** n
    elif interest_type == 'continuous':
        final = principal * np.exp(rate * n)
    else:
        raise Exception('Invalid Type!')
    return final

#%%
# 计算终值
npf.fv(0.1, 4, 0, -1000)

# 计算现值
npf.pv(0.1, 4, 0, -1500)

# 计算净现值
rate, cashflows = 0.08, [-40_000, 5_000, 8_000, 12_000, 30_000]
npf.npv(rate, cashflows).round(5)

#%%
npf.pv(0.06, 3, -100, 0)
npf.pv(0.06, 3, -100, 0, when='begin')

# 验证
npf.pv(0.06, 3, 100, 0, when='begin') / npf.pv(0.06, 3, 100, 0) == 1.06

npf.fv(0.06, 3, -100, 0)
npf.fv(0.06, 3, -100, 0, when='begin')

# 验证
npf.fv(0.06, 3, 100, 0, when='begin') / npf.fv(0.06, 3, 100, 0) == 1.06

#%%
round(npf.irr([-100, 39, 59, 55, 20]), 5)
round(npf.irr([-100, 0, 0, 74]), 5)
round(npf.irr([-100, 100, 0, -7]), 5)
round(npf.irr([-100, 100, 0, 7]), 5)
round(npf.irr([-5, 10.5, 1, -8, 1]), 5)


from brian import *

#tau_pre = 5*ms
tau_post = 5 * ms
gmax = 1.0
delta_A_pre = 0.2
delta_A_post = -0.3

G = NeuronGroup(2, 'V:1', reset=0, threshold=1)

C = Connection(G, G, 'V')

C[0, 1] = 0.5

stdp = STDP(C, '''
            dA_pre/dt  = -0.1*sqrt(clip(A_pre,0,inf))/tau_pre   : 1
            dA_post/dt = -A_post/tau_post : 1
            tau_pre : second
            ''', pre='''
            A_pre += delta_A_pre
            w += A_post
            ''', post='''
            A_post += delta_A_post
            w += A_pre
            ''', wmax=gmax)

stdp.tau_pre = [2 * ms, .1 * ms]

M_pre = StateMonitor(stdp.pre_group, 'A_pre', record=True)
M_post = StateMonitor(stdp.post_group, 'A_post', record=True)

wvals = []

@network_operation
def rec_wvals():
    wvals.append(C[0, 1])

run(1 * ms)
G.V[1] = 2
run(1 * ms)
G.V[0] = 2
run(1 * ms)

subplot(221)
M_pre.plot()
subplot(222)
M_post.plot()
subplot(223)
plot(wvals)

show()


from rest_framework import serializers
from flights.models import City, Airport, Route, Flight

class CitySerializer(serializers.ModelSerializer):
    class Meta:
        model = City
        fields = ("id", "name", "is_capital")

class AirportListSerializer(serializers.ModelSerializer):
    city = serializers.StringRelatedField()

    class Meta:
        model = Airport
        fields = ("id", "name", "city")

class AirportSerializer(serializers.ModelSerializer):
    class Meta:
        model = Airport
        fields = ("id", "name", "city")

    def to_representation(self, instance):
        return AirportListSerializer(instance).data

class RouteListSerializer(serializers.ModelSerializer):
    source = serializers.StringRelatedField()
    destination = serializers.StringRelatedField()

    class Meta:
        model = Route
        fields = ("id", "source", "destination", "distance")

class RouteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Route
        fields = ("id", "source", "destination", "distance")

    def to_representation(self, instance):
        return RouteListSerializer(instance).data

class FlightListSerializer(serializers.ModelSerializer):
    route = serializers.StringRelatedField()
    crews = serializers.StringRelatedField(many=True)
    airplane = serializers.StringRelatedField()
    seats_available = serializers.IntegerField(read_only=True)

    class Meta:
        model = Flight
        fields = (
            "id",
            "route",
            "crews",
            "airplane",
            "departure_time",
            "arrival_time",
            "seats_available",
        )

class FlightSerializer(serializers.ModelSerializer):
    class Meta:
        model = Flight
        fields = (
            "id",
            "route",
            "crews",
            "airplane",
            "departure_time",
            "arrival_time"
        )

    def to_representation(self, instance):
        return FlightListSerializer(instance).data

class FlightDetailSerializer(serializers.ModelSerializer):
    route = serializers.StringRelatedField()
    crews = serializers.StringRelatedField(many=True)
    airplane = serializers.StringRelatedField()
    taken_seats = serializers.SerializerMethodField()

    class Meta:
        model = Flight
        fields = (
            "id",
            "route",
            "crews",
            "airplane",
            "departure_time",
            "arrival_time",
            "taken_seats",
        )

    def get_seat_and_row(self, ticket):
        return {"row": ticket.row, "seat": ticket.seat}

    def get_taken_seats(self, flight):
        return [self.get_seat_and_row(ticket) for ticket in
                flight.tickets.all()]

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data["taken_seats"] = self.get_taken_seats(instance)
        return data


class BigThing:

    def __init__(self, random):
        self._random = random

    def size(self):
        if isinstance(self._random, int):
            return self._random
        return len(self._random)

class BigCat(BigThing):

    def __init__(self, random, weight):
        super().__init__(random)
        self._weight = weight

    def size(self):
        if (self._weight > 20):
            print("Very Fat")
        elif ((self._weight < 20) and (self._weight > 15)):
            print("Fat")
        else:
            print("OK")

my_thing = BigThing("balloon")
print(my_thing.size())

cutie = BigCat("mitzy", 22)
print(cutie.size())


import pycurl
from io import BytesIO

def curlRequest(s):
    buffer = BytesIO()
    print(type(s))
    print(s)
    s = s.replace(" ", "%20")
    s = s.replace("'", "%E2%80%99")
    s = s.replace("\t", "")
    request = "http://localhost:2222/rest/annotate?text=" + s.encode("ascii", errors="ignore").decode()
    # request = "https://api.dbpedia-spotlight.org/en/annotate?text=" + b;
    print(request)
    crl = pycurl.Curl()
    crl.setopt(crl.URL, request)
    crl.setopt(pycurl.HTTPHEADER, ['accept: application/json'])
    crl.setopt(pycurl.CUSTOMREQUEST, "GET")
    crl.setopt(crl.WRITEDATA, buffer)
    crl.perform()
    crl.close()
    result = buffer.getvalue().decode('utf-8')
    print(result)
    print(type(result))
    dict = {}
    try:
        result = result[result.index("[")+1:result.index("]"):1].split("},")
        key = ""
        value = ""
        for single_result in result:
            items = single_result.split("\",")
            for item in items:
                if (item.startswith("\"@surfaceForm")):
                    key = item[item.index(":") + 2:]
                    print(key)
                if (item.startswith("{\"@URI")):
                    value = item[item.index(":") + 2:]
                    print(value)
            dict[key] = value
    except ValueError:
        pass

    for x, y in dict.items():
        print(x, y)

    return dict

# curlRequest("Concordia advanced six spots to 10th place among Canada's engineering schools in the Maclean's 2018 Program Rankings, while computer science advanced three spots into 11th position this year")
# curlRequest("TOPICS IN SOFTWARE ENGINEERING 1 - 	SOFTWARE RE-ENGINEERING")

def id_keywords_uri_pair(id_description_dict):
    id_keywords = {}
    for id in id_description_dict:
        id_keywords[id] = curlRequest(id_description_dict[id])
        print(id_keywords[id])

    fo = open("id_keywords_uri.txt", "w")
    for x, y in id_keywords.items():
        for y1, y2 in y.items():
            fo.write(x + " " + y1 + " " + y2 + "\n")
    fo.close()

    return id_keywords


# -*- coding: gb18030 -*-

import BigWorld
from bwdebug import *
from Spell_Item import Spell_Item
import items
import random
import csdefine
import ECBExtend
g_items = items.instance()

class Spell_QuestItem_Catch( Spell_Item ):
	"""
	抓捕怪物生成任务道具
	"""
	def __init__( self ):
		"""
		构造函数。
		"""
		Spell_Item.__init__( self )
		self._monsterID = ""		# 怪物ID
		self._isAllCatch = False	# 是否全部抓捕
		self._itemID = 0			# 任务物品ID

	def init( self, dict ):
		"""
		读取技能配置
		@param dict: 配置数据
		@type  dict: python dict
		"""
		Spell_Item.init( self, dict )
		self._monsterID = str( dict["param1"] )
		self._isAllCatch = bool( int( dict["param2"] ) )	# 填0抓捕一个，填1全部抓捕
		self._itemID = int( dict["param4"] )

	def cast( self, caster, target ):
		"""
		virtual method.
		正式向一个目标或位置施放（或叫发射）法术，此接口通常直接（或间接）由intonate()方法调用。

		注：此接口即原来旧版中的castSpell()接口

		@param     caster: 使用技能的实体
		@type      caster: Entity
		@param target: 施展对象
		@type  target: 一个包装过的对象entity 被包装对象可能是 (位置，entity, item)详细请看SkillTargetObjImpl.py
		"""
		# 引导技能检测
		caster.delHomingOnCast( self )
		self.setCooldownInIntonateOver( caster )
		# 处理消耗
		self.doRequire_( caster )
		#通知所有客户端播放动作/做其他事情
		caster.planesAllClients( "castSpell", ( self.getID(), target ) )

		# 法术施放完毕通知，不一定能打中人哦(是否能打中已经和施法没任何关系了)！
		# 如果是channel法术(未实现)，只有等法术结束后才能调用
		self.onSkillCastOver_( caster, target )

		#保证客户端和服务器端处理的受术者一致
		delay = self.calcDelay( caster, target )
		if delay <= 0.5:
			# 瞬发
			self.onArrive( caster, target )
		else:
			# 延迟
			caster.addCastQueue( self, target, delay )

		#更新物品 只有物品成功使用之后才可以对物品的消减进行操作
		self.updateItem( caster )

	def onArrive( self, caster, target ):
		"""
		virtual method = 0.
		法术抵达目标通告。在默认情况下，此处执行可受术人员的获取，然后调用receive()方法进行对每个可受术者进行处理。
		注：此接口为旧版中的receiveSpell()

		@param   caster: 施法者
		@type    caster: Entity
		@param target: 施展对象
		@type  target: 一个包装过的对象entity 被包装对象可能是 (位置，entity, item)详细请看SkillTargetObjImpl.py
		"""
		# 获取所有受术者
		receivers = self.getReceivers( caster, target )
		usefulReceivers = []
		for receiver in receivers:
			if not hasattr( receiver, "className" ) or receiver.className != self._monsterID:	# 不符合条件的受术者直接跳过
				continue
			receiver.clearBuff( self._triggerBuffInterruptCode )
			usefulReceivers.append( receiver )

		if self._isAllCatch:	# 全部抓捕
			for re in usefulReceivers:
				self.receive( caster, re )
				self.receiveEnemy( caster, re )
		else:
			if len( usefulReceivers ):
				en = random.choice( usefulReceivers ) # 随机取一个
				self.receive( caster, en )
				self.receiveEnemy( caster, en )

		if not caster.isDestroyed:
			caster.onSkillArrive( self, usefulReceivers )

	def receive( self, caster, receiver ):
		"""
		virtual method.
		法术到达所要做的事情
		"""
		Spell_Item.receive( self, caster, receiver )

		receiver.addTimer( 0.1, 0, ECBExtend.MONSTER_CORPSE_DELAY_TIMER_CBID )	# 销毁怪物
		item = g_items.createDynamicItem( self._itemID , 1 )
		caster.addItem( item, csdefine.ADD_ITEM_QTSGIVEITEMS )	# 任务道具


# import os module
import os

# import csv module
import csv

# Path to CSV file
csvpath = os.path.join('/Users/leahkrausetp/Desktop/Leah_UCB/PROJECTS/python-challenge/PyPoll','Resources', 'election_data.csv')

# Read CSV file in "read" mode. Assign readable file as a new variable
with open(csvpath) as csvfile:

# Specifies delimiter and variable. Prints this into csv reader
    csvreader = csv.reader(csvfile, delimiter=',')

# Read header and skips it
    header = next(csvreader)

# Create lists to store data
    voter_id = []
    candidate = []
    candidates_votes = []
    indv_candidates = []

# Create variables
    can1_votes = 0
    can2_votes = 0
    can3_votes = 0
    total_votes = 0

# Create a function that provides the total number and percentage each candidate received
    for row in csvreader:

# Total votes
        voter_id.append((row[0]))
# Candidate list
        candidate.append(row[2])

# Attain individual candidates names without repetition
    indv_candidates = list(set(candidate))

    with open(csvpath) as csvfile2:
        csvreader2 = csv.reader(csvfile2, delimiter=',')
        header = next(csvreader2)

        for row in csvreader2:
# Count up votes per candidate
            if row[2] == indv_candidates[0]:
                can1_votes += 1
            elif row[2] == indv_candidates[1]:
                can2_votes += 1
            elif row[2] == indv_candidates[2]:
                can3_votes += 1

# Calculate total number of votes
        total_votes = len(voter_id)

# Voter percentage per candidate
        can1_percentage = round(can1_votes / total_votes * 100, 3)
        can2_percentage = round(can2_votes / total_votes * 100, 3)
        can3_percentage = round(can3_votes / total_votes * 100, 3)

# Winner
if can1_percentage > can2_percentage and can3_percentage:
    winner = indv_candidates[0]
elif can2_percentage > can3_percentage and can1_percentage:
    winner = indv_candidates[1]
elif can3_percentage > can2_percentage and can1_percentage:
    winner = indv_candidates[2]

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

# Print output
print("Election Results")
print("--"*15)
print("Total Votes: ", total_votes)
print("--"*15)
print(f"{indv_candidates[0]}: {can1_percentage}% ({can1_votes})")
print(f"{indv_candidates[1]}: {can2_percentage}% ({can2_votes})")
print(f"{indv_candidates[2]}: {can3_percentage}% ({can3_votes})")
print("--"*15)
print(f"Winner: {winner}")
print("--"*15)

# Print output to text file
with open ("PyPoll_Output.text", "w") as x:
    x.write("Election Results")
    x.write("\n")
    x.write("--"*15)
    x.write("\n")
    x.write(f"Total Votes: {total_votes}")
    x.write("\n")
    x.write("--"*15)
    x.write("\n")
    x.write(f"{indv_candidates[0]}: {can1_percentage}% ({can1_votes})")
    x.write("\n")
    x.write(f"{indv_candidates[1]}: {can2_percentage}% ({can2_votes})")
    x.write("\n")
    x.write(f"{indv_candidates[2]}: {can3_percentage}% ({can3_votes})")
    x.write("\n")
    x.write("--"*15)
    x.write("\n")
    x.write(f"Winner: {winner}")
    x.write("\n")
    x.write("--"*15)


import utils
import numpy as np
import torch
import torch.nn.functional as F
from models.retrieve_modeling import TuringNLRv3PreTrainedModel, TuringNLRv3Model

class OneTowerForNeighborPredict(TuringNLRv3PreTrainedModel):
    def __init__(self, config):
        super().__init__(config)
        self.bert = TuringNLRv3Model(config)
        self.init_weights()

    def infer_embedding(self,input_ids,attention_mask):
        vec=self.bert(input_ids,attention_mask)[0][:,0,:]
        return vec

    def retrieve_loss(self,q,k):
        score = torch.matmul(q, k.transpose(0, 1))
        loss = F.cross_entropy(score,torch.arange(start=0, end=score.shape[0],
                                                  dtype=torch.long, device=score.device))
        return loss

    def test(self,input_ids_query,attention_mask_query,input_ids_key,attention_mask_key,neighbor_num):
        all_nodes_num = input_ids_query.shape[0]
        batchsize = all_nodes_num // (neighbor_num+1)
        input_ids_query = input_ids_query.reshape(batchsize, -1)
        attention_mask_query = attention_mask_query.reshape(batchsize, -1)
        input_ids_key = input_ids_key.reshape(batchsize, -1)
        attention_mask_key = attention_mask_key.reshape(batchsize, -1)

        query_emb=self.infer_embedding(input_ids_query,attention_mask_query)
        key_emb=self.infer_embedding(input_ids_key,attention_mask_key)
        return query_emb, key_emb

    def forward(self,input_ids_query,attention_mask_query,input_ids_key,attention_mask_key,neighbor_num):
        """
            input_ids_query: batchsize*(neighbor_num+1), seq_length
            attention_mask_query: batchsize*(neighbor_num+1), seq_length
        """
        all_nodes_num = input_ids_query.shape[0]
        batchsize = all_nodes_num // (neighbor_num+1)
        input_ids_query = input_ids_query.reshape(batchsize, -1)
        attention_mask_query = attention_mask_query.reshape(batchsize, -1)
        input_ids_key = input_ids_key.reshape(batchsize, -1)
        attention_mask_key = attention_mask_key.reshape(batchsize, -1)

        query_emb=self.infer_embedding(input_ids_query,attention_mask_query)
        key_emb=self.infer_embedding(input_ids_key,attention_mask_key)
        neighbor_predict_loss = self.retrieve_loss(query_emb, key_emb)
        return neighbor_predict_loss

    def onestep_evaluate(self, input_ids_query, attention_masks_query, mask_query, input_ids_key,
        attention_masks_key, mask_key, neighbor_num, mask_self_in_graph=False):
        """
            input_ids: Tensor(batch_size*(neighbor_num+1),seq_length)
            attention_masks: Tensor(batch_size*(neighbor_num+1), seq_length)
            mask_query/key: Tensor(batch_size*(neighbor_num+1))
        """
        all_nodes_num = mask_query.shape[0]
        batch_size = all_nodes_num//(neighbor_num+1)

        query_ids = input_ids_query.view(batch_size, neighbor_num+1, -1)[:,:1,:] # B 1 L
        query_ids = query_ids.expand(-1, neighbor_num+1, -1).reshape(batch_size*(neighbor_num+1), -1) # B*(N+1) L
        query_neighbor_ids = torch.cat([query_ids, input_ids_query], axis=1) # B*(N+1) 2*L

        neighbor_mask_query = mask_query.view(batch_size, 1+neighbor_num) # B 1+N

        query_attention = attention_masks_query.view(batch_size, neighbor_num+1, -1)[:,:1,:] # B 1 L
        query_attention = query_attention.expand(-1, neighbor_num+1, -1).reshape(batch_size*(neighbor_num+1), -1) # B*(N+1) L
        query_neighbor_attention = torch.cat([query_attention, attention_masks_query], axis=1) # B*(N+1) 2*L

        key_ids = input_ids_key.view(batch_size, neighbor_num+1, -1)[:,:1,:] # B 1 L
        key_ids = key_ids.expand(-1, neighbor_num+1, -1).reshape(batch_size*(neighbor_num+1), -1) # B*(N+1) L
        key_neighbor_ids = torch.cat([key_ids, input_ids_key], axis=1) # B*(N+1) 2*L

        key_attention = attention_masks_key.view(batch_size, neighbor_num+1, -1)[:,:1,:] # B 1 L
        key_attention = key_attention.expand(-1, neighbor_num+1, -1).reshape(batch_size*(neighbor_num+1), -1) # B*(N+1) L
        key_neighbor_attention = torch.cat([key_attention, attention_masks_key], axis=1) # B*(N+1) 2*L

        neighbor_mask_key = mask_key.view(batch_size, 1+neighbor_num) # B 1+N

        new_query_embed = self.infer_embedding(query_neighbor_ids, query_neighbor_attention).reshape(batch_size, neighbor_num+1, -1) # B*(N+1) D
        new_key_embed = self.infer_embedding(key_neighbor_ids, key_neighbor_attention).reshape(batch_size, neighbor_num+1, -1) # B*(N+1) D

        query_neighbor_scores = torch.matmul(new_query_embed, new_key_embed[:,:1,:].transpose(1,2)).squeeze(2)  # B 1+N
        query_neighbor_scores = query_neighbor_scores.masked_fill(neighbor_mask_query == 0, float(-1e4))
        key_neighbor_scores = torch.matmul(new_key_embed, new_query_embed[:,:1,:].transpose(1,2)).squeeze(2)  # B 1+N
        key_neighbor_scores = key_neighbor_scores.masked_fill(neighbor_mask_key == 0, float(-1e4))

        return query_neighbor_scores, key_neighbor_scores, None, None


import requests
from bs4 import BeautifulSoup

url = 'http://photo.poco.cn/lastphoto-htx-id-5748659-p-0.xhtml#'

wb_data = requests.get(url)

soup = BeautifulSoup(wb_data.text,'lxml')
imgs = soup.select('div.img-item > div.img-box.photo')
print(imgs)


import sounddevice
from scipy.io.wavfile import write

fs = 44100
second = 1

print(sounddevice.query_devices())
sounddevice.default.device = 1

for i in range(2):
    print("recorde")
    record_voice = sounddevice.rec( int( second * fs ) , samplerate = fs , channels = 1 )
    sounddevice.wait()
    write("out" + str(i) + ".wav", fs , record_voice )


#!/usr/bin/env python3
# The print statements go to the console or web server access log or error log; they do not go to the web page.

from flask import Flask, render_template, request, make_response
import flask
print(f"flask {flask.__version__}")

app = Flask(__name__)

app.config["APPLICATION_ROOT"] = "/recommendit" # IDK if this actually does anything.
import os
import common
import pandas as pd
print(f"pandas {pd.__version__}")
import pyarrow  # Not refrenced in MY code, but is actually required by pandas bc I call read_feather.
print(f"pyarrow {pyarrow.__version__}")
from pathlib import Path

# Decide if running on dev host or public host, so path can be automatically changed. Basis: comcast isp vs amazon.com?
# In advance, set these env vars on the host.
# In Azure cloud: Portal | Home | wackysubs App Service | Settings | Configuration | Application Settings
# In Amazon EC2 or local dev host: Just set an env var in a startup script
adfpath = Path(os.environ['WACKYSUBSDATAPATHPART1'])
edfpath = Path(os.environ['WACKYSUBSDATAPATHPART2'])

print(f"Loading part 1 of model from path {adfpath}")
adf = pd.read_feather(adfpath);
print(f"Loading part 2 of model from path {edfpath}")
edf = pd.read_feather(edfpath);

@app.context_processor
def GetAllSubreddits():
    return dict(allsubreddits=sorted(edf.columns))

@app.route('/')
def index():
    return render_template('index.html', confMin=0.05)

# User keying in a subreddit, so offer a partially matching list.
@app.route('/offersubreddits', methods=["GET"])
def offersubreddits():
	q = request.args.get("q")
	subreddits = [subreddit for subreddit in edf.columns if subreddit.startswith(q)]
	return render_template("offersubreddits.html", subreddits=subreddits)

def GetFavsList():
	favs = request.cookies.get('favs')
	if favs is None:
		favs = ''
	favsList = [f for f in favs.split(";") if f != '']
	favsList = sorted(list(set(favsList)))
	return favsList

# User clicked button to run the recommender system
# Check the value of the action property of the submit button to decide action
@app.route('/formaction', methods=["GET"])
def formaction():
	baction = request.args.get('baction')
	if 'query' == baction:
		confMin = 0.01 if None == request.args.get('confMin') else request.args.get('confMin')
		searchTerm = request.args.get('searchTerm') # add 2 more searchTerm later
		if searchTerm is None or searchTerm == '':
			favsList = GetFavsList()
			return render_template('index.html', favorites=favsList)
		searchList=[searchTerm]
		recommendations = []
		if set(searchList).issubset(edf.columns):
			df = common.QueryModel(adf, edf, searchList, exactMatch=True, confMin=confMin)
			recommendations = common.QueryResultList(df) # [np.array(['Jokes'], dtype=object), np.array(['Showerthoughts'], dtype=object), ...
			recommendations = [list(a)[0] for a in recommendations] # ['Jokes', 'Showerthoughts', ...
			resp = make_response(render_template('index.html', recommendations=recommendations, searchList=searchList, searchTerm=searchTerm, confMin=confMin))
			# Every time they Find an item, add that to their favorites, but No duplicates, no empty strings.
			favsList = GetFavsList() + searchList
			favsList = sorted(favsList)
			favs = ';'.join(favsList)
			resp.set_cookie('favs', favs)
			return resp
		else:
			return render_template('index.html', confMin=0.05) # no such subreddit

	elif 'showfavs' == baction:
		favsList = GetFavsList()
		return render_template('index.html', favorites=favsList)
	elif 'delete' == baction:
		favsList = GetFavsList()
		item = request.args.get('delete')
		if item in favsList:
			favsList.remove(item)
		resp = make_response(render_template('index.html', favorites=favsList, baction='showfavs')) # show the (new) favs
		favs = ';'.join(favsList) # cookiefy the list
		resp.set_cookie('favs', favs) # set the favs into cookie
		return resp
	else:
		print(f"Bad parameter value in baction:*{baction}*")

if __name__ == "__main__":
    app.run()