from commands.abs_command import AbsCommand
from commands.helpers import select_table
from dbs.commands_to_db.db_commit import DbCommit
from dbs.commands_to_db.db_select_one import DbSelectOne

class Remove(AbsCommand):
    name = 'Remove'

    def execute(self):

        table = select_table()

        element_id = input('Provide expense id you want to remove. \n')

        try:
            element_id = int(element_id)

            query = f'SELECT * FROM {table[0]} WHERE  id=?'
            data = (element_id,)

            element = DbSelectOne().do(query, data)
            obj = table[1]
            print(obj(element))

            confirm = input('To confirm deletion provide "Y".').lower().strip()

            if confirm == 'y':
                query_delete = f'DELETE FROM  {table[0]} WHERE id = ?'
                data = (element_id,)

                DbCommit().do(query_delete, data)
                print('The expense has been removed.')

        except ValueError:
            print(f"Incorrect value {element_id}.")
        except TypeError:
            print(f"Incorrect value, no id {element_id}.")


from controller import Robot
import pika
import json
import string
import ast
import threading
import pathlib
import time
import os
import sys
from message_subscriber import MessageSubscriber

# This is a "workaround" to be able to import the class when the controllers are running in the
# Webots "sandbox". So we need to add the current working directory as well as "two parents steps up".
cbaa_path = os.path.join(os.getcwd(), os.pardir)
cbaa_path = os.path.join(cbaa_path, os.pardir)
sys.path.insert(0, cbaa_path)
from task_allocation.cbaa import CBAA

class ControllerSuperclass:
    def __init__(self, name, robot_type):
        '''
        Super class for the simpleactions generators, with the most common functionalities. Each robot type
        class extends this class
        '''
        # create the Robot instance.
        self.robot = Robot()
        self.robot_name = name
        self.robot_type = robot_type
        # get the time step of the current world.
        self.timestep = int(self.robot.getBasicTimeStep())

        self.available_simpleactions_functions = {}
        self.simpleactions = []

        # List of simpleaction from the configuration file
        self.config_simpleactions_names_cost = {}

        # Initiate the topics subscriber
        self.binding_key = f"{name}_queue"
        self.exchange = "routing_exchange"
        self.exchange_type = "direct"
        self.simpleactions_subscriber = MessageSubscriber(
            self.binding_key, self.exchange, self.exchange_type, self.execute_simpleactions_callback
        )

        # Create subscriber for listening to the CBAA task allocation updates
        # we can give it an empty binding key, because the 'fanout' exchange will ignore its value
        # either way
        cbaa_exchange_name = "cbaa_initiate_exchange"
        cbaa_exchange_type = "fanout"
        self.cbaa_subscriber = MessageSubscriber(
            "", cbaa_exchange_name, cbaa_exchange_type, self.initiate_cbaa_callback
        )

        # Initiate thread for listening to the CBAA task allocation initiation from the server
        cbaa_initiation_communication = threading.Thread(target=self.cbaa_subscriber.subscription)
        cbaa_initiation_communication.start()

        # Create a Subscription for receiving bids from the other robots
        self.cbaa_bids_exchange_name = "cbaa_bids_exchange"
        self.cbaa_bids_subscriber = MessageSubscriber(
            "", self.cbaa_bids_exchange_name, cbaa_exchange_type, self.receive_cbaa_bids_callback
        )
        # Initiate a thread for receiving the bids from the other robots
        cbaa_bids_communication = threading.Thread(target=self.cbaa_bids_subscriber.subscription)
        cbaa_bids_communication.start()

        # Read the config data to get the available simpleactions for this robot type
        self.read_config_data()

        # TODO this should somehow be dynamic
        # self.n_robots = 4
        self.consensus_based_auction_algorithm = CBAA(
            # self.robot_name, self.test_avail_simpleactions, self.n_robots
            "cbaa",self.robot_name, self.config_simpleactions_names_cost, self.n_robots
        )

        print(f"Super class initiated. {self.robot_name}")

    def read_config_data(self):
        """
        Reads the configuration file
        """
        with open(pathlib.Path.cwd().parent.parent / 'config.json') as json_config_file:
            data = json.load(json_config_file)
            self.n_robots = len(data["robots"])
            for x in data["robots"][self.robot_type]["simpleactions"]:
                self.config_simpleactions_names_cost[x["name"]] = float(x["cost"])

    def add_available_simpleaction(self, name, function_reference):
        self.available_simpleactions_functions[name] = function_reference

    def execute_simpleactions_callback(self, ch, method, properties, body):
        print(f"{self.robot_name} callback: %r" % body)
        # TODO as for now, the incoming messages are functions calls, separated by ","
        # simpleactions.extend(body.decode('utf-8').split(","))

        # Decode the JSON back to a list
        new_simpleactions = json.loads(body.decode('utf-8'))
        self.simpleactions.extend(new_simpleactions)
        print(f'{self.robot_name} Simpleactions = {self.simpleactions}, type={type(self.simpleactions)}')

        # Now execute the simpleactions
        # for i in range(len(simpleactions)):
        while self.simpleactions:
            sim_act = self.simpleactions.pop(0)
            print(f"sim_act = {sim_act}")
            print(f"Function name = {sim_act['function_name']}, Args = {sim_act['args']}")
            function_name = sim_act['function_name']
            args = sim_act['args']
            # Retrieve the args
            # function_name = sim_act.split('(')[0]
            # args = sim_act.split('(')[1].split(')')[0]
            #
            if not args:
                self.available_simpleactions_functions[function_name]()
                continue
            # Convert the arguments
            if all([x in string.digits for x in args]):
                print(f"{args} is a number")
                args = int(args)
            elif "[" in args or "]" in args:
                # ast.literal_eval will safely evaluate the string representation of a list (with the square brackets
                # as well) to a python list
                args = ast.literal_eval(args)

            self.available_simpleactions_functions[function_name](args)

        print(f"{self.robot_name} finished callback function")

    def receive_cbaa_bids_callback(self, ch, method, properties, body):
        all_bids = json.loads(body)
        print(f"{self.robot_name} received: {all_bids}")
        for other_robot_name, bids in all_bids.items():
            if self.robot_name == other_robot_name:
                # Skip the bid of this robot
                continue
            self.consensus_based_auction_algorithm.receive_other_winning_bids(other_robot_name, bids)

    def publish_bids(self, bids):
        connection = pika.BlockingConnection(
            pika.ConnectionParameters(host='localhost'))
        channel = connection.channel()

        channel.exchange_declare(exchange=self.cbaa_bids_exchange_name, exchange_type='fanout')

        # message = f"Bids by {self.robot_name}: {bids}"
        message = {self.robot_name : bids}
        channel.basic_publish(exchange=self.cbaa_bids_exchange_name, routing_key='', body=json.dumps(message))
        # print(" [x] Sent %r" % message)
        connection.close()

    def initiate_cbaa_callback(self, ch, method, properties, body):
        print(f'{self.robot_name} initiate cbaa callback function, received {body}')
        # time.sleep(1)
        # self.publish_bids()
        new_available_tasks = json.loads(body.decode('utf-8'))
        # print(f"new_available_tasks = {new_available_tasks}")
        # new_task_lists = []
        # for task in new_available_tasks:
        #     new_task_lists.append(task["simpleactions"])
        # print(f"new_task_list = {new_task_lists}")
        self.consensus_based_auction_algorithm.add_task_list(new_available_tasks)
        # self.consensus_based_auction_algorithm.add_task_list(new_task_lists)

        # Phase 1
        self.consensus_based_auction_algorithm.select_task()

        # Phase 2
        # self.consensus_based_auction_algorithm.update_task()
        bids = self.consensus_based_auction_algorithm.get_winning_bids()
        self.publish_bids(bids)

        self.consensus_based_auction_algorithm.confirm_all_bids(self.robot_name)

        self.consensus_based_auction_algorithm.update_task()

        # Finally, publish the results
        # winning_robots = self.consensus_based_auction_algorithm.winning_robots
        # self.send_cbaa_result_to_server(winning_robots)
        self.consensus_based_auction_algorithm.post_results()
        # After posting the consensus to the server, reset the values in the CBAA Class
        self.consensus_based_auction_algorithm.cleanup()

    # def send_cbaa_result_to_server(self, winning_robots):
    #     """
    #     Publish the winning robots to the server, using the 'routing_exchange' exchange which is commonly used
    #     to publish the simpleactions to the server
    #     """
    #     connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
    #     channel = connection.channel()
    #
    #     exchange_name = 'routing_exchange'
    #     routing_key = 'server_queue'
    #     message = json.dumps(winning_robots)
    #
    #     channel.exchange_declare(exchange=exchange_name, exchange_type='direct')
    #     channel.basic_publish(exchange=exchange_name, routing_key=routing_key, body=message)
    #     print(f"{self.robot_name} published it winning bid list")
    #     connection.close()


def solution(targets):
    answer = 0
    end = 0
    targets.sort(key=lambda x:(x[1], x[0]))

    for s, e in targets:
        if not answer or s >= end:
            answer += 1
            end = e
    return answer

'''
# 그리디 문제
# 백준 (1931) 회의실 배정하기 문제와 유사

1. targets 배열을 폭격 미사일의 종료 지점, 시작 지점 기준으로 정렬한다.
2. 첫 번째 원소는 answer를 1 증가하고, 종료 지점 인덱스를 현재 원소의 종료 지점으로 바꾼다.
3. 다음 원소부터는 다음을 만족한다.
3-1. 폭격 미사일의 시작 지점이 이전 폭격 미사일 종료 지점 인덱스보다 적다면 같은 요격미사일로 격추가 가능하기 때문에 건너뛴다.
3-2. 폭격 미사일의 시작 지점이 이전 폭격 미사일 종료 지점 인덱스보다 크거나 같다면 (개구간 조건)으로 다른 요격 미사일로 격추해야하기 때문에 answer를 1 증가한다.

'''


from Tkinter import *
import pygame.mixer
from time import sleep

mixer = pygame.mixer
mixer.init()

sound_file = "50459_M_RED_Nephlimizer.wav"
track = mixer.Sound(sound_file)

def track_stop():
    track.stop()

def track_start():
    track.play(loops = -1)
    sleep(2)
    track.set_volume(0.9)
    sleep(2)
    track.set_volume(0.1)
    sleep(2)
    track.stop()

app = Tk()
app.title("Head First Mix")

stop_botton = Button(app, command = track_stop, text = "Stop")
stop_botton.pack(side = RIGHT)

start_button = Button(app, command = track_start, text = "Start")
start_button.pack(side = LEFT)

app.geometry('255x100+200+100')
app.mainloop()


import time
import numpy as np
t0 = time.process_time()
with open("binary_file2", mode='rb') as file:
    bytes_data = file.read()
    array_data = np.frombuffer(bytes_data, dtype='b', count=bytes_data.__len__())
t1=time.process_time()-t0
print("Local FS READING TIME : ",t1)
print('NB PIXELS :',len(array_data))


import socket
import json
import win32api
import wx
import numpy as np
from time import sleep

client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
IPADRESS = "192.168.1.137"

app = wx.App(False) # the wx.App object must be created first.
width, height = wx.GetDisplaySize()
'''
def getColorAndPower(x ,y):
    x_center = width / 2
    y_center = height / 2

    x, y = x - x_center, y_center - y

    r = (x **2 + y**2) ** 0.5
    r_scaled = r / min(width / 2, height / 2) * 100
    theta = np.arctan(y/x) * 180 / np.pi
    #print(r_scaled, theta)
    if(theta < 90 and theta > 30):
        color = "red"
    if(theta < 30 and theta > -30):
        color = "green"
    if(theta < -30 and theta > -90):
        color = "blue"

    if(r_scaled < 30):
        r_scaled = 0

    power = r_scaled
    print(color, power)
    return color, power

while 1:
    try:
        x, y = win32api.GetCursorPos()

        color, power = getColorAndPower(x, y)
        data = json.dumps({"color": color, "power": power }).encode('utf8')
        client_socket.sendto(data, (IPADRESS,6666))

        #print ("Sending request")
    except Exception as ex:
        print(ex)

'''

def sendData(color, power):
    data = json.dumps({"color": color, "power": power }).encode('utf8')
    client_socket.sendto(data, (IPADRESS,6666))

def setColor(R, G, B):
    sendData("red", R)
    sendData("green", G)
    sendData("blue", B)

while 1:
    try:

        setColor(0, 0, 255)

    except Exception as ex:
        print(ex)

client_socket.close()


#!/usr/bin/python
import sys
def max_list(lt):
    temp = 0
    for i in lt:
        if lt.count(i) > temp:
            max_str = i
            temp = lt.count(i)
    return max_str
try:
    # print("please input")
    if __name__ == "__main__":
        strList = []
        for line in sys.stdin:  # 当没有接受到输入结束信号就一直遍历每一行
            tempStr = line.split()  # 对字符串利用空字符进行切片
            strList.extend(tempStr)  # 把每行的字符串合成到列表
        n = strList[1:]
        # print(n)
        length = len(n)
    if n.count(max_list(n)) > length / 2:
        print(max_list(n))
except:
    pass


from django.shortcuts import render
from order.models import Order
from parse_data.models import Product
from user_admin.models import User
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
import plotly.graph_objs as go
from plotly.offline import plot

def is_admin(request):
    user_id = request.COOKIES.get('userid', None)

    if user_id:
        try:
            user = User.objects.get(id=user_id)
            if user.is_admin:
                return True
        except User.DoesNotExist:
            pass

    return False

def list(request):
    if not is_admin(request):
        return render(request, 'not_admin.html')
    order_list = Order.objects.all().order_by('id')
    # Pagination
    paginator = Paginator(order_list, 10)  # Display 10 products per page
    page = request.GET.get('page') or 1  # If the requested page number is not set or is an empty string, set to 1

    try:
        orders = paginator.page(page)
    except PageNotAnInteger:
        # If the requested page number is not an integer, the first page is displayed
        orders = paginator.page(1)
    except EmptyPage:
        # If the requested page number is out of range, the last page will be displayed
        orders = paginator.page(paginator.num_pages)

    return render(request, 'admin_list.html',{'orders':orders})

def userList(request):
    if not is_admin(request):
        return render(request, 'not_admin.html')
    user_list = User.objects.all().order_by('id')
    # Pagination
    paginator = Paginator(user_list, 10)  # Display 10 products per page
    page = request.GET.get('page') or 1  # If the requested page number is not set or is an empty string, set to 1

    try:
        users = paginator.page(page)
    except PageNotAnInteger:
        # If the requested page number is not an integer, the first page is displayed
        users = paginator.page(1)
    except EmptyPage:
        # If the requested page number is out of range, the last page will be displayed
        users = paginator.page(paginator.num_pages)

    return render(request, 'user_list.html',{'users':users})

def dashboard(request):
    if not is_admin(request):
        return render(request, 'not_admin.html')
    orders = Order.objects.all().order_by('order_date')
    data = [
        go.Scatter(
            x=[order.order_date for order in orders],
            y=[order.product_quantity for order in orders],
            name='Quantity',
            mode='lines'
        ),
        go.Scatter(
            x=[order.order_date for order in orders],
            y=[order.product_price for order in orders],
            name='Price',
            mode='lines'
        )
    ]
    layout = go.Layout(
        title='Sales Over Time',
        xaxis=dict(title='Date'),
        yaxis=dict(title='Sales')
    )
    chart = plot(go.Figure(data=data, layout=layout), output_type='div')

    return render(request, 'dashboard.html', {'chart': chart})


import time
from telegram import *

import Diploma.Get_all as ga
import Diploma.keyboards.Feed as kbf
import Diploma.keyboards.Toys as kbt

# обработчик всех кнопок со всех клавиатур
def keyboards_callback_handler(bot: Bot, update: Update, chat_data=None, **kwargs):
    query = update.callback_query
    data = query.data

    kbf.feed(query, data, bot,
             query['message']['chat']['id'],
             [kbf.order_feed[0], kbf.order_feed[1], kbf.order_feed[2],
              kbf.order_feed[3], kbf.order_feed[4], kbf.order_feed[5]],
             time.asctime())

    kbt.toys(query, data, bot,
             query['message']['chat']['id'],
             [kbt.order_toys[0], kbt.order_toys[1], kbt.order_toys[2],
              kbt.order_toys[3], kbt.order_toys[4], kbt.order_toys[5]],
             time.asctime())

    # print('query from')
    # print(query['message']['message_id'])

    if data == 'New order':
        query.edit_message_text(text='Choose a category:',
                                reply_markup=ga.category())


from typing import Optional

import boto3

from app.config import AWS_REGION
from .data import AUTHORS
from moto import mock_dynamodb

@mock_dynamodb
def get_dynamodb_table(table_name: str):
    dynamodb = boto3.resource("dynamodb", region_name=AWS_REGION)
    return dynamodb.Table(table_name)

@mock_dynamodb
def setup_db() -> None:
    dynamodb = boto3.client("dynamodb", region_name=AWS_REGION)

    dynamodb.create_table(
        TableName='Authors',
        BillingMode='PAY_PER_REQUEST',
        KeySchema=[
            {
                'AttributeName': 'name',
                'KeyType': 'HASH'
            }
        ],
        AttributeDefinitions=[
            {
                'AttributeName': 'name',
                'AttributeType': 'S'
            },
            {
                'AttributeName': 'country',
                'AttributeType': 'S'
            }
        ],
        GlobalSecondaryIndexes=[
            {
                'IndexName': 'GSI1',
                'KeySchema': [
                    {
                        'AttributeName': 'name',
                        'KeyType': 'HASH'
                    },
                    {
                        'AttributeName': 'country',
                        'KeyType': 'RANGE'
                    }
                ],
                'Projection': {
                    'ProjectionType': 'ALL'
                }
            }
        ],
    )

@mock_dynamodb
def add_item(table_name: str, item) -> None:
    table = get_dynamodb_table(table_name)
    table.put_item(Item=item)

@mock_dynamodb
def get_item(table_name: str, keys) -> Optional[dict]:
    table = get_dynamodb_table(table_name)
    response = table.get_item(Key=keys)

    if "Item" not in response:
        return None

    return response["Item"]

@mock_dynamodb
def populate_authors():

    for author in AUTHORS:
        add_item("Authors", author)


# 11. Container With Most Water
# Medium
# 23.7K
# 1.3K
# Companies
# You are given an integer array height of length n. There are n vertical lines drawn such that the two
# endpoints of the ith line are (i, 0) and (i, height[i]).

# Find two lines that together with the x-axis form a container, such that the container contains the most water.

# Return the maximum amount of water a container can store.

# Notice that you may not slant the container.

# Example 1:

# Input: height = [1,8,6,2,5,4,8,3,7]
# Output: 49
# Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water
# (blue section) the container can contain is 49.
# Example 2:

# Input: height = [1,1]
# Output: 1

def most_water(arr):

    p1, p2 = 0, len(arr)-1
    largest_space = 0

    while p1 < p2:

        temp = (p2-p1) * min(arr[p1],arr[p2])
        if temp > largest_space:
            largest_space = temp
        if arr[p2] >= arr[p1]:
            p1 += 1
        elif arr[p2] <= arr[p1]:
            p2 -= 1

    return largest_space

#input = list
#output = area of the shape(int)
#two pointer algorithm
#define a variable that stores the largest container
#while loop to go thru each elements and compare them with each other.
#if statement to check if the area computed is larger than the one defined earlier

print(most_water([1,1]))


import pytest

from application.crud import room as crud_room, booking as crud_booking
from application.database.models import Booking
from application.dto import BookingIn, RoomIn

def test_booking_create_success(client, test_db, room_input, booking_input):
    room = crud_room.save_room(test_db, RoomIn(**room_input))

    input_data = {**booking_input, 'room_id': room.id}
    response = client.post('/booking/', json=input_data)

    assert response.status_code == 201

    data = response.json()
    expected_data = BookingIn(**input_data)
    assert 'id' in data

    booking = test_db.query(Booking).get(data['id'])
    assert booking.begin_date == expected_data.begin_date
    assert booking.end_date == expected_data.end_date
    assert booking.room_id == expected_data.room_id

@pytest.mark.parametrize('field', ['begin_date', 'end_date', 'room_id'])
def test_booking_create_without_required_field(client, booking_input, field):
    input_data = {**booking_input}
    del input_data[field]
    response = client.post('/booking/', json=input_data)

    assert response.status_code == 422

@pytest.mark.parametrize('begin_date', [None, '', '2021-01-0', '2021-02-30'])
def test_booking_create_invalid_begin_date(client, booking_input, begin_date):
    response = client.post('/booking/', json={**booking_input, 'begin_date': begin_date})

    assert response.status_code == 422

@pytest.mark.parametrize('end_date', [None, '', '2021-01-0', '2021-02-30'])
def test_booking_create_invalid_end_date(client, booking_input, end_date):
    response = client.post('/booking/', json={**booking_input, 'end_date': end_date})

    assert response.status_code == 422

@pytest.mark.parametrize('room_id', [None, '', 'N'])
def test_booking_create_invalid_room_id(client, booking_input, room_id):
    response = client.post('/booking/', json={**booking_input, 'room_id': room_id})

    assert response.status_code == 422

def test_booking_create_end_date_preceds_begin_date(client):
    response = client.post('/booking/', json={
        'begin_date': '2021-01-07',
        'end_date': '2021-01-01',
        'room_id': 1
    })

    assert response.status_code == 422

@pytest.mark.parametrize('dates', [
    # inside of the date range
    {'begin_date': '2021-01-07', 'end_date': '2021-01-13'},
    {'begin_date': '2021-01-06', 'end_date': '2021-01-14'},
    {'begin_date': '2021-01-07', 'end_date': '2021-01-14'},
    # outside of the date range
    {'begin_date': '2021-01-06', 'end_date': '2021-01-15'},
    {'begin_date': '2021-01-06', 'end_date': '2021-01-14'},
    {'begin_date': '2021-01-07', 'end_date': '2021-01-15'},
    # crosses the left border
    {'begin_date': '2021-01-06', 'end_date': '2021-01-13'},
    {'begin_date': '2021-01-06', 'end_date': '2021-01-07'},
    # crosses the right border
    {'begin_date': '2021-01-13', 'end_date': '2021-01-15'},
    {'begin_date': '2021-01-14', 'end_date': '2021-01-15'},
])
def test_booking_create_overlapping_dates(client, test_db, room_input, dates):
    room = crud_room.save_room(test_db, RoomIn(**room_input))

    booking_1 = {
        'begin_date': '2021-01-07',
        'end_date': '2021-01-14',
        'room_id': room.id
    }
    crud_booking.save_booking(test_db, BookingIn(**booking_1))

    booking_2 = {
        **dates,
        'room_id': room.id
    }
    response = client.post('/booking/', json=booking_2)

    assert response.status_code == 422


from __future__ import print_function, division

from math import exp, expm1
import argparse

from jsonctmctree.interface import process_json_in

# high population boundary behaviors
WRAP = 'wrap'
ABSORB = 'absorb'
BLOCK = 'block'

def gen_speciation_triples(lam, n, boundary):
    for i in range(1, n-1):
        yield [1, i], [1, i+1], i*lam
    if boundary == WRAP:
        yield [1, n-1], [0, 0], (n-1)*lam

def gen_extinction_triples(mu, n, boundary):
    yield [1, 1], [0, 0], mu
    for i in range(2, n-1):
        yield [1, i], [1, i-1], i*mu
    if boundary in {WRAP, BLOCK}:
        yield [1, n-1], [1, n-2], (n-1)*mu

def get_scene(edge_rates, mu, lam, n, boundary):
    leaves = [2, 3, 4]
    tree = dict(
            row_nodes = [0, 0, 1, 1],
            column_nodes = [1, 2, 3, 4],
            edge_rate_scaling_factors = edge_rates,
            edge_processes = [0, 0, 0, 0])
    speciation_triples = list(gen_speciation_triples(lam, n, boundary))
    extinction_triples = list(gen_extinction_triples(mu, n, boundary))
    triples = speciation_triples + extinction_triples
    row_states, column_states, transition_rates = zip(*triples)
    scene = dict(
            node_count = 5,
            process_count = 1,
            state_space_shape = [2, n],
            tree = tree,
            root_prior = dict(
                states = [[1, 1]],
                probabilities = [1.0],
                ),
            process_definitions = [dict(
                row_states = row_states,
                column_states = column_states,
                transition_rates = transition_rates,
                )],
            observed_data = dict(
                nodes = leaves,
                variables = [0, 0, 0],
                iid_observations = [[1, 1, 1]],
                )
            )
    return scene

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--n', type=int, default=1000, help='population size')
    parser.add_argument('--mu', type=float, default=0.3, help='extinction')
    parser.add_argument('--lam', type=float, default=0.5, help='speciation')
    args = parser.parse_args()

    n = args.n
    mu = args.mu
    lam = args.lam

    edge_rates = [5, 10, 5, 5]
    wrap_scene = get_scene(edge_rates, mu, lam, n, WRAP)
    absorb_scene = get_scene(edge_rates, mu, lam, n, ABSORB)

    # Log likelihood.
    logl_request = dict(property='snnlogl')

    # Unweighted sum over observations and over edges,
    # and weighted sum over transitions consisting of the unweighted sum
    # over transitions corresponding to extinction events.
    extinction_request = dict(
        property='ssntran',
        transition_reduction = dict(
            row_states = [[1, i] for i in range(2, n)],
            column_states = [[1, i-1] for i in range(2, n)],
            weights = [1]*(n-2),
        ))

    # Unweighted sum over observations, and weighted sum over states.
    extant_request = dict(
        property='snwnode',
        state_reduction = dict(
            states = [[1, i] for i in range(n)],
            weights = range(n),
            ))

    # Unweighted sum over observations, weighted sum over edges,
    # and weighted sum over states.
    dwell_request = dict(
        property='swwdwel',
        edge_reduction = dict(
            edges = [0, 1, 2, 3],
            weights = edge_rates),
        state_reduction = dict(
            states = [[1, i] for i in range(n)],
            weights = range(n)))

    # Compute only the likelihood for the absorbing high population boundary.
    j_out = process_json_in(dict(scene=absorb_scene, requests=[logl_request]))
    absorb_likelihood = exp(j_out['responses'][0])

    # Compute more stuff for the wrapping boundary.
    j_in = dict(
            scene=wrap_scene,
            requests=[
                logl_request,
                extinction_request,
                extant_request,
                dwell_request,
                ])
    j_out = process_json_in(j_in)

    logl, extinction, extant, dwell = j_out['responses']
    wrap_likelihood = exp(logl)
    print('gene population limit:', n)
    print('gene birth rate:', lam)
    print('gene death rate:', mu)
    print('likelihood:', wrap_likelihood)
    print('upper bound likelihood for unbounded population:', absorb_likelihood)
    print('unconditional probability of exceeding the population cap:',
            absorb_likelihood - wrap_likelihood)
    print('expected number of extinctions:', extinction)
    print('expected number of extant lineages at each node:')
    for i, x in enumerate(extant):
        print(i, ':', x)
    print('expected total size of the gene tree:', dwell)

main()


from evolution_compositionality_under_noise import *

###################################################################################################################
# ALL PARAMETER SETTINGS GO HERE:

meanings = ['02', '03', '12', '13']  # all possible meanings
possible_form_lengths = np.array([2, 4])  # all possible form lengths
forms_without_noise = create_all_possible_forms(2, possible_form_lengths)  # all possible forms, excluding their
# possible 'noisy variants'
noisy_forms = create_all_possible_noisy_forms(forms_without_noise)
# all possible noisy variants of the forms above
all_forms_including_noisy_variants = forms_without_noise + noisy_forms  # all possible forms, including both
# complete forms and noisy variants

error = 0.05  # the probability of making a production error (Kirby et al., 2015 use 0.05)

turnover = True  # determines whether new individuals enter the population or not
popsize = 2  # If I understand it correctly, Kirby et al. (2015) used a population size of 2: each generation is simply
# a pair of agents.
runs = 1  # the number of independent simulation runs (Kirby et al., 2015 used 100)
generations = 1000  # the number of generations (Kirby et al., 2015 used 100)
initial_language_type = 'degenerate'  # set the language class that the first generation is trained on

interaction = 'taking_turns'  # can be set to either 'random' or 'taking_turns'. The latter is what Kirby et al. (2015)
# used, but NOTE that it only works with a popsize of 2!
n_parents = 'single'  # determines whether each generation of learners receives data from a single agent from the
# previous generation, or from multiple (can be set to either 'single' or 'multiple').

burn_in = round(generations / 2)  # the burn-in period that is excluded when calculating the mean distribution over
# languages after convergence

pickle_file_path = "pickles/"

# THE FOLLOWING PARAMETERS SHOULD ONLY BE SET IF __name__ == '__main__', BECAUSE THEY ARE RETRIEVED FROM THE INPUT
# ARGUMENTS GIVEN TO THE PYTHON SCRIPT WHEN RUN FROM THE TERMINAL OR FROM A .SH SCRIPT:
if __name__ == '__main__':

    b = int(sys.argv[1])  # the bottleneck (i.e. number of meaning-form pairs the each pair gets to see during training
    # (Kirby et al. used a bottleneck of 20 in the body of the paper.
    rounds = 2 * b  # Kirby et al. (2015) used rounds = 2*b, but SimLang lab 21 uses 1*b
    print('')
    print("b is:")
    print(b)

    compressibility_bias = str_to_bool(sys.argv[2])  # Setting the 'compressibility_bias' parameter based on the
    # command-line input #NOTE: first argument in sys.argv list is always the name of the script; Determines whether
    # agents have a prior that favours compressibility, or a flat prior
    print('')
    print("compressibility_bias (i.e. learnability pressure) is:")
    print(compressibility_bias)

    noise_prob = float(sys.argv[3])  # Setting the 'noise_prob' parameter based on the command-line input #NOTE: first
    # argument in sys.argv list is always the name of the script  # the probability of environmental noise obscuring
    # part of an utterance
    print('')
    print("noise_prob is:")
    print(noise_prob)

    gamma = float(sys.argv[4])  # parameter that determines strength of ambiguity penalty (Kirby et al., 2015 used
    # gamma = 0 for "Learnability Only" condition, and gamma = 2 for both "Expressivity Only", and "Learnability and
    # Expressivity" conditions
    print('')
    print("gamma is:")
    print(gamma)

    delta = float(sys.argv[5])  # parameter that determines strength of effort penalty (i.e. how strongly speaker
    # tries to avoid using long utterances)
    print('')
    print("delta is:")
    print(delta)

###################################################################################################################
# NOW SOME FUNCTIONS THAT HANDLE PRODUCTION, NOISY PRODUCTION, AND RECEPTION WITH AND WITHOUT REPAIR:

def production_likelihoods_with_noise_and_minimal_effort(language, topic, meaning_list, forms, noisy_variants, ambiguity_penalty, effort_penalty, error_prob, prob_of_noise):
    """
    Calculates the production probabilities for each of the possible forms (including both forms without noise and all
    possible noisy variants) given a language and topic, and the probability of environmental noise

    :param language: list of forms that has same length as list of meanings (global variable), where each form is
    mapped to the meaning at the corresponding index
    :param topic: the index of the topic (corresponding to an index in the globally defined meaning list) that the
    speaker intends to communicate
    :param meaning_list: list containing all possible meanings; corresponds to global variable 'meanings'
    :param forms: list of all possible forms *excluding* their noisy variants
    :param noisy_variants: list of all possible noisy variants of forms
    :param ambiguity_penalty: parameter that determines the strength of the penalty on ambiguity (gamma)
    :param effort_penalty: parameter that determines the strength of the penalty on speaker effort (i.e. utterance
    length)
    :param error_prob: the probability of making an error in production
    :param prob_of_noise: the probability of environmental noise masking part of the utterance
    :return: 1D numpy array containing a production probability for each possible form (where the index of the
    probability corresponds to the index of the form in the global variable "all_forms_including_noisy_variants")
    """
    all_possible_forms = forms + noisy_variants
    for m in range(len(meaning_list)):
        if meaning_list[m] == topic:
            topic_index = m
    correct_form = language[topic_index]
    error_forms = list(forms)  # This may seem a bit weird, but a speaker should be able to produce *any*
    # form as an error form right? Not limited to only the other forms that exist within their language? (Otherwise a
    # speaker with a degenerate language could never make a production error).
    error_forms = remove_all_instances(error_forms, correct_form)
    if len(error_forms) == 0:  # if the list of error_forms is empty because the language is degenerate
        error_forms = language  # simply choose an error_form from the whole language
    noisy_variants_correct_form = create_noisy_variants(correct_form)
    noisy_variants_error_forms = []
    for error_form in error_forms:
        noisy_variants = create_noisy_variants(error_form)
        noisy_variants_error_forms = noisy_variants_error_forms+noisy_variants
    ambiguity = 0
    for f in language:
        if f == correct_form:
            ambiguity += 1
    # prop_to_prob_correct_form_complete = ((1./ambiguity) ** ambiguity_penalty) * (1. - error_prob) * (1 - prob_of_noise)
    # prop_to_prob_error_form_complete = error_prob / (len(forms) - 1) * (1 - prob_of_noise)
    # prop_to_prob_correct_form_noisy = ((1. / ambiguity) ** ambiguity_penalty) * (1. - error_prob) * (prob_of_noise / len(noisy_variants))
    # prop_to_prob_error_form_noisy = error_prob / (len(forms) - 1) * (1 - prob_of_noise) * (prob_of_noise / len(noisy_variants))
    prop_to_prob_per_form_array = np.zeros(len(all_possible_forms))
    for i in range(len(all_possible_forms)):
        possible_form = all_possible_forms[i]
        if possible_form == correct_form:
            prop_to_prob_per_form_array[i] = ((1./ambiguity) ** ambiguity_penalty) * ((1./len(possible_form)) ** effort_penalty) * (1. - error_prob) * (1 - prob_of_noise)
        elif possible_form in noisy_variants_correct_form:
            prop_to_prob_per_form_array[i] = ((1. / ambiguity) ** ambiguity_penalty) * ((1./len(possible_form)) ** effort_penalty) * (1. - error_prob) * (prob_of_noise / len(noisy_variants))
        elif possible_form in noisy_variants_error_forms:
            prop_to_prob_per_form_array[i] = error_prob / (len(forms) - 1) * (1 - prob_of_noise) * (prob_of_noise / len(noisy_variants))
        else:
            prop_to_prob_per_form_array[i] = error_prob / (len(forms) - 1) * (1 - prob_of_noise)
    return prop_to_prob_per_form_array

# And finally, let's write a function that actually produces an utterance, given a language and a topic:
def produce_with_minimal_effort(language, topic, ambiguity_penalty, effort_penalty, error_prob, prob_of_noise):
    """
    Produces an actual utterance, given a language and a topic

    :param language: list of forms_without_noisy_variants that has same length as list of meanings (global variable),
    where each form is mapped to the meaning at the corresponding index
    :param topic: the index of the topic (corresponding to an index in the globally defined meaning list) that the
    speaker intends to communicate
    :param ambiguity_penalty: parameter that determines the strength of the penalty on ambiguity (gamma)
    :param effort_penalty: parameter that determines the strength of the penalty on speaker effort (i.e. utterance
    length)
    :param error_prob: the probability of making an error in production
    :param prob_of_noise: the probability of noise happening (only relevant when noise_switch is set to True);
    corresponds to global variable 'noise_prob'
    :return: an utterance. That is, a single form chosen from either the global variable "forms_without_noise" (if
    noise is False) or the global variable "all_forms_including_noisy_variants" (if noise is True).
        """
    prop_to_prob_per_form_array = production_likelihoods_with_noise_and_minimal_effort(language, topic, meanings, forms_without_noise, noisy_forms, ambiguity_penalty, effort_penalty, error_prob, prob_of_noise)
    prob_per_form_array = np.divide(prop_to_prob_per_form_array, np.sum(prop_to_prob_per_form_array))
    utterance = np.random.choice(all_forms_including_noisy_variants, p=prob_per_form_array)
    return utterance

def receive_with_repair_open_only(language, utterance):
    """
    Receives and utterance and gives a response, which can either be an interpretation or a repair initiator. How likely
    these two response types are to happen depends on the settings of the paremeters 'mutual_understanding' and
    'minimal_effort' (and, if minimal_effort is set to True, the parameter 'cost_vector'). These three parameters are
    all assumed to be global variables.

    :param language: list of forms_without_noisy_variants that has same length as list of meanings (global variable),
    where each form is mapped to the meaning at the corresponding index
    :param utterance: an utterance (string)
    :return: a response, which can either be an interpretation (i.e. meaning) or a repair initiator ('??'). The listener
    initiates repair whenever there is any ambiguity about how to interpret the utterance according to the language
    (either caused by noise or just by ambiguity in the language itself).
    """
    if '_' in utterance:
        compatible_forms = noisy_to_complete_forms(utterance, forms_without_noise)
        possible_interpretations = find_possible_interpretations(language, meanings, compatible_forms)
    else:
        possible_interpretations = find_possible_interpretations(language, meanings, [utterance])
    if len(possible_interpretations) == 0:
        possible_interpretations = meanings
    if len(possible_interpretations) == 1:
        response = possible_interpretations[0]
    else:
        response = '??'
    return response

# AND NOW FOR THE FUNCTIONS THAT DO THE BAYESIAN LEARNING:

def update_posterior_from_cache(log_posterior, log_likelihood_cache, topic, utterance, meaning_list, all_possible_forms):
    """
    Takes a LOG posterior probability distribution and a <topic, utterance> pair, and updates the posterior probability
    distribution accordingly

    :param log_posterior: 1D numpy array containing LOG posterior probability values for each hypothesis
    :param log_likelihood_cache: 3D numpy array with axis 0 = meanings, axis 1 = all possible forms, and axis 2 = LOG
    likelihood of corresponding <meaning, form> pair for each hypothesis
    :param topic: a topic (string from the global variable meanings)
    :param utterance: an utterance (string from the global variable forms (can be a noisy form if parameter noise is
    True)
    :param meaning_list: list containing all possible meanings; corresponds to global variable 'meanings'
    :param all_possible_forms: list of all possible forms INCLUDING noisy variants; corresponds to global variable
    'all_forms_including_noisy_variants'
    :return: the updated (and normalized) log_posterior (1D numpy array)
    """
    # First let's find out what the index of the meaning is:
    for i in range(len(meanings)):
        if meaning_list[i] == topic:
            meaning_index = i
    # Then, let's find out what the index of the utterance is in the list of all possible forms (including the noisy
    # variants):
    for i in range(len(all_possible_forms)):
        if all_possible_forms[i] == utterance:
            utterance_index = i
    # Now, let's retrieve the corresponding log_likelihood values for this particular <meaning, form> pair form the
    # log_likelihood_cache, and update the posterior accordingly (addition in logspace == multiplication in probability
    # space).
    new_log_posterior_new_method = np.add(log_posterior, log_likelihood_cache[meaning_index][utterance_index])
    new_log_posterior_normalized_new_method = np.subtract(new_log_posterior_new_method,
                                                          scipy.special.logsumexp(new_log_posterior_new_method))
    return new_log_posterior_normalized_new_method

def population_communication_mutual_understanding(population, n_rounds, ambiguity_penalty, effort_penalty, prob_of_noise, hypotheses, log_likelihood_cache):
    """
    Takes a population, makes it communicate for a number of rounds (where agents' posterior probability distribution
    is updated every time the agent gets assigned the role of hearer)

    :param population: a population (1D numpy array), where each agent is simply a LOG posterior probability
    distribution
    :param n_rounds: the number of rounds for which the population should communicate; corresponds to global variable
    'rounds'
    :param ambiguity_penalty: parameter which determines the extent to which the speaker tries to avoid ambiguity;
    corresponds to global variable 'gamma'
    :param effort_penalty: parameter that determines the strength of the penalty on speaker effort (i.e. utterance
    length)
    :param prob_of_noise: the probability of noise happening (only relevant when noise_switch == True); corresponds to
    global variable 'noise_prob'
    :param hypotheses: list of all possible languages; corresponds to global parameter 'hypothesis_space'
    :param log_likelihood_cache: 3D numpy array with axis 0 = meanings, axis 1 = all possible forms, and axis 2 = LOG
    likelihood of corresponding <meaning, form> pair for each hypothesis
    :return: (1) the data that was produced during the communication rounds, as a list of (topic, utterance) tuples; (2) the sampled_languages_array which lists the indices of the languages (in the hypotheses list) that was sampled per agent per round; (3) a list of counts of the number of repair initiations
    """
    if n_parents == 'single':
        if len(population) != 2 or interaction != 'taking_turns':
            raise ValueError("OOPS! n_parents = 'single' only works if popsize = 2 and interaction = 'taking_turns'.")
        random_parent_index = np.random.choice(np.arange(len(population)))  # this determines which agent's productions
        # will form the input for the next generation
    data = []
    repair_counts = []
    sampled_languages_array = np.zeros((len(population), n_rounds))
    for i in range(n_rounds):
        if interaction == 'taking_turns':
            if len(population) != 2:
                raise ValueError("OOPS! interaction = 'taking_turns' only works if popsize = 2.")
            if i % 2 == 0:
                speaker_index = 0
                hearer_index = 1
            else:
                speaker_index = 1
                hearer_index = 0
        else:
            pair_indices = np.random.choice(np.arange(len(population)), size=2, replace=False)
            speaker_index = pair_indices[0]
            hearer_index = pair_indices[1]
        topic = random.choice(meanings)
        # whenever a speaker is called upon to produce a utterance, they first sample a language from their
        # posterior probability distribution. So each agent keeps updating their language according to the data
        # received from their communication partner.
        speaker_language, speaker_lang_index = sample(hypotheses, population[speaker_index])
        hearer_language, hearer_lang_index = sample(hypotheses, population[hearer_index])
        if speaker_index == 0:
            sampled_languages_array[0][i] = speaker_lang_index
            sampled_languages_array[1][i] = hearer_lang_index
        else:
            sampled_languages_array[0][i] = hearer_lang_index
            sampled_languages_array[1][i] = speaker_lang_index
        utterance = produce_with_minimal_effort(speaker_language, topic, ambiguity_penalty, effort_penalty, error, prob_of_noise)
        listener_response = receive_with_repair_open_only(hearer_language, utterance)
        counter = 0
        while '?' in listener_response:
            if counter == 3:  # After 3 attempts, the listener stops trying to do repair
                break
            utterance = produce_with_minimal_effort(speaker_language, topic, ambiguity_penalty, effort_penalty, error, prob_of_noise)
            listener_response = receive_with_repair_open_only(hearer_language, utterance)
            counter += 1

        population[hearer_index] = update_posterior_from_cache(population[hearer_index], log_likelihood_cache, topic, utterance, meanings, all_forms_including_noisy_variants)

        if n_parents == 'single':
            if speaker_index == random_parent_index:
                data.append((topic, utterance))
        elif n_parents == 'multiple':
            data.append((topic, utterance))
        repair_counts.append(counter)

    return data, sampled_languages_array, repair_counts

# AND NOW FINALLY FOR THE FUNCTION THAT RUNS THE ACTUAL SIMULATION:

def simulation_repair_vs_redundancy(population, n_gens, n_rounds, bottleneck, pop_size, hypotheses, log_likelihood_cache, class_per_language, log_priors, data, interaction_order, ambiguity_penalty, effort_penalty, prob_of_noise, all_possible_forms):
    """
    Runs the full simulation and returns the total amount of posterior probability that is assigned to each language
    class over generations (language_stats_over_gens) as well as the data that each generation produced (data)

    :param population: the population at generation 0
    :param n_gens: the desired number of generations (int); corresponds to global variable 'generations'
    :param n_rounds: the desired number of communication rounds *within* each generation; corresponds to global variable
    'rounds'
    :param bottleneck: the amount of data (<meaning, form> pairs) that each learner receives
    :param pop_size: the desired size of the population (int); corresponds to global variable 'popsize'
    :param hypotheses: list of all possible languages; corresponds to global variable 'hypothesis_space'
    :param log_likelihood_cache: 3D numpy array with axis 0 = meanings, axis 1 = all possible forms, and axis 2 = LOG
    likelihood of corresponding <meaning, form> pair for each hypothesis
    :param class_per_language: list specifiying the class for each corresponding language in the variable 'hypotheses'
    :param log_priors: the LOG prior probability distribution that each agent should be initialised with
    :param data: the initial data that generation 0 learns from
    :param interaction_order: the order in which agents take turns in interaction (can be set to either 'taking_turns'
    or 'random')
    :param ambiguity_penalty: parameter that determines the extent to which the speaker tries to avoid ambiguity;
    corresponds to global variable 'gamma'
    :param effort_penalty: parameter that determines the strength of the penalty on speaker effort (i.e. utterance
    length)
    :param prob_of_noise: probability of noise (only relevant when noise_switch == True); corresponds to global variable
    'noise_prob'
    :param all_possible_forms: list of all possible forms INCLUDING noisy variants; corresponds to global variable
    'all_forms_including_noisy_variants'
    :return: (1) sampled_languages_over_gens (which contains the indices of the sampled languages per generation per agent per round of interaction); (2) language_stats_over_gens (which contains language stats over generations); (3) data (which contains data over generations over runs); (4) repair_count_over_gens (which tracks the number of repair initiations over generations); and (5) the final population
    """
    sampled_languages_over_gens = np.zeros((n_gens, pop_size, n_rounds))
    language_stats_over_gens = np.zeros((n_gens, int(max(class_per_language)+1)))
    data_over_gens = []
    repair_count_over_gens = []
    for i in range(n_gens):

        print('gen: '+str(i))

        for j in range(pop_size):
            for k in range(bottleneck):
                if interaction_order == 'taking_turns':
                    if len(population) != 2:
                        raise ValueError(
                            "OOPS! interaction = 'taking_turns' only works if popsize = 2.")
                    if bottleneck != len(data):
                        raise ValueError(
                            "UH-OH! data should have the same size as the bottleneck b")
                    meaning, signal = data[k]
                else:
                    meaning, signal = random.choice(data)
                population[j] = update_posterior_from_cache(population[j], log_likelihood_cache, meaning, signal, meanings, all_possible_forms)
        data, sampled_languages_array, repair_count = population_communication_mutual_understanding(population, n_rounds, ambiguity_penalty, effort_penalty, prob_of_noise, hypotheses, log_likelihood_cache)

        sampled_languages_over_gens[i] = sampled_languages_array
        language_stats_over_gens[i] = language_stats(population, possible_form_lengths, class_per_language)
        data_over_gens.append(data)
        repair_count_over_gens.append(repair_count)
        if i == n_gens-1:
            final_pop = population
        if turnover:
            population = new_population(pop_size, log_priors)
    return sampled_languages_over_gens, language_stats_over_gens, data_over_gens, repair_count_over_gens, final_pop

###################################################################################################################
if __name__ == '__main__':

    ###################################################################################################################
    # FIRST LET'S RETRIEVE THE RELEVANT LOG LIKELIHOOD CACHE:

    log_likelihood_cache = pickle.load(open("pickles/log_likelihood_cache_form_lengths_"+convert_array_to_string(possible_form_lengths)+"_noise_prob_"+convert_float_value_to_string(noise_prob)+"_gamma_"+convert_float_value_to_string(gamma)+"_delta_"+convert_float_value_to_string(delta)+"_error_"+convert_float_value_to_string(error)+".p", "rb"))
    print('')
    print("log_likelihood_cache.shape is:")
    print(log_likelihood_cache.shape)

    ###################################################################################################################
    # NOW LET'S RUN THE ACTUAL SIMULATION:

    t0 = time.process_time()

    hypothesis_space = create_all_possible_languages(meanings, forms_without_noise)
    print("number of possible languages is:")
    print(len(hypothesis_space))
    t1 = time.process_time()
    print('')
    print("number of minutes it took to create all languages (i.e. the hypothesis space):")
    print(round((t1-t0)/60., ndigits=2))

    class_per_lang = classify_all_languages(hypothesis_space, forms_without_noise, meanings)
    print("class_per_lang.shape is:")
    print(class_per_lang.shape)

    t2 = time.process_time()
    print('')
    print("number of minutes it took to classify languages:")
    print(round((t2-t1)/60., ndigits=2))

    if compressibility_bias:
        priors = prior(hypothesis_space, forms_without_noise, meanings, possible_form_lengths)
    else:
        priors = np.ones(len(hypothesis_space))
        priors = np.divide(priors, np.sum(priors))
        priors = np.log(priors)

    t3 = time.process_time()
    print('')
    print("number of minutes it took to create prior:")
    print(round((t3-t2)/60., ndigits=2))

    initial_dataset = create_initial_dataset(initial_language_type, b, hypothesis_space, class_per_lang, meanings, possible_form_lengths)  # the data that the first generation learns from
    print('')
    print("initial_dataset is:")
    print(initial_dataset)

    sampled_languages_over_gens_per_run = np.zeros((runs, generations, popsize, rounds))
    language_stats_over_gens_per_run = np.zeros((runs, generations, int(max(class_per_lang)+1)))
    data_over_gens_per_run = []
    repair_count_over_gens_per_run = []
    final_pop_per_run = np.zeros((runs, popsize, len(hypothesis_space)))
    for r in range(runs):

        print('')
        print("r is:")
        print(r)

        population = new_population(popsize, priors)

        sampled_languages_over_gens, language_stats_over_gens, data_over_gens, repair_count_over_gens, final_pop = simulation_repair_vs_redundancy(population, generations, rounds, b, popsize, hypothesis_space, log_likelihood_cache, class_per_lang, priors, initial_dataset, interaction, gamma, delta, noise_prob, all_forms_including_noisy_variants)

        sampled_languages_over_gens_per_run[r] = sampled_languages_over_gens
        language_stats_over_gens_per_run[r] = language_stats_over_gens
        data_over_gens_per_run.append(data_over_gens)
        repair_count_over_gens_per_run.append(repair_count_over_gens)
        final_pop_per_run[r] = final_pop

    timestr = time.strftime("%Y%m%d-%H%M%S")

    pickle_file_name = "Pickle_r_" + str(runs) +"_g_" + str(generations) + "_form_lengths_"+convert_array_to_string(possible_form_lengths)+"_b_" + str(b) + "_rounds_" + str(rounds) + "_pop_size_" + str(popsize) + "_gamma_" + convert_float_value_to_string(gamma) + "_delta_" + convert_float_value_to_string(delta) + "_turnover_" + str(turnover) + "_bias_" + str(compressibility_bias) + "_init_" + initial_language_type + "_noise_prob_" + convert_float_value_to_string(noise_prob) + "_" + timestr
    pickle.dump(sampled_languages_over_gens_per_run, open(pickle_file_path + pickle_file_name + "_sampled_langs" + ".p", "wb"))
    pickle.dump(language_stats_over_gens_per_run, open(pickle_file_path + pickle_file_name + "_lang_stats" + ".p", "wb"))
    pickle.dump(data_over_gens_per_run, open(pickle_file_path+pickle_file_name+"_data"+".p", "wb"))
    pickle.dump(repair_count_over_gens_per_run, open(pickle_file_path + pickle_file_name + "_repairs" + ".p", "wb"))
    pickle.dump(final_pop_per_run, open(pickle_file_path + pickle_file_name + "_final_pop" + ".p", "wb"))

    t4 = time.process_time()

    print('')
    print("number of minutes it took to run simulation:")
    print(round((t4-t3)/60., ndigits=2))

    print('')
    print('results were saved in folder:')
    print(pickle_file_path)

    print('')
    print('using filename:')
    print(pickle_file_name)


import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
from util.LoadDataset import LoadBBDataset
from torch.utils.data import RandomSampler
from torch import optim
import numpy as np

from models.U_Net_3D import U_Net_3D

class U_Net_3D_flag_position(nn.Module):
    def __init__(self):
        super(U_Net_3D_flag_position, self).__init__()
        self.model_flag = U_Net_3D(76, 3)
        self.model_position = U_Net_3D(76, 78)

    def forward(self, factor):
        out_flag, factor = self.model_flag(factor)
        out_position, _ = self.model_position(factor)
        return out_flag, out_position

class FocalLoss(nn.Module):
    """
    This is a implementation of Focal Loss with smooth label cross entropy supported which is proposed in
    'Focal Loss for Dense Object Detection. (https://arxiv.org/abs/1708.02002)'
        Focal_Loss= -1*alpha*(1-pt)^gamma*log(pt)
    :param num_class:
    :param alpha: (tensor) 3D or 4D the scalar factor for this criterion
    :param gamma: (float,double) gamma > 0 reduces the relative loss for well-classified examples (p>0.5) putting more
                    focus on hard misclassified example
    :param smooth: (float,double) smooth value when cross entropy
    :param balance_index: (int) balance class index, should be specific when alpha is float
    :param size_average: (bool, optional) By default, the losses are averaged over each loss element in the batch.
    """

    def __init__(self, num_class, alpha=None, gamma=2, balance_index=-1, smooth=None, size_average=True):
        super(FocalLoss, self).__init__()
        self.num_class = num_class
        self.alpha = alpha
        self.gamma = gamma
        self.smooth = smooth
        self.size_average = size_average

        if self.alpha is None:
            self.alpha = torch.ones(self.num_class, 1)
        elif isinstance(self.alpha, (list, np.ndarray)):
            assert len(self.alpha) == self.num_class
            self.alpha = torch.FloatTensor(alpha).view(self.num_class, 1)
            self.alpha = self.alpha / self.alpha.sum()
        elif isinstance(self.alpha, float):
            alpha = torch.ones(self.num_class, 1)
            alpha = alpha * (1 - self.alpha)
            alpha[balance_index] = self.alpha
            self.alpha = alpha
        else:
            raise TypeError('Not support alpha type')

        if self.smooth is not None:
            if self.smooth < 0 or self.smooth > 1.0:
                raise ValueError('smooth value should be in [0,1]')

    def forward(self, input, target):
        logit = F.softmax(input, dim=1)

        if logit.dim() > 2:
            # N,C,d1,d2 -> N,C,m (m=d1*d2*...)
            logit = logit.view(logit.size(0), logit.size(1), -1)
            logit = logit.permute(0, 2, 1).contiguous()
            logit = logit.view(-1, logit.size(-1))
        target = target.reshape(-1, 1)

        # N = input.size(0)
        # alpha = torch.ones(N, self.num_class)
        # alpha = alpha * (1 - self.alpha)
        # alpha = alpha.scatter_(1, target.long(), self.alpha)
        epsilon = 1e-10
        alpha = self.alpha
        if alpha.device != input.device:
            alpha = alpha.to(input.device)

        idx = target.cpu().long()
        one_hot_key = torch.FloatTensor(target.size(0), self.num_class).zero_()
        one_hot_key = one_hot_key.scatter_(1, idx, 1)
        if one_hot_key.device != logit.device:
            one_hot_key = one_hot_key.to(logit.device)

        if self.smooth:
            one_hot_key = torch.clamp(
                one_hot_key, self.smooth, 1.0 - self.smooth)
        pt = (one_hot_key * logit).sum(1) + epsilon
        logpt = pt.log()

        gamma = self.gamma

        alpha = alpha[idx]
        loss = -1 * alpha * torch.pow((1 - pt), gamma) * logpt

        if self.size_average:
            loss = loss.mean()
        else:
            loss = loss.sum()
        return loss

if __name__ == '__main__':
    slice_width = 49
    slice_num = 162
    epoch = 15
    batch_size = 16
    lr = 0.005
    lr_unchanged = True
    loss_sum = 0
    loss_cnt = 0

    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    torch.backends.cudnn.benchmark = True
    torch.autograd.set_detect_anomaly(True)

    GPM_BB_train_data = LoadBBDataset('../data/Ku/raw_train', slice_width, slice_num)
    train_loader = DataLoader(GPM_BB_train_data, batch_size=batch_size, sampler=RandomSampler(GPM_BB_train_data),
                              pin_memory=True, num_workers=4)

    model = U_Net_3D_flag_position().to(device)

    opt = optim.Adam(model.parameters(), lr=lr)
    # opt = optim.SGD(model.parameters(), lr=lr)
    focal_loss_flag = nn.CrossEntropyLoss().to(device)
    focal_loss_position = nn.CrossEntropyLoss().to(device)

    for epoch_idx in range(0, epoch):
        for batch_idx, (data, target) in enumerate(train_loader):
            data = data.to(device, non_blocking=True).float()
            target = target.to(device, non_blocking=True).long()

            with torch.no_grad():
                flag = data[:, 0, ...].long()
                # zero = data[:, 1, ...].unsqueeze(dim=1).long()
                # zero = torch.zeros(zero.shape[0], 76, zero.shape[-2], zero.shape[-1], dtype=torch.float32).to(
                #     device).scatter_(1, zero, 1)
                # zero_ca = np.zeros((data.shape[0], 76))
                # for i in range(data.shape[0]):
                #     zero_mean = data[i, 1, ...].mean()
                #     norm = lambda x: math.exp(-(x - (zero_mean - 2)) ** 2 / (2 * 15 ** 2))
                #     zero_ca[i] = np.array([norm(j) for j in range(76)])
                # zero_ca = torch.from_numpy(zero_ca).unsqueeze(dim=-1).unsqueeze(dim=-1).to(device).float()
                factor = data[:, 2:, ...]

                BBPeak = target[:, -1, ...]

            out_flag, out_position = model(factor)

            out_position[:, 76, ...] = out_flag[:, 1, ...]
            out_position[:, 77, ...] = out_flag[:, 0, ...]

            opt.zero_grad()
            loss = focal_loss_flag(out_flag, flag) + focal_loss_position(out_position, BBPeak)
            loss.backward()
            opt.step()

            with torch.no_grad():
                loss_sum += loss
                loss_cnt += 1

                if loss_cnt == 100:
                    if lr > 0.001 and epoch_idx >= 5:
                        lr = 0.001
                        print('Change lr to {}'.format(lr))
                        opt = optim.SGD(model.parameters(), lr=lr)
                    elif lr > 0.0001 and epoch_idx >= 10:
                        lr = 0.0001
                        print('Change lr to {}'.format(lr))
                        opt = optim.SGD(model.parameters(), lr=lr)

                    Conv1_weight = model.model_flag.Conv1.down3D[0].weight
                    Conv1_3D_weight = model.model_flag.Conv1_3D[0].weight
                    print('Conv1 weight:\t\tMax:\t{}, Min:\t{}'.format(Conv1_weight.data.abs().max(),
                                                                       Conv1_weight.data.abs().min()))
                    print('Conv1_3D weight:\tMax:\t{}, Min:\t{}'.format(Conv1_3D_weight.data.abs().max(),
                                                                        Conv1_3D_weight.data.abs().min()))
                    print('Conv1 grad:\t\t\tMax:\t{}, Min:\t{}'.format(Conv1_weight.grad.data.abs().max(),
                                                                       Conv1_weight.grad.data.abs().min()))
                    print('Conv1_3D grad:\t\tMax:\t{}, Min:\t{}'.format(Conv1_3D_weight.grad.data.abs().max(),
                                                                        Conv1_3D_weight.grad.data.abs().min()))

                    print('epoch:{}, batch:{}, loss:{}'.format(epoch_idx, batch_idx, loss_sum / loss_cnt))
                    loss_sum = 0
                    loss_cnt = 0

        torch.save(model, 'U_Net_3D.pth')


# -*- coding: utf-8 -*-

"""Ajustando una señal electromiográfica funcional:

-Laboratorio Integrativo de Biomecánica y Fisiología del Esfuerzo,
Escuela de Kinesiología, Universidad de los Andes, Chile-
-Escuela de Ingeniería Biomédica, Universidad de Valparaíso, Chile-
        --Profesores: Oscar Valencia & Alejandro Weinstein--

"""
# Importar librerias
import numpy as np
import pandas as pd
from scipy.signal import butter, filtfilt
import matplotlib.pyplot as plt

def ajusta_emg_func(emg_fun, emg_cvm, fs, fc, filt_ord):
    """Ajusta EMG funcional según contracción voluntaria máxima.

    La función utiliza una señal EMG funcional y otra basada en la
    solicitación de una contracción isométrica voluntaria máxima. Ambas señales
    son procesadas considerando su centralización (eliminación de
    "offset"), rectificación y filtrado (pasa bajo con filtfilt).

    Parameters
    ----------
    emg_fun : array_like
        EMG funcional del músculo a evaluar
    emg_cvm : array_like
        EMG vinculada a la contracción voluntaria máxima del mismo músculo
    fs : float
       Frecuencia de muestreo, en hertz, de la señal EMG. Debe ser la misma
       para ambas señales.
    fc : float
        Frecuencia de corte, en hertz, del filtro pasa-bajos.
    filt_ord : int
        Orden del filtro pasa bajos

    Return
    ------
    emg_fun_norm : array_like
        EMG funcional filtrada y  normalizada
    emg_fun_env_f : array_like
        Envolvente de EMG funcional filtrada
    emg_cvm_envf_ : array_like
        Envolvente de EMG CVM filtrada
    """
    #centralizando y rectificando las señales EMG
    emg_fun_env = abs(emg_fun - np.mean(emg_fun))
    emg_cvm_env = abs(emg_cvm - np.mean(emg_cvm))

    # Filtrado pasa-bajo de las señales
    b, a = butter(int(filt_ord), (int(fc)/(fs/2)), btype = 'low')
    emg_fun_env_f = filtfilt(b, a, emg_fun_env)
    emg_cvm_env_f = filtfilt(b, a, emg_cvm_env)

    #calculando el valor máximo de emg_cvm y ajustando la señal EMG funcional
    emg_cvm_I = np.max(emg_cvm_env_f)
    emg_fun_norm = (emg_fun_env_f / emg_cvm_I) * 100

    return emg_fun_norm, emg_fun_env_f, emg_cvm_env_f

#%%

def plot_emgs(emg_fun, emg_fun_env, emg_fun_norm, emg_cvm, emg_cvm_env,
              fs, f_c, f_orden,
              nombre):
    """Grafica señales de EMG funcional y CVM.

    Parameters
    ----------
    emg_fun : array_like
        EMG funcional.
    emg_fun_env : array_like
        Envolvente del EMG funcional.
    emg_fun_norm : array_like
        EMG funcional normalizada según CVM.
    emg_cvm : array_like
        EMG contracción voluntaria máxima.
    fs : float
        Frecuencia de muestreo, en hertz.
    f_c : float
        Frecuencia de corte del filtro pasa-bajo, en hertz.
    f_orden : int
        Orden del filtro.
    nombre : str
        Nombre del músculo.
    """

    # Vectores de tiempo
    t1 = np.arange(0, len(emg_fun) / fs, 1 / fs)
    t2 = np.arange(0, len(emg_cvm) / fs, 1 / fs)

    fig, (ax1, ax2, ax3) = plt.subplots(3, 1,figsize = (8, 7))

    ax1.plot(t1, emg_fun, 'b', label='Señal bruta')
    ax1.set_title(f'Músculo: {nombre}; filtro aplicado: f_c={f_c} [Hz] y '
                  f'orden {f_orden}')

    ax1.plot(t1, emg_fun_env, 'r', lw=2, label='Señal filtrada')
    ax1.set_ylabel(f'{nombre} Funcional\nAmplitud [V]',fontsize=9)
    ax1.set_ylim(emg_fun.min() - 0.1, emg_fun.max() + 0.1)
    ax1.set_xlim(0, t1.max())
    ax1.grid()
    ax1.legend(loc='upper center', fontsize='x-small', borderpad=None)

    ax2.plot(t2, emg_cvm, 'b', label='Señal bruta')
    ax2.plot(t2, emg_cvm_env, 'r', lw=2, label='Señal filtrada')
    ax2.set_ylabel(f'{nombre} CVM\nAmplitud [V]',fontsize=9)
    ax2.axvline((np.argmax(emg_cvm_env) / fs), color='maroon')
    ax2.text(0.85, 0.95 ,f'Max = {emg_cvm_env.max():.2f}',
             transform=ax2.transAxes, ha="left", va="top")
    ax2.set_ylim(emg_cvm.min() - 0.1, emg_cvm.max() + 0.1)
    ax2.set_xlim(0, t2.max())
    ax2.grid()
    ax2.legend(loc='upper center', fontsize='x-small', borderpad=None)

    ax3.plot(t1, emg_fun_norm, 'g',label='Señal ajustada según CVM')
    ax3.set_ylim(emg_fun_norm.min(), emg_fun_norm.max() + 2)
    ax3.set_xlim(0, t1.max())
    ax3.set_xlabel('Tiempo [s]', fontsize=9)
    ax3.set_ylabel('% EMG CVM')
    ax3.grid()
    ax3.legend(loc='upper center', fontsize='x-small', borderpad=None)

    plt.tight_layout(h_pad=.1)

#%% ejemplo para utilizar funciones

if __name__ == '__main__':
    df_funcional = pd.read_csv('emg_funcional.csv')
    df_cvm = pd.read_csv('emg_cvm.csv')

    musculo = 'GM'
    emg_funcional = df_funcional[musculo].to_numpy()
    emg_cvm = df_cvm[musculo].to_numpy()
    fs = 1e3
    fc, forden = 40, 2
    emg_f_n, emg_f_env, emg_cvm_env = ajusta_emg_func(emg_funcional,
                                                      emg_cvm, fs, fc, forden)

    #imprime el valor máximo de la señal funcional ajustada y la emg_cvm
    print(f'Valor máximo de la señal CVM {emg_cvm_env.max():.2f} V')
    print(f'% de activación máxima de la señal ajustada:{emg_f_n.max():.2f}%')

    plt.close('all')
    plot_emgs(emg_funcional, emg_f_env, emg_f_n, emg_cvm, emg_cvm_env,
              fs, fc, forden, 'GM')
    plt.savefig('emg.png')
    plt.savefig('emg.pdf')
    plt.show()


n = input()
long = len(n)
n = int(n)

for i in range(1, n):
    tmp = 0
    word = str(i)
    for w in word:
        tmp += int(w)
    tmp += i
    if tmp == n:
        print(i)
        break
else:
    print(0)


from __future__ import print_function
import os
import sys
import numpy
import tensorflow as tf
from auto_reg_input import  *
import matplotlib.pyplot as plt

tf.app.flags.DEFINE_integer('training_iteration', 100,
                            'number of training iterations.')
tf.app.flags.DEFINE_integer('model_version', 1, 'version number of the model.')
tf.app.flags.DEFINE_string('work_dir', './models/', 'Working directory.')
FLAGS = tf.app.flags.FLAGS

def main(_):
    if len(sys.argv) < 2 or sys.argv[-1].startswith('-'):
    	print('Usage: mnist_export.py [--training_iteration=x] '
    	  '[--model_version=y] export_dir')
    	sys.exit(-1)
    if FLAGS.training_iteration <= 0:
    	print('Please specify a positive value for training iteration.')
    	sys.exit(-1)
    if FLAGS.model_version <= 0:
    	print('Please specify a positive value for version number.')
    	sys.exit(-1)
    # Hyperparameters
    learning_rate = 1e-3
    display_step = 1
    batch_size = 30
    hidden_layer_1 = 1
    # Construct Model
    sess = tf.InteractiveSession()
    x, train_x,test_x = input_data() # take data from linear_input_data, linear_input_data.input_data()
    train_X = numpy.asarray(train_x)
    test_X = numpy.asarray(test_x)
    train_Y = numpy.asarray(train_X)
    n_samples = train_X.shape[1]
    # tf Graph Input
    X = tf.placeholder(dtype='float32',shape=(None,n_samples),name="first_placeholder")
    Y = tf.placeholder(dtype='float32',shape=(None,1),name="second_placeholder")
    # Set model weights
    W = tf.Variable(tf.random_normal((n_samples,hidden_layer_1),stddev=0.01,dtype='float32'),name="weights")
    b = tf.Variable(tf.zeros((1,hidden_layer_1),dtype='float32'))
    # Construct a linear model
    prediction = tf.add(tf.matmul(X,W),tf.reduce_sum(b*W))
    # Gradient descent
    # Note, minimize() knows to modify W and b because Variable objects are trainable=True by default
    loss = tf.reduce_sum(tf.square(prediction-Y))
    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
    iteration = int(len(train_X)/batch_size)
    init = tf.global_variables_initializer()
    sess.run(tf.global_variables_initializer())
    for step in range(FLAGS.training_iteration-1):
        for epoch in range(iteration):
            batch_x1 = train_X[epoch:batch_size+epoch:]
            batch_y1 = train_X[epoch+1:batch_size+epoch+1:]
            sess.run(optimizer, feed_dict={X: batch_x1, Y: batch_y1})
            if (epoch+1) % display_step == 0:
                    cosst = sess.run(loss, feed_dict={X: batch_x1, Y:batch_y1}) # show information about cost, weights, bias every 50 steps
        training_cost = sess.run(loss, feed_dict={X: batch_x1, Y: batch_y1})
        print("Epoch=", step,"Training cost=", training_cost, "W=", sess.run(W), "b=", sess.run(b), '\n')
        predict = sess.run(prediction, feed_dict={X: batch_x1})
    # Test our model
    test_batch_x1 = test_X[:batch_size+1,:]
    test_batch_x = test_batch_x1.reshape(-1,1)
    test_batch_y1 = test_X[:batch_size+1,:]
    test_batch_y = test_batch_y1.reshape(-1,1)
    predict_test = sess.run(prediction, feed_dict={X: test_batch_x})
    print("prediction:",predict_test,"Real data:",test_batch_x)
    plt.plot(predict_test,color='green') # Predicted line
    plt.ylabel('Sin')
    plt.plot(test_batch_y,color='blue') # Test line
    plt.show()
    # Path to save model
    export_path_base = sys.argv[-1]
    export_path = os.path.join(
    tf.compat.as_bytes(export_path_base),
    tf.compat.as_bytes(str(FLAGS.model_version)))
    print('Exporting trained model to', export_path)
    builder = tf.saved_model.builder.SavedModelBuilder(export_path)
    # Build the signature_def_map.
    regression_inputs = tf.saved_model.utils.build_tensor_info(X) # Save first_placeholder to take prediction
    regression_outputs_prediction = tf.saved_model.utils.build_tensor_info(prediction) # Save predcition function
    regression_signature = (
    tf.saved_model.signature_def_utils.build_signature_def(
    inputs={
        tf.saved_model.signature_constants.REGRESS_INPUTS:regression_inputs
    },
    outputs={
        tf.saved_model.signature_constants.REGRESS_OUTPUTS:regression_outputs_prediction,
    },
    method_name=tf.saved_model.signature_constants.REGRESS_METHOD_NAME
    ))

    tensor_info_x = tf.saved_model.utils.build_tensor_info(X) # Save first_placeholder to take prediction
    tensor_info_y = tf.saved_model.utils.build_tensor_info(prediction) # Save cost function

    prediction_signature = (
    tf.saved_model.signature_def_utils.build_signature_def(
    inputs={'input_value':tensor_info_x},
    outputs={'output_value':tensor_info_y},
    method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))

    legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
    builder.add_meta_graph_and_variables(
    sess, [tf.saved_model.tag_constants.SERVING],
    signature_def_map={
        'predict_value':
            prediction_signature,
        tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
            regression_signature,
    },
    legacy_init_op = legacy_init_op)

    builder.save()
    print("Done exporting!")

if __name__ == '__main__':
    tf.app.run()


from enum import Enum
import os
import re
import subprocess
from typing import Callable, Optional

from lib.utils import popen_with_callback, remove_emojis, remove_successive_spaces, remove_control_characters

class SpeechModeEnum(str, Enum):
    """
    TTS のモード
    """
    NEURAL_JP = "neural-jp"
    CLASSIC_JP = "classic-jp"
    CLASSIC_EN = "classic-en"

def speak(
    text: str,
    mode: SpeechModeEnum,
    callback: Optional[Callable] = None
) -> None:
    """
    text を喋る．
    """
    this_directory = os.path.dirname(__file__)
    text = convert_text_for_speech(text)
    if mode is SpeechModeEnum.NEURAL_JP:
        # 日本語を綺麗に喋る
        text_for_tts = convert_text_for_speech(text)
        proc = subprocess.run(
            ["sh", "./tts.sh", text_for_tts],
            cwd=this_directory,
            stdout=subprocess.PIPE
        )
        path_to_audio_file = proc.stdout.decode("utf-8").strip()
        # 音声ファイルの再生開始（再生終了まで待たない．再生終了時に callback 実行）
        popen_with_callback(
            callback,
            ["mpg123", "-q", path_to_audio_file],
            cwd=this_directory
        )
    elif mode is SpeechModeEnum.CLASSIC_JP:
        # 日本語を雑に喋る
        text_for_tts = convert_text_for_speech(text)
        popen_with_callback(
            callback,
            ["say", "-v", "Kyoko", text_for_tts]
        )
    elif mode is SpeechModeEnum.CLASSIC_EN:
        # 英語を雑に喋る
        text_for_tts = convert_text_for_speech(text)
        popen_with_callback(
            callback,
            ["say", "-v", "Samantha", text_for_tts]
        )
    else:
        raise ValueError(f"Invalid mode: {mode}")

def convert_text_for_speech(text: str) -> str:
    """
    TTS に入力するために，テキストを最適化する
    """
    text = remove_control_characters(text)
    text = remove_emojis(text)
    text = remove_successive_spaces(text)
    # 空白の左側がひらがなカタカナ漢字である場合は，読点を挿入する
    text = re.sub(r"([ぁ-んァ-ン一-龥〜])\s", r"\1、", text)
    return text


#import bibliotek
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn import model_selection, preprocessing, linear_model, naive_bayes, metrics, svm
from sklearn import ensemble
import pickle

trainDF = pd.read_csv('indexing_bots.csv', sep='\t')

# podziel dane na zbiór treningowy i testowy
train_x, valid_x, train_y, valid_y = model_selection.train_test_split(trainDF['user_agent'], trainDF['is_indexing_bot'])

# zakoduj tekst na wektory numeryczne TF-IDF
tfidf_vect = TfidfVectorizer(analyzer='word', token_pattern=r'\w{1,}', max_features=5000)
tfidf_vect.fit(trainDF['user_agent'])
with open('project/tf_idf_vect.pickle', 'wb') as handle:
    pickle.dump(tfidf_vect, handle)
xtrain_tfidf =  tfidf_vect.transform(train_x)
xvalid_tfidf =  tfidf_vect.transform(valid_x)

# uniwersalna metoda do trenowania i ewaluacji modelu
def train_model(classifier, feature_vector_train, label, feature_vector_valid):
    # trenuj model
    classifier.fit(feature_vector_train, label)

    # generuj etykiety dla zbioru walidacyjnego
    predictions = classifier.predict(feature_vector_valid)

    # wyznacz metryki oceny modelu
    scores = list(metrics.precision_recall_fscore_support(predictions, valid_y))
    score_vals = [
        scores[0][0],
        scores[1][0],
        scores[2][0]
    ]
    score_vals.append(metrics.accuracy_score(predictions, valid_y))
    return classifier, score_vals

# MODEL - Lasy losowe
classifier, accuracy = train_model(ensemble.RandomForestClassifier(), xtrain_tfidf, train_y, xvalid_tfidf)
print ("RF: ", accuracy)

#export model
with open('project/model.pickle', 'wb') as handle:
    pickle.dump(classifier, handle)


"""
利用栈进行十进制到其他进制（二进制 ~ 十六进制）的转换
"""
from pythonds.basic.stack import Stack

def dem2base(value, base):
    flag = "0123456789ABCDEF"
    s = Stack()
    result = ""
    while value != 0:
        mod = flag[value % base]
        s.push(mod)
        value = value // base
    while not s.isEmpty():
        result += str(s.pop())
    return result

if __name__ == '__main__':
    print(dem2base(10, 2))
    print(dem2base(935, 16))


"""
3. В массиве случайных целых чисел поменять местами минимальный и максимальный элементы.
"""
import random

random_list = random.sample(range(0,1000), 5)
print(f'{"Массив случаных чисел":25} {random_list}')
index_max = index_min = 0
number_max = random_list[0]
number_min = random_list[0]

for index, number in enumerate(random_list):
    if(number > number_max):
        number_max = number
        index_max = index
    if(number < number_min):
        number_min = number
        index_min = index
random_list[index_min], random_list[index_max] = random_list[index_max], random_list[index_min]

print(f'{"Массив измененный":25} {random_list}\nЗамена местами максимального числа {number_max} и минимального числа {number_min}')


import RPi.GPIO as GPIO
import time

makerobo_TouchPin = 36   # 触摸传感器管脚PIN

makerobo_tmp = 0    #是否有触摸判断

def init():
    GPIO.setmode(GPIO.BOARD)       # 采用实际的物理管脚给GPIO口
    GPIO.setwarnings(False)        # 忽略GPIO操作注意警告
    GPIO.setup(makerobo_TouchPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)    # 设置makerobo_TouchPin管脚为输入模式，上拉至高电平(3.3V)

# 打印函数，显示出是否有触摸
def is_touch(x):
	global makerobo_tmp
	if x != makerobo_tmp:
		if x == 1:
			return True
		if x == 0:
			return False
		makerobo_tmp = x

if __name__ == '__main__':
    while True:
        cur = is_touch(GPIO.input(makerobo_TouchPin))
        if cur:
            print('1')
        else:
            print('0')
        time.sleep(1)


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

#======================================#
#=         PLANET CONDITIONS          =#
#======================================#

"""
    Выбирает случайное количество и случайные настройки для игры
    в соответствии с весовыми коэффициентами вероятностей.
    Для игры Dome Keeper.
"""

import random
from functools import reduce

# Количество случайных настроек
AMOUNTS = [
#   Количество             Вероятность
    (0,                    4),
    (1,                    4),
    (2,                    3),
    (3,                    2),
    (4,                    1),
]

# Настройки планеты
PLANET_CONDITIONS = [
#   Настройка              Вероятность
    ("Feeble enemies",     2),
    ("Long cycles",        6),
    ("Double iron",        1),
    ("Maze structure",     4),
]

"""
    Выбор элемента в соответствии с его весом.
"""
def weighted_choice(settings: list):
    total_weight = reduce(lambda a, b: a + b, [w for (s, w) in settings])
    r = random.random() * total_weight
    # Секции делят интервал (от 0 до Суммы весов) на отрезки для каждого элемента.
    # Проверяем в какую секцию попало случайное число r.
    choice = None
    section = 0
    for (s, w) in settings:
        section += w
        if r > section:
            # Попали в секцию для этого элемента.
            choice = s
            break
    return choice

# Unit test
def test_weighted_choice():
    stats = {0:0, 1:0, 2:0, 3:0, 4:0}
    test_range = 10_000
    for _ in range(test_range):
        choice = weighted_choice(AMOUNTS)
        stats[choice] += 1
    percented_stats = { key: f"{int(stats[key] / test_range * 100)}%" for key in stats.keys() }
    print(f"Probability distribution test results:\n{percented_stats}")

#===================== MAIN =====================

def main():
    print("=" * 16 + " Testing probabilities " + "=" * 16)
    test_weighted_choice()
    print()
    print("=" * 16 + " Detecting planet conditions " + "=" * 10)
    amount = weighted_choice(AMOUNTS)
    print(f"Amount of planet conditions: {amount}")
    result = []
    for _ in range(amount):
        while True:
            choice = weighted_choice(PLANET_CONDITIONS)
            if choice not in result:
                result.append(choice)
                break
    if amount == 0:
        print("No planet conditions.")
    else:
        print("\t+ " + "\n\t+ ".join(result))
    print()

#================================================

if __name__ == "__main__":
    main()


import os

from jalef.plots import plot_confusion_matrix
from .custom_callback import CustomCallback
from .store_validation_results import StoreValidationResults

class SaveConfusionMatrix(CustomCallback):
    def __init__(self, svr_instance: StoreValidationResults, title: str, save_freq: int=1):
        self._svr = svr_instance
        self._title = title

        if not (save_freq >= 1 and type(save_freq) is int):
            raise ValueError("Save frequency must be a positive integer!")

        self._save_freq = save_freq

        super().__init__()

    def init_training(self, log_dir_path):
        super().init_training(log_dir_path)

        self._log_dir_path = os.path.join(self._log_dir_path, "confusion_matrices")
        os.makedirs(self._log_dir_path)

    def on_epoch_end(self, epoch, logs=None):
        if epoch % self._save_freq == 0:
            y_true = self._svr.get_true_classes()
            y_pred = self._svr.get_predicted_classes()

            plot_confusion_matrix(y_true=y_true,
                                  y_pred=y_pred,
                                  title=self._title.format(epoch),
                                  show_fig=False,
                                  save_fig=True,
                                  filename=os.path.join(self._log_dir_path, "epoch_{}.png".format(epoch))
                                  )


import sys
import csv
import os

CLIENT_TABLE = 'C:/Users/JuanseDesktop/Documents/Courses/platzi_python_django/crud_creation_course/clients.csv'
CLIENT_SCHEMA = ['uid','name','company','email','position']
clients = []

def _initialize_clients():
    with open(CLIENT_TABLE, 'r') as file:
        reader = csv.DictReader(file, fieldnames=CLIENT_SCHEMA)

        for row in reader:
            clients.append(row)

def _save_clients_to_csv(clients):
    tmp_table_name = f'{CLIENT_TABLE}.tmp'
    with open(tmp_table_name, 'w') as f:
        writer = csv.DictWriter(f, CLIENT_SCHEMA)
        writer.writerows(clients)

        os.remove(CLIENT_TABLE)
    os.rename(tmp_table_name,CLIENT_TABLE)

def create_client(client):
    global clients
    if client not in clients:
        clients.append(client)
    else:
        print('Client already is in the client\'s list')

def update_client(client):
    global clients
    index = int(client['uid'])
    if 0 <= index and index <= len(clients)-1:
        clients[index] = client
    else:
        print('Client is not in client\'s list')

def search_client(index):
    global clients
    if 0 <= index and index <= len(clients)-1:
        return clients[index]['name']

def delete_client(index):
    global clients

    if 0 <= index and index <= len(clients)-1:
        clients.pop(index)
    else:
        print('Client is not in client\'s list')

def list_clients():
    global clients
    print(f'{CLIENT_SCHEMA[0]} | {CLIENT_SCHEMA[1]} | {CLIENT_SCHEMA[2]} | {CLIENT_SCHEMA[3]} | {CLIENT_SCHEMA[4]}')
    print('*'*50)
    for idx, client in enumerate(clients):
        print(f'{idx} | {client["name"]} | {client["company"]} | {client["email"]} | {client["position"]}')

def _get_property(property,updated = False):
    client_property = None
    while client_property is None:
        if updated:
             client_property = input(f'What is the updated client {property}? ')
        else:
            client_property = input(f'What is the client {property}? ')
        if client_property == 'exit':
            client_property = None
            break
        if property == 'uid':
            client_property = int(client_property)

    if client_property is None:
            sys.exit()

    return client_property

def _print_welcome():
    print('WELCOME TO PLATZI SALES')
    print('*'*50)
    print('What would you like to do today?')
    print('[C]reate client')
    print('[L]ist clients')
    print('[U]pdate client')
    print('[D]elete client')
    print('[S]earch client')

if __name__ == '__main__':
    _initialize_clients()
    _print_welcome()

    command = input()
    command = command.upper()

    if command == 'C':
        client = {
            'name': _get_property('name'),
            'company': _get_property('company'),
            'email': _get_property('email'),
            'position': _get_property('position')
        }
        create_client(client)
    elif command == 'L':
        list_clients()
    elif command == 'D':
        index = _get_property('uid')
        delete_client(index)
    elif command == 'U':
        client = {
            'uid' : _get_property('uid'),
            'name': _get_property('name',True),
            'company': _get_property('company',True),
            'email': _get_property('email',True),
            'position': _get_property('position',True)
        }
        update_client(client)
    elif command == 'S':
        index = _get_property('uid')
        found = search_client(index)
        if found:
            print('The client is in the client\'s list')
        else:
            print(f'The client with uid {index} is not in our client\'s list')
    else:
        print('Invalid command')
    _save_clients_to_csv(clients)


import pytest

from app.models.game.buildings import BuildingType
from app.models.game.technologies.technology_type import TechnologyType
from app.models.game.territory import ResourceType, Territory
from app.models.game.community.faction import Faction

class TestFactions:

    @pytest.mark.usefixtures("base_universe")
    @pytest.mark.usefixtures("authenticate_as_admin")
    def test_init_factions(self, client, session):
        """
        Test init factions
        ---
        :param client: http client
        :param session: db session
        """
        res = client.post('/api/galaxy/factions')
        assert res.status_code == 200
        assert len(res.json) == 3
        assert len(Faction.all(session=session)) == 3

    @pytest.mark.usefixtures("base_universe")
    @pytest.mark.usefixtures("authenticate_as_admin")
    def test_affect_user_faction(self, client, session):
        """
        Test affect faction to user
        :param client: http client
        :param session: db dession
        """
        res = client.post('/api/galaxy/factions')
        assert res.status_code == 200
        res = client.put('/api/faction/1')
        assert res.status_code == 204
        res = client.put('/api/faction/666')
        assert res.status_code == 400
        assert "Faction does not exist" == res.json["message"]
        res = client.put('/api/faction/1')
        assert res.status_code == 409
        assert "User already has a faction" == res.json["message"]

    @pytest.mark.usefixtures("base_universe")
    @pytest.mark.usefixtures("authenticate_as_user")
    @pytest.mark.parametrize("faction", (
        'Technocrats',
        'Warriors',
        'Merchants'
    ))
    def test_check_user_faction_apply_advantages(self, client, session, faction):
        """
        Test affect faction to user
        :param client: http client
        :param session: db dession
        """
        res = client.post('/api/galaxy/factions')
        assert res.status_code == 200
        id = next(f['id'] for f in res.json if f['name'] == faction)
        response = client.get(
            '/api/territories'
        )
        assert response.status_code == 200
        assert len(response.json) == 1
        assert response.json[0].get('id') is not None

        # Check starting resource and set level of building to 1
        territory = Territory.get(id=response.json[0]["id"])
        territory.add(type=BuildingType.power_station, amount=15)
        territory.add(type=BuildingType.mater_extractor, amount=5)
        territory.add(type=BuildingType.economical_center, amount=5)
        territory.add(type=BuildingType.rafinery, amount=5)
        for techno in territory.user.technologies:
            techno.increase(territory=territory, now=True)
        gain_without_faction = {
            ResourceType.mater: territory.get_hourly_gain(ResourceType.mater),
            ResourceType.credits: territory.get_hourly_gain(ResourceType.credits),
            ResourceType.tritium: territory.get_hourly_gain(ResourceType.tritium)
        }
        response = client.get(
            '/api/technologies'
        )
        assert response.status_code == 200
        assert len(response.json) == len(TechnologyType)
        tech_durations = {x['type']: x['duration'] for x in response.json}

        # Apply faction
        res = client.put(f'/api/faction/{id}')
        assert res.status_code == 204
        gain = {
            ResourceType.mater: territory.get_hourly_gain(ResourceType.mater),
            ResourceType.credits: territory.get_hourly_gain(ResourceType.credits),
            ResourceType.tritium: territory.get_hourly_gain(ResourceType.tritium)
        }
        response = client.get(
            '/api/technologies'
        )
        assert response.status_code == 200
        assert len(response.json) == len(TechnologyType)
        new_tech_durations = {x['type']: x['duration'] for x in response.json}
        # Test advantages
        if faction == 'Technocrats':
            resource_bonus = ResourceType.mater
            for tech, duration in tech_durations.items():
                assert new_tech_durations[tech] == duration - (10 / 100 * duration)
        if faction == 'Warriors':
            resource_bonus = ResourceType.tritium
            for tech, duration in tech_durations.items():
                assert new_tech_durations[tech] == duration
        if faction == 'Merchants':
            resource_bonus = ResourceType.credits
            for tech, duration in tech_durations.items():
                assert new_tech_durations[tech] == duration
        expected_gain = gain_without_faction.copy()
        expected_gain[resource_bonus] += expected_gain[resource_bonus] * 1 / 100
        assert gain == expected_gain

        response = client.get(
            '/api/technologies'
        )


from settings import *

MEDIA_ROOT = '/tmp/media'
DOCVIEWER_DOCUMENT_ROOT = join(MEDIA_ROOT, 'docs/')

DATABASES['default']['TEST_NAME'] = ':memory:'

STATICFILES_STORAGE = 'pipeline.storage.NonPackagingPipelineStorage'
PIPELINE_ENABLED = False

CELERY_EAGER_PROPAGATES_EXCEPTIONS=True
CELERY_ALWAYS_EAGER=True
BROKER_BACKEND='default'

#TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner'


import re
import csv

txt_file_path = 'MyFile.txt'
text_file = open(txt_file_path, "r")

uni = ""
sektor = ""
qrup = ""

for line in text_file:
    if len(line) > 0:
        print(line)

        ixtisas_id = ""
        ixtisas_eyani_or_qiyabi = ""
        ixtisas_adi = ""
        ixtisas_pullu_kechid_bali = ""
        ixtisas_pulsuz_kechid_bali = ""

        line = line.replace("\n", "").replace("\"", "")

        if line.startswith("[") and line.endswith("]") and line.count("[") == 1:
            uni = line.replace("[", "").replace("]", "")

        if line.__eq__("[[[AZ]]]"):
            sektor = "AZ"

        if line.__eq__("[[I]]"):
            qrup = "I"
        if line.__eq__("[[II]]"):
            qrup = "II"
        if line.__eq__("[[III]]"):
            qrup = "III"
        if line.__eq__("[[IV]]"):
            qrup = "IV"
        if line.__eq__("[[V]]"):
            qrup = "V"

        split_lines = line.split()

        ixtisas_adin_elave_elesin = False

        for string in split_lines:

            if len(string) == 1 and (string == "Ə" or string == "Q"):
                ixtisas_eyani_or_qiyabi = string
                ixtisas_adin_elave_elesin = False

            if ixtisas_adin_elave_elesin:
                ixtisas_adi = ixtisas_adi + " " + string

            if (len(string) == 6 and re.match(r'^([\s\d]+)$', string)) or \
                    (len(string) == 8 and re.match(r'^([\s\d]+)$', string.replace("*", ""))) or \
                    (len(string) == 7 and re.match(r'^([\s\d]+)$', string.replace("*", ""))):
                ixtisas_id = string
                ixtisas_adin_elave_elesin = True

            if (len(string) == 3 or len(string) == 2) and re.match(r'^([\s\d]+)$', string):
                ixtisas_pullu_kechid_bali = string

            if (len(string) == 5 or len(string) == 4) and string.startswith("(") and string.endswith(")"):
                ixtisas_pulsuz_kechid_bali = string.replace("(", "").replace(")", "")

            if len(string) == 1 and (string.__eq__("(") or string.__eq__("-") or string.__eq__(")")):
                ixtisas_pulsuz_kechid_bali = " - "

            if string.count("/") == 1 and not string.startswith("("):
                ixtisas_pullu_kechid_bali = string

            if string.count("/") == 1 and string.startswith("("):
                ixtisas_pulsuz_kechid_bali = string.replace("(", "").replace(")", "")

        if len(ixtisas_id) > 0:
            with open('data.csv', 'a+', newline='') as file:
                writer = csv.writer(file)
                writer.writerow(
                    [sektor, qrup, uni, ixtisas_id, ixtisas_adi, ixtisas_eyani_or_qiyabi, ixtisas_pullu_kechid_bali,
                     ixtisas_pulsuz_kechid_bali])


#!/usr/bin/env python

from __future__ import division,print_function
import sys

def getGraphKmerDict(inFile):
	graphKmerDict=dict()
	with open(inFile) as inFile:
		for line in inFile:
			if line:
				line=line.strip().split()
				kmer=line[0].upper()
				count=int(line[1])
				graphKmerDict[kmer]=count
	return graphKmerDict

def getReadKmerDict(inFile):
	readKmerDict=dict()
	with open(inFile) as inFile:
		for line in inFile:
			line=line.strip()
			if line and len(line.split())==2:
				line=line.split()
				kmer=line[0]
				count=int(line[1])
				readKmerDict[kmer]=count
	return readKmerDict

def main():
	graphKmerFile,readKmerFile=sys.argv[1:]
	graphKmerDict=getGraphKmerDict(graphKmerFile)
	readKmerDict=getReadKmerDict(readKmerFile)
	# if not all([len(kmer)==20 for kmer in graphKmerDict]):
	# 	print("Not all kmers in graph are length 20!")
	# if not all([len(kmer)==20 for kmer in readKmerDict]):
	# 	print("Not all kmers in reads are length 20!")
	totalReadKmers=sum(readKmerDict.itervalues())
	readKmersInGraph=sum([readKmerDict[read] for read in readKmerDict if read in graphKmerDict])
	print(readKmersInGraph,totalReadKmers)

if __name__=="__main__":
	main()


import torch
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torchvision.io import read_image
from torchvision.transforms import Resize
from glob import glob
import os
import numpy as np

class LescroartDataset(Dataset):
    def __init__(self, dataset_dir='../Lescroart.etal.2018/'):

        dirlist = glob(os.path.join(dataset_dir, 'stimuli_trn_*'))

        file_list = []
        for dir in dirlist:
            file_list.extend(glob(os.path.join(dir, 'fr*.png')))

        self.file_list = file_list

    def __len__(self):
        return len(self.file_list)

    def __getitem__(self, idx):
        file_name = self.file_list[idx]
        img1 = read_image(file_name)
        img1 = img1[0:3, :, :] # remove alpha channel

        ret = {'img1': img1, 'gt_segment': torch.randint(4, (1, 512, 512), dtype=torch.int64)}

        return ret

class BonnerDataset(Dataset):
    def __init__(self, dataset_dir='../stimuli/'):

        self.file_list = glob(os.path.join(dataset_dir, 'pathways*.jpg'))
        self.resize_op = Resize(size=(512, 512))

    def __len__(self):
        return len(self.file_list)

    def __getitem__(self, idx):
        file_name = self.file_list[idx]
        img1 = self.resize_op(read_image(file_name))

        ret = {'img1': img1,
               'gt_segment': torch.randint(4, (1, 512, 512), dtype=torch.int64)}

        return ret

def fetch_dataloader_lesc(args):

    dataset = LescroartDataset()

    dataloader = DataLoader(dataset,
                            batch_size=args.batch_size,
                            pin_memory=False,
                            shuffle=False)
    return dataloader

if __name__ == "__main__":
    pass